Logo Search packages:      
Sourcecode: mailody version File versions  Download package

mainwindow.cpp

/* This file is part of the KDE project

   Copyright (C) 2006-2007 KovoKs <info@kovoks.nl>
   Copyright (C) 2006-2007 Frode M. Døving <frode@lnix.net>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <sys/time.h>

#include <qlayout.h>
#include <qcursor.h>
#include <qsplitter.h>
#include <qtoolbutton.h>
#include <qtimer.h>
#include <qpopupmenu.h>
#include <qdragobject.h>
#include <qsimplerichtext.h>
#include <qvalidator.h>
#include <qobjectlist.h>

#include <kapplication.h>
#include <kconfig.h>
#include <kcmdlineargs.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kmdcodec.h>
#include <kfiledialog.h>
#include <kinputdialog.h>
#include <knotifydialog.h>
#include <knotifyclient.h>
#include <khtml_part.h>
#include <ksqueezedtextlabel.h>
#include <kstdaction.h>
#include <kstdaccel.h>
#include <kstatusbar.h>
#include <ktabwidget.h>
#include <klistview.h>
#include <klistviewsearchline.h>
#include <kactionclasses.h>
#include <kiconloader.h>
#include <kpopupmenu.h>
#include <ktoolbar.h>

#include "db.h"
#include "imapmanager.h"
#include "messagedata.h"
#include "headerlistview.h"
#include "mailboxlistview.h"
#include "messageview.h"
#include "mainwindow.h"
#include "setup.h"
#include "tooltip.h"
#include "global.h"
#include "dcopiface.h"
#include "composer.h"

namespace Mailody {

00073 MainWindow::MainWindow(   )
  : KMainWindow(0), m_idlePossible(false)
{
    // First do a check for settings. If not go to the settings dialog...
    KConfig* config = kapp->config();
    config->setGroup("General");
    if (config->readEntry("imapServer").isEmpty())
        startupSetup(); // do not refresh mb list now...

    // Convert old smtp settings to an identity
    config->setGroup("General");
    if (config->hasKey("smtpServer"))
        Global::convertOldSmtpToIdentities();

    QString hp = config->readEntry("homePage", "http://www.mailody.net");

    m_db = DB::dbinstance();
    m_imapmanager = new ImapManager(this,"imapanddb");
    m_imapmanager->startConnection();

    connect(m_imapmanager, SIGNAL(showSettings()), SLOT(slotSetup()));
    connect(m_imapmanager, SIGNAL(loginOk()), SLOT(slotCheckMail()));
    connect(m_imapmanager, SIGNAL(loginOk()), SLOT(slotStartCheckMailTimer()));
    connect(m_imapmanager, SIGNAL(loginOk()), SLOT(slotFillMailBoxList()));

    connect(m_imapmanager, SIGNAL(mailBoxList(const QStringList&)),
            SLOT(slotPopulateMailBoxList(const QStringList&)));
    connect(m_imapmanager, SIGNAL(mailBoxAdded(const QString&)),
            SLOT(slotAddMailBox(const QString&)));
    connect(m_imapmanager, SIGNAL(mailBoxDeleted(const QString&)),
            SLOT(slotDelMailBox(const QString&)));

    connect(m_imapmanager,
            SIGNAL(mailBox( const QString&, const QStringList& )),
            SLOT(slotPopulateHeaderList(const QString&, const QStringList& )));
    connect(m_imapmanager,
            SIGNAL(mailBoxAddition(const QString&, const QStringList&)),
            SLOT(slotAddHeaderList(const QString&, const QStringList&)));
    connect(m_imapmanager, SIGNAL(messageCount(const QString&, int)),
            SLOT(slotUpdateMessageCount(const QString&, int)));
    connect(m_imapmanager, SIGNAL(unseenCount(const QString&, int)),
            SLOT(slotUpdateUnseenMessageCount(const QString&, int)));

            // TODO:
    connect(m_imapmanager, SIGNAL(allUidsKnown(const QString&)),
            SLOT(slotAllMessages(const QString&)));
    connect(m_imapmanager, SIGNAL(status(const QString&)),
            SLOT(slotUpdateStatusBar(const QString&)));
    connect(m_imapmanager, SIGNAL(statusError(const QString&)),
            SLOT(slotUpdateStatusBarRestoreMouse(const QString&)));
    connect(m_imapmanager, SIGNAL(statusReady()),
            SLOT(slotClearStatusBar()));

    m_first = new QSplitter(this);

    m_mailboxList = new MailBoxListView(m_first);
    connect(m_mailboxList,
            SIGNAL(selectionChanged( QListViewItem* )),
            SLOT( slotSelectMailBox()));
    connect(m_mailboxList,
            SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint &)),
            SLOT(slotContextMenuMailbox(KListView*, QListViewItem*,
                 const QPoint &)));
    connect(m_mailboxList,
            SIGNAL(dropped(QDropEvent*, QListViewItem *)),
            SLOT(slotDropped(QDropEvent*)));

    m_nextUnreadAction = new KAction(   i18n("Next unread"), "next",
                                    Qt::Key_Space, this, SLOT(slotNextUnread()),
                                    actionCollection(),"next_unread");
    m_syncAction = new KAction(   i18n("Sync mailbox with server"), 0,
                                    this, SLOT(slotSyncMailBox()),
                                    actionCollection(),"sync_mailbox");
    m_expungeAction = new KAction(  i18n("Remove the deleted messages"),
                                     "remove", 0, this,
                                     SLOT(slotExpungeMailBox()),
                                     actionCollection(),"expunge_mailbox");
    m_selectAllAction = new KAction(i18n("Select all messages"), "select_all",
                                    KStdAccel::selectAll(), this,
                                    SLOT(slotSelectAllMessages()),
                                    actionCollection(),"select_all_msg");
    m_childSortAction = new KToggleAction(i18n("Sort on youngest child"),
                              0, 0, this,
                              SLOT(slotSortOnYoungestChild()),
                              actionCollection(), "sort_youngest_child");
    m_hideDeletedAction = new KToggleAction(i18n("Hide deleted messages"),
                              0, 0, this,
                              SLOT(slotHideDeleted()),
                              actionCollection(), "hide_deleted");

    m_second = new QSplitter(m_first);
    m_second->setOrientation(Qt::Vertical);

    QWidget* widg = new QWidget(m_second);
    QGridLayout* gbox = new QGridLayout(widg,0,0);

    m_headerList = new HeaderListView(widg);
    connect(m_headerList, SIGNAL(scrollDown()),
            SLOT( slotTabScrollDown()));
    connect(m_headerList, SIGNAL(scrollUp()),
            SLOT( slotTabScrollUp()));
    connect(m_headerList, SIGNAL(scrollPageDown()),
            SLOT( slotTabScrollPageDown()));
    connect(m_headerList, SIGNAL(scrollPageUp()),
            SLOT( slotTabScrollPageUp()));
    connect(m_headerList, SIGNAL(selectionChanged()),
            SLOT( slotShowMessage()));
    connect(m_headerList, SIGNAL(mouseButtonPressed( int, QListViewItem *,
                                  const QPoint&, int )),
            SLOT( slotMouseClickInHeaders( int, QListViewItem*, const QPoint& )));

    //------------------ Search line -----------------------------//
    // The searchlinewidget is not used as we can not relyablie
    // connect to a textChanged signal because creation is delayed

    KToolBar* searchBar = new KToolBar( widg, "searchbar");
    searchBar->setMovingEnabled( false );
    searchBar->boxLayout()->setSpacing( KDialog::spacingHint() );

    QToolButton* clearButton = new QToolButton(searchBar);
    QIconSet icon = SmallIconSet(
            QApplication::reverseLayout() ? "clear_left" : "locationbar_erase");
    clearButton->setIconSet(icon);
    clearButton->show();

    QLabel *label = new QLabel(i18n("S&earch:"), searchBar, "kde toolbar widget");

    m_searchLine = new KListViewSearchLine( searchBar, m_headerList );
    label->setBuddy(m_searchLine);

    connect(clearButton, SIGNAL(clicked()), this,
            SLOT(slotSearchLineClear()));
    connect(m_searchLine, SIGNAL(textChanged(const QString&)),
            SLOT(slotSearchLineChange(const QString&)));

    searchBar->setStretchableWidget( m_searchLine );

    gbox->addWidget(searchBar,0,0);
    gbox->addWidget(m_headerList,1,0);

    m_right = new QHBox( m_second );

    // ---------------- Tab Widget -------------------//

    m_tabWidget = new KTabWidget( m_right );
    m_tabWidget->setTabPosition( QTabWidget::Top );
    m_tabWidget->setTabReorderingEnabled( true );
    m_tabWidget->setAutomaticResizeTabs( true );
    m_tabWidget->setTabCloseActivatePrevious( true );

    QToolButton* button = new QToolButton( m_tabWidget );
    button->setIconSet( SmallIcon( "tab_new" ) );
    button->adjustSize();
    m_tabWidget->setCornerWidget( button, TopLeft );

    m_closeButton = new QToolButton(m_tabWidget);
    m_closeButton->setIconSet( SmallIcon("tab_remove") );
    m_closeButton->adjustSize();
    m_closeButton->setEnabled(false);
    m_tabWidget->setCornerWidget( m_closeButton, TopRight );

    connect(button, SIGNAL(clicked()), SLOT(slotNewTab()));
    connect(m_closeButton, SIGNAL(clicked()), SLOT(slotDeleteTab()));
    connect(m_tabWidget, SIGNAL(closeRequest(QWidget*)),
            SLOT(slotDeleteTab(QWidget*)));
    connect(m_tabWidget, SIGNAL(contextMenu(QWidget*, const QPoint &)),
            SLOT(slotContextMenuTab(QWidget*, const QPoint &)));
    connect(m_tabWidget, SIGNAL(currentChanged(QWidget*)),
            SLOT(slotCurrentTabChanged(QWidget*)));
    // add a ctrl-w....
    m_closeAction = new KAction( i18n("Close tab"), Qt::CTRL + Qt::Key_W,
                                  this, SLOT(slotDeleteTab()),
                                  actionCollection(),"close_tab");
    kapp->config()->setGroup("General");
    if (kapp->config()->readBoolEntry("AutoHideTabBar"))
        m_tabWidget->setTabBarHidden(true);

    // Dont load the favorite website yet, first setup all the actions.
    m_tabWidget->show();

    // ------------------ Load settings ----------------------//

    kapp->config()->setGroup("MainWindowSplitterSize");
    QValueList<int> defaultsize1 = config->readIntListEntry("vsplitter");
    if (!defaultsize1.count())
    {
        defaultsize1.append(170);
        defaultsize1.append(460);
    }

    QValueList<int> defaultsize2 = config->readIntListEntry("hsplitter");
    if (!defaultsize2.count())
    {
        defaultsize2.append(280);
        defaultsize2.append(691);
    }

    m_first->setSizes(defaultsize1);
    m_second->setSizes(defaultsize2);

    m_headerList->restoreLayout(config,"MainWindowHeaderListSize");
    m_mailboxList->restoreLayout(config,"MainWindowMailboxListSize");

    // -------------------- Create actions --------------------//

    KStdAction::quit(this, SLOT(slotQuit()), actionCollection(),
                     "app_exit");
    m_msgSaveAction = KStdAction::saveAs(this, SLOT(slotSave()),
                                       actionCollection(), "msg_save");
    m_msgPrintAction = KStdAction::print(this, SLOT(slotPrint()),
                                       actionCollection(), "msg_print");
    m_msgZoomInAction = KStdAction::zoomIn(this, SLOT(slotZoomIn()),
                                           actionCollection(), "msg_zoom_in");
    m_msgZoomOutAction  = KStdAction::zoomOut(this, SLOT(slotZoomOut()),
                                              actionCollection(),
                                              "msg_zoom_out");
    KStdAction::preferences(this, SLOT(slotSetup()), actionCollection());
    KStdAction::configureNotifications(this, SLOT(slotNotifications()),
                                       actionCollection());

    new KAction(i18n("Sync mailbox list"), 0, this,
                SLOT(slotSyncMailBoxList()),
                actionCollection(), "sync_mblist");
    new KAction(i18n("Check for Mail Now"), "mail_get",
                Qt::CTRL + Qt::Key_L , this,
                SLOT(slotCheckMail()),
                actionCollection(), "check_mail");

    m_plainTextAction = new KToggleAction( i18n( "Show as Text" ), "text",
                                          Qt::Key_F10, this,
                                          SLOT(slotToggleHTML()),
                                          actionCollection(), "toggle_html" );
    m_sourceAction = new KToggleAction( i18n( "Show source" ), "text_block",
                                         Qt::Key_V, this,
                                         SLOT(slotToggleSource()),
                                         actionCollection(), "toggle_source" );
    m_fixedfontAction = new KToggleAction( i18n( "Use fixed font" ),
                                         Qt::Key_X, this,
                                         SLOT(slotToggleFixedFont()),
                                         actionCollection(), "toggle_fixedfont" );
    m_externalImageAction = new KToggleAction( i18n( "Load external images" ),
                                         0, this,
                                         SLOT(slotToggleExternalImage()),
                                         actionCollection(),
                                         "toggle_externalimage" );
    m_msgDelAction = new KToggleAction( i18n("Message deleted"),
                                   "mail_delete", Qt::Key_Delete, this,
                                   SLOT(slotToggleDelete()),
                                   actionCollection(),"delete_message");
    /*m_relatedAction = new KToggleAction( i18n("What's related"),
                                   0, Qt::Key_W, this,
                                   SLOT(slotIsolateItem()),
                                   actionCollection(),"related_message");*/
    m_msgNewAction = KStdAction::openNew( this, SLOT( slotNewMessage() ),
                         actionCollection(), "compose_new_message" );
    m_msgNewAction->setIcon("mail_new3");
    m_msgNewAction->setEnabled( true );

    m_msgNewActionMenu = new KActionMenu( i18n( "New message to" ),
                                    "compose_new_message",
                                    actionCollection(),
                                    "compose_new_messageMenu" );
    m_msgNewActionMenu->setIcon("mail_new3");
    m_msgNewActionMenu->setEnabled( true );

    connect(m_msgNewActionMenu, SIGNAL(activated()),
            SLOT(slotNewMessage()));
    connect(m_msgNewActionMenu->popupMenu(), SIGNAL(aboutToShow()),
            SLOT(slotNewMessageMenu()));
    connect(m_msgNewActionMenu->popupMenu(), SIGNAL(activated(int)),
            SLOT(slotNewMessageMenuSelected(int)));

    m_msgReplyAction = new KAction( i18n( "Reply to message" ), "mail_replyall",
                                   Qt::CTRL + Qt::Key_R, this,
                                   SLOT(slotReplyMessage()),
                                   actionCollection(), "reply_message" );

    m_msgReEditAction = new KAction( i18n( "Re-Edit Message" ), "edit",
                                    Qt::CTRL + Qt::Key_T, this,
                                    SLOT(slotReEditMessage()),
                                    actionCollection(), "reedit_message" );

    m_msgForwardAction = new KAction( i18n( "Forward this message" ),
                                      "mail_forward",
                                   Qt::CTRL + Qt::Key_F, this,
                                   SLOT(slotForwardMessage()),
                                   actionCollection(), "forward_message" );
    m_msgForwardActionMenu = new KActionMenu( i18n( "Forward this message to" ),
                                   "mail_forward",
                                   actionCollection(), "forward_messageMenu" );
    connect(m_msgForwardActionMenu, SIGNAL(activated()),
            SLOT(slotForwardMessage()));
    connect(m_msgForwardActionMenu->popupMenu(), SIGNAL(aboutToShow()),
            SLOT(slotForwardMessageMenu()));
    connect(m_msgForwardActionMenu->popupMenu(), SIGNAL(activated(int)),
            SLOT(slotForwardMessageMenuSelected(int)));

    m_msgUser0Action = new KAction( i18n("No Label"),
                                     Qt::Key_0, this,
                                     SLOT(slotUser0()),
                                     actionCollection(),"tag_0");
    m_msgUser1Action = new KAction( i18n("Label &1"),"label1",
                                     Qt::Key_1, this,
                                     SLOT(slotUser1()),
                                     actionCollection(),"tag_1");
    m_msgUser2Action = new KAction( i18n("Label &2"),"label2",
                                     Qt::Key_2, this,
                                     SLOT(slotUser2()),
                                     actionCollection(),"tag_2");
    m_msgUser3Action = new KAction( i18n("Label &3"),"label3",
                                     Qt::Key_3, this,
                                     SLOT(slotUser3()),
                                     actionCollection(),"tag_3");
    m_msgUser4Action = new KAction( i18n("Label &4"),"label4",
                                     Qt::Key_4, this,
                                     SLOT(slotUser4()),
                                     actionCollection(),"tag_4");
    m_msgUser5Action = new KAction( i18n("Label &5"),"label5",
                                     Qt::Key_5, this,
                                     SLOT(slotUser5()),
                                     actionCollection(),"tag_5");

    // -------- set the actions according to the settings ----------//

    //this also calls setActionStates();
    slotOpenURLInNewTab( hp );

    kapp->config()->setGroup("ToggleStates");
    m_plainTextAction->setChecked(
            kapp->config()->readBoolEntry("plaintext", true));
    m_sourceAction->setChecked(
            kapp->config()->readBoolEntry("source", false));
    m_fixedfontAction->setChecked(
            kapp->config()->readBoolEntry("fixed", false));
    m_externalImageAction->setChecked(
            kapp->config()->readBoolEntry("externalimage", false));

    m_childSortAction->setChecked(
            kapp->config()->readBoolEntry("sort_youngest", false));
    m_hideDeletedAction->setChecked(
            kapp->config()->readBoolEntry("hide_deleted", false));
    slotHideDeleted();
    slotToggleHTML();

    m_first->show();
    setCentralWidget(m_first);
    setupGUI(Keys | StatusBar | ToolBar | Create | Save);
    setMinimumSize(QSize(900,750));
    setAutoSaveSettings("MainWindow", true);

    // -------------- statusbar ------------------------------------//

    m_statusText = new KSqueezedTextLabel(this);
    m_statusText->setFrameStyle( QFrame::NoFrame );
    m_statusText->setMargin(1);
    m_statusText->setText(i18n("Ready"));
    statusBar()->addWidget(m_statusText,10);
    statusBar()->setItemAlignment(1,Qt::AlignLeft);
    statusBar()->insertItem(i18n("Plain"),2,1);
    statusBar()->insertItem(i18n("Short for no ext. images",
                             "No ext."), 3, 1);
    connect(statusBar(), SIGNAL(pressed(int)),
        SLOT(slotStatusBarClicked(int)));

    m_statusTimer = new QTimer(this);
    connect(m_statusTimer, SIGNAL(timeout()), SLOT(slotStatusBarReady()));

    // -----------------prep Tooltip and checkmail timer ------------//

    m_tooltip = new ToolTip(this,"notification");
    connect(m_tooltip, SIGNAL(leftClicked(const QString&)),
            SLOT(slotSelectMB(const QString&)));

    // This is the mailcheck timer.
    m_checkMailTimer = new QTimer(this);
    connect(m_checkMailTimer, SIGNAL(timeout()), SLOT(slotCheckMail()));

    // Commandline stuff - for now only catch mailto: thingies, so I can
    // use mailody as default mua. It also assumes an INBOX.
    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    if (args)
    {
        for(int i=0; i < args->count(); i++)
        {
            QString argument = args->arg(i);
            if (argument.startsWith("mailto:"))
                slotOpenComposer(argument);
        }
    }

    DCOPIface* dcopIface = new DCOPIface(this, "actions");
    connect( dcopIface, SIGNAL( signalMailTo( const QString& ) ),
             SLOT( slotOpenComposer( const QString& ) ) );
    connect( dcopIface, SIGNAL( signalCompose( const QString&, const QString& ) ),
             SLOT( slotOpenComposer( const QString&, const QString& ) ) );
}

00470 MainWindow::~MainWindow()
{
    kapp->config()->setGroup("MainWindowSplitterSize");
    kapp->config()->writeEntry("vsplitter", m_first->sizes());
    kapp->config()->writeEntry("hsplitter", m_second->sizes());

    m_headerList->saveLayout(kapp->config(),"MainWindowHeaderListSize");
    m_mailboxList->saveLayout(kapp->config(),"MainWindowMailboxListSize");

    kapp->config()->setGroup("ToggleStates");
    kapp->config()->writeEntry("plaintext", m_plainTextAction->isChecked());
    kapp->config()->writeEntry("source", m_sourceAction->isChecked());
    kapp->config()->writeEntry("fixed", m_fixedfontAction->isChecked());
    kapp->config()->writeEntry("externalimage",
                               m_externalImageAction->isChecked());
    kapp->config()->writeEntry("sort_youngest", m_childSortAction->isChecked());
    kapp->config()->writeEntry("hide_deleted", m_hideDeletedAction->isChecked());

    kapp->config()->sync();

    delete m_db;
    delete m_imapmanager;
}

bool MainWindow::queryClose()
{
    // We want to know if there are dirty composers. If that is the case,
    // dont close the mainwindow.

    // example taken from /kopete/protocols/groupwise/gwcontactlist.cpp
    const QObjectList * l = children();
    if ( l && !l->isEmpty() )
    {
        QObjectListIt it( *l );
        QObject *obj;
        while ( (obj = it.current()) != 0 )
        {
            if (obj->isA("Mailody::Composer"))
            {
                Composer* c = static_cast<Composer*>(obj);
                if (!c->canClose())
                    return false;
            }
            ++it;
        }
    }
    return true;
}

void MainWindow::slotOpenComposer(const QString& address,
                                  const QString& files,
                                  const QString& mb)
{
    Composer* composer = new Composer(this, mb);

    // emails
    QStringList addrList = QStringList::split(",", address);
    for(QStringList::Iterator it = addrList.begin();
        it != addrList.end();
        ++it)
    {
        QString a = *it;
        if (a.startsWith("mailto:"))
            a.mid(7);
        a.replace("%40","@");

    // kdDebug() << "Composer requested: " << a << endl;
    if(!a.isEmpty())
        composer->setRcpt(a, Composer::To);
    }

    // attachments
    QStringList fileList =  QStringList::split(";;", files);
    for(QStringList::Iterator it = fileList.begin();
        it != fileList.end();
        ++it)
    {
        KURL url = KURL(*it);
        if((url).isValid())
            composer->addAttachment(url);
    }
    composer->setMsg(QString::null);
    composer->show();
}

void MainWindow::slotSyncMailBoxList()
{
    m_imapmanager->getMailBoxList( true /* not from cache */);
}

void MainWindow::slotFillMailBoxList()
{
    m_imapmanager->getMailBoxList( false /* from cache */);
}

void MainWindow::slotPopulateMailBoxList(const QStringList& list)
{
    kdDebug() << k_funcinfo << endl;

    m_mailboxList->clear();
    m_mailboxMap.clear();

    QStringList::ConstIterator it = list.begin();
    while (it != list.end())
    {
        const QString name = *it;
        ++it;
        const QString amount = *it;
        ++it;

        if (name.isEmpty())
            continue;
        else
            slotAddMailBox(name);

        slotUpdateMessageCount(name, (*it).toInt());
    }
}

void MainWindow::slotDelMailBox(const QString& box)
{
    MailBoxListViewItem* item = m_mailboxMap[box];
    if (!item)
        return;

    // Delete the childeren.
    QListViewItem* myChild = item->firstChild();
    while ( myChild )
    {
        QString child = static_cast<MailBoxListViewItem*>(myChild)->fullName();
        myChild = myChild->nextSibling();
        slotDelMailBox(child);
    }

    m_mailboxMap.erase(box);
    delete item;
}

void MainWindow::slotAddMailBox(const QString& box)
{
    // Know which need the checkmail bit.
    // TODO: not very efficient here...
    QStringList checkMail = m_db->getCheckMailBoxList();

    QString visualName, completeName;
    MailBoxListViewItem* previousItem=0;

    char sep = '.';
    if (box.find("/") != -1)
            sep = '/';

    // We have to work our way through the sections of the path,
    // because it is not sure we receive foo before foo.bar, so in
    // any case we need to create foo first.
    QStringList sections = QStringList::split(sep, box);
    bool remapped = false;
    for (uint i = 0; i < sections.count(); i++)
    {
        // this is the name we are going to add....
        visualName = sections[i];

        // Keep track of the complete path
        i == 0 ? completeName = visualName
            : completeName += sep + visualName;

        // Now we have the completename set, check if this is a INBOX
        // item, so we ignore that, this means a better layout for courier
        // users.
        if (i == 0 && sections.count() > 1 && visualName == "INBOX")
        {
            remapped = true;
            continue;
        }

        // See if this path has been made before.
        QMap<QString,MailBoxListViewItem*>::Iterator findBase;
        findBase = m_mailboxMap.find(completeName);

        // handle the root item differently.
        if (i == 0 || (i == 1 && remapped))
        {
            // if the path does not exist create it, if it exists
            // save the pointer, for the next part of the path
            if (findBase.key().isEmpty())
            {
                bool check = checkMail.findIndex(completeName) != -1;
                MailBoxListViewItem* storeItem =
                        new MailBoxListViewItem(m_mailboxList, visualName,
                                                completeName, check);
                m_mailboxMap[completeName] = storeItem;
                previousItem = storeItem;
            }
            else
                previousItem = findBase.data();
        }
        else
        {
            if (findBase.key().isEmpty())
            {
                bool check = checkMail.findIndex(completeName) != -1;
                MailBoxListViewItem* storeItem =
                        new MailBoxListViewItem(previousItem, visualName,
                                                completeName, check );
                m_mailboxMap[completeName] = storeItem;
                previousItem = storeItem;
            }
            else
                previousItem = findBase.data();
        }
    }
}

void MainWindow::slotPopulateHeaderList(const QString& mailbox,
                                       const QStringList& values)
{
    // kdDebug() << k_funcinfo << mailbox
    //         << " msg: " << values.count() << endl;

    MailBoxListViewItem* mbi =
            static_cast<MailBoxListViewItem*>(m_mailboxList->currentItem());
    if (!mbi || !mbi->isSelected() || !m_mailboxMap[mailbox]->isSelected())
        return;

    slotAddHeaderList(mailbox,values);
}

void MainWindow::slotAddHeaderList(const QString& mailbox,
                                  const QStringList& values)
{
    // kdDebug() << k_funcinfo << mailbox
    //        << " msg: " << values.count() << endl;

    MailBoxListViewItem* mbi =
            static_cast<MailBoxListViewItem*>(m_mailboxList->currentItem());
    if ( !mbi || !mbi->isSelected() || !m_mailboxMap[mailbox] ||
         !m_mailboxMap[mailbox]->isSelected())
        return;

    // workaround to get the statusbar updated.
    slotUpdateStatusBar(i18n("Opening %1").arg(mailbox));
    m_addheaderlist_val = values;

    QTimer::singleShot(10, this, SLOT(slotAddHeaderList_process()));
}

void MainWindow::slotAddHeaderList_process( int level )
{
    // kdDebug() << k_funcinfo << endl;

    const QStringList values = m_addheaderlist_val;

    bool sort_on_child = m_childSortAction->isChecked();
    QDateTime currentTime = QDateTime::currentDateTime();

    //struct timeval tv1, tv2;
    //gettimeofday(&tv1, 0);

    QStringList::ConstIterator it = values.begin();
    while (it != values.end())
    {
        const int uid = (*it).toInt();
        ++it;

        const QString mb = *it;
        ++it;

        const QString headers = *it;
        ++it;

        const QString flags = *it;
        ++it;

        HeaderListViewItem* exists = m_headerMap[qMakePair(mb,uid)];
        if (!exists)
        {
            MessageData* r = new MessageData(this, "message", uid, mb, headers);

            HeaderListViewItem* threadTo = m_threadMap[r->inreplyto()];
            if (!threadTo || r->inreplyto().isEmpty())
                exists = new HeaderListViewItem(m_headerList, r);
            else
            {
                exists = new HeaderListViewItem(threadTo, r);

                while (threadTo)
                {
                    // if this is a new item, make the parents open....
                    if (flags.find("\\Seen") == -1)
                        threadTo->setOpen( true );

                    // set the sorting to the childs date
                    if (sort_on_child  && r->sortDate() <= currentTime &&
                        threadTo->msg()->sortDate() < r->sortDate())
                        threadTo->msg()->setSortDate(r->sortDate());

                    threadTo = (HeaderListViewItem*)threadTo->parent();
                }
            }
            exists->setLevel(level);
            m_threadMap[r->messageID()] = exists;
            m_headerMap[qMakePair(mb,uid)] = exists;
        }
    }

    //gettimeofday(&tv2, 0);
    //Global::timing("filling", tv1, tv2);

    // since the parents might have new sortdates, we need a resort.
    //gettimeofday(&tv1, 0);
    if (sort_on_child)
        m_headerList->sort();
    //gettimeofday(&tv2, 0);
    //Global::timing("sorting", tv1, tv2);

    // hide the deleted;
    if (m_hideDeletedAction->isChecked())
        slotHideDeleted();

    // scroll down as long as we do not store the last selected mail.
    if (!m_headerList->selectedItems().count() &&
         m_headerList->sortOrder() == Qt::Ascending)
        QTimer::singleShot(200, this, SLOT(slotScrollBottom()));

    searchLineUpdate();
    slotClearStatusBar();
    m_addheaderlist_val.clear();
}

QString MainWindow::retrieveMailboxName(QListViewItem* item)
{
    QString mailbox;
    QMap<QString,MailBoxListViewItem*>::Iterator ita;
    for (ita = m_mailboxMap.begin(); ita != m_mailboxMap.end(); ++ita)
    {
        if (ita.data() == item )
            mailbox = ita.key();
    }
    return mailbox;
}

void MainWindow::slotExpungeMailBox()
{
    QListViewItem* item = m_mailboxList->currentItem();
    //kdDebug() << "slotExpungeMailBox:" << item->text(0) << endl;

    m_imapmanager->expungeMailBox( retrieveMailboxName(item) );
}

void MainWindow::slotSelectMailBox( bool clear )
{
    QListViewItem* item = m_mailboxList->currentItem();
    // kdDebug() << "slotCheckMailBox:" << item->text(0) << endl;
    m_tooltip->addToBlockList( ((MailBoxListViewItem*)item)->fullName() );

    // clear the message part.
    if (clear)
    {
        TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
        if (i)
            i->clearView();
        slotUpdateTabTitle(i18n("Message"));
    }

    // clear the headers part.
    m_headerMap.clear();
    m_threadMap.clear();
    m_headerList->clear();
    setActionStates();

    m_imapmanager->getMailBox( retrieveMailboxName(item), false /* cache */ );
    m_imapmanager->checkMail( retrieveMailboxName(item) ); // unseen count
}

void MainWindow::slotSyncMailBox()
{
    QListViewItem* item = m_mailboxList->currentItem();
    m_imapmanager->getMailBox( retrieveMailboxName(item),true /* no cache */);
}

void MainWindow::slotNextUnread()
{
    // so, this goes in three stages:
    // a) if message shown, scroll down to end of the message
    // b) go to next unread in that box
    // c) go to next folder with unread messages, go to b.

    // ---- a ---

    MailBoxListViewItem* mbi =
            static_cast<MailBoxListViewItem*>(m_mailboxList->currentItem());
    TotalView* tb = 0;

    // Only when a mailbox is selected (hp case)
    if (mbi)
        tb = static_cast<TotalView*>(m_tabWidget->currentPage());

    if (tb)
    {
        QScrollView* i = static_cast<QScrollView *>(tb->body()->widget());
        if ((i->contentsY()+i->visibleHeight()) < i->contentsHeight())
        {
            i->scrollBy(0, (int)(0.85*i->height()));
            return;
        }
    }

    // ----- b ----

    HeaderListViewItem* next = 0;

    // Only when this folder contains unread messages
    if (mbi && mbi->getUnseen() > 0)
        next = m_headerList->nextUnread();

    if (next)
    {
        m_headerList->blockSignals(true);
        m_headerList->clearSelection();
        m_headerList->blockSignals(false);
        m_headerList->ensureItemVisible(next);
        m_headerList->setCurrentItem(next);
        m_headerList->setSelected(next, true);
        m_headerList->setSelectionAnchor(next);
        m_headerList->center(0, next->itemPos());
        return;
    }

    // ---- c -----
    MailBoxListViewItem* mbnext = m_mailboxList->nextWithUnread();
    if (mbnext)
    {
        m_mailboxList->blockSignals(true);
        m_mailboxList->clearSelection();
        m_mailboxList->blockSignals(false);
        m_mailboxList->ensureItemVisible(mbnext);
        m_mailboxList->setCurrentItem(mbnext);
        m_mailboxList->setSelected(mbnext, true);
        m_mailboxList->setSelectionAnchor(mbnext);
        m_mailboxList->center(0, mbnext->itemPos());

        QTimer::singleShot(200, this, SLOT(slotNextUnread()));
    }
}

//---------------------- message --------------------------------//

bool MainWindow::addTag( const QString& tag)
{
    bool done = false;
    QListViewItem *item;
    QListViewItemIterator it( m_headerList, QListViewItemIterator::Selected  );
    while ( it.current() )
    {
        item = it.current();
        done = true;
        addTag((HeaderListViewItem*)item, tag);
        ++it;
    }
    return done;
}

void MainWindow::addTag(HeaderListViewItem* item, const QString& tag,
                        bool forceChilds)
{
    MessageData *r = item->msg();
    //kdDebug() << r->subject() << tag
    //        << m_db->hasFlag(r->uid(), r->mb(), tag) << endl;
    if (!m_db->hasFlag(r->uid(), r->mb(), tag))
    {
        m_imapmanager->addFlag(r->mb(), r->uid(), tag);
        m_headerList->repaintItem(item);
    }

    // See if the item has childeren and do the same for them if the thread is
    // open
    if (!item->isOpen() || forceChilds)
    {
        QListViewItem * myChild = item->firstChild();
        while ( myChild )
        {
            addTag((HeaderListViewItem*)myChild, tag, true);
            myChild = myChild->nextSibling();
        }
    }
}

bool MainWindow::removeTag( const QString& tag)
{
    bool done = false;
    QListViewItem *item;
    QListViewItemIterator it( m_headerList, QListViewItemIterator::Selected );
    while ( it.current() )
    {
        item = it.current();
        done = true;
        removeTag((HeaderListViewItem*)item, tag);
        ++it;
    }

    return done;
}

void MainWindow::removeTag(HeaderListViewItem* item, const QString& tag,
                          bool forceChilds)
{
    MessageData *r = item->msg();
    // kdDebug() << "remove tag; has " << tag
    //        << m_db->hasFlag(r->uid(), r->mb(), tag) << endl;
    if (m_db->hasFlag(r->uid(), r->mb(), tag))
    {
        m_imapmanager->removeFlag(r->mb(), r->uid(), tag);
        m_headerList->repaintItem(item);
    }

    // See if the item has childeren and do the same for them if the thread is
    // open
    if (!item->isOpen() || forceChilds)
    {
        QListViewItem * myChild = item->firstChild();
        while ( myChild )
        {
            removeTag((HeaderListViewItem*)myChild, tag, true);
            myChild = myChild->nextSibling();
        }
    }
}

bool MainWindow::moveMessage(const QString& destBox)
{
    bool done = false;
    m_db->beginTransaction();
    QListViewItem *item;
    QListViewItemIterator it( m_headerList, QListViewItemIterator::Selected  );
    while ( it.current() )
    {
        item = it.current();
        done = true;
        // Move to trashfolder, unless we already are in there.
        HeaderListViewItem* hlv = (HeaderListViewItem*)item;
        if (hlv->msg()->mb() != destBox)
            moveMessage(hlv, destBox);
        else
            addTag(hlv, "\\Deleted");

        ++it;
    }
    m_db->commitTransaction();
    m_headerList->triggerUpdate();

    // kdDebug() << destBox << m_db->getTotalMessagesMessages(destBox) << endl;

    // We don't do a checkMail as that is a serious drain, only good for
    // an updated message count, we can do that on another way: trust the db.
    // m_imapmanager->checkMail(destBox);
    slotUpdateMessageCount( destBox, m_db->getTotalMessagesMailbox(destBox));

    // If you are deleting a bunch, updating the headerlist every time is a
    // bit to much, just delay it a bit.
    if (m_hideDeletedAction->isChecked())
        QTimer::singleShot(500, this, SLOT(slotHideDeleted()));

    return done;
}

void MainWindow::moveMessage(HeaderListViewItem* item, const QString& destBox,
                             bool forceChilds )
{
    MessageData *r = item->msg();
    m_imapmanager->moveMessage(r->mb(), r->uid(), destBox);

    // See if the item has childeren and do the same for them if the thread is
    // open
    if (!item->isOpen() || forceChilds)
    {
        QListViewItem * myChild = item->firstChild();
        while ( myChild )
        {
            moveMessage((HeaderListViewItem*)myChild, destBox, true);
            myChild = myChild->nextSibling();
        }
    }
}

void MainWindow::setUserTag(int t)
{
//    kdDebug() << "set " << t << endl;
    // remove all existing UserTags....
    // Looks like a performance drain, but i do not think it will be used
    // on thousand messages at a time...
    for (int i = 1; i < 6 ; ++i)
        removeTag( "$Label" + QString::number(i) );

    if (t > 0)
        addTag( "$Label" + QString::number(t) );
}

void MainWindow::slotToggleDelete()
{
    if (!m_msgDelAction->isChecked())
    {
        removeTag( "\\Deleted" );
    }
    else
    {
        // As deleted items get removed, save the unselected item below first.
        QListViewItem* lvibelow = m_headerList->currentItem()->itemBelow();
        while (lvibelow != 0 && lvibelow->isSelected())
            lvibelow = lvibelow->itemBelow();

        int amountDeleted = 0;

        // if there is a folder marked as trash box, we move instead of delete
        QString destBox = m_db->getSetting("trashfolder");
        if (!destBox.isEmpty())
            amountDeleted = moveMessage( destBox );
        else
            amountDeleted = addTag( "\\Deleted" );

        // hide deleted...
        if (m_hideDeletedAction->isChecked())
            slotHideDeleted();

        // clear the view.
        TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
        if (i)
            i->clearView();
        slotUpdateTabTitle(i18n("Message"));

        if ( lvibelow && (amountDeleted == 1 ||
             m_headerList->selectedItems( false ).count() == 0))
        {
            m_headerList->setSelected(m_headerList->currentItem(), false);
            m_headerList->setSelected(lvibelow, true);
            m_headerList->setSelectionAnchor(lvibelow);
            m_headerList->ensureItemVisible(lvibelow);
            m_headerList->setCurrentItem(lvibelow );

            // try to let other items be visible as well...
            m_headerList->center(0, lvibelow->itemPos());
            slotShowMessage();
        }
    }
}

void MainWindow::slotUser0()
{
    // REMOVE all tags...
    setUserTag(0);
}

void MainWindow::slotUser1()
{
    setUserTag(1);
}

void MainWindow::slotUser2()
{
    setUserTag(2);
}

void MainWindow::slotUser3()
{
    setUserTag(3);
}

void MainWindow::slotUser4()
{
    setUserTag(4);
}

void MainWindow::slotUser5()
{
    setUserTag(5);
}

void MainWindow::slotToggleHTML()
{
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    i->body()->setHTML( !m_plainTextAction->isChecked() );
    m_fixedfontAction->setEnabled( m_plainTextAction->isChecked() );
    m_externalImageAction->setEnabled( !m_plainTextAction->isChecked() );
    setStatusBarStates();
}

void MainWindow::slotToggleSource()
{
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    m_sourceAction->isChecked() ? i->body()->setViewSource()
        :i->body()->setHTML( !m_plainTextAction->isChecked() );
    m_plainTextAction->setEnabled( !m_sourceAction->isChecked() );
}

void MainWindow::slotToggleFixedFont()
{
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    i->body()->setFixedFont( m_fixedfontAction->isChecked() );
}

void MainWindow::slotToggleExternalImage()
{
    TotalView* tv = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (m_externalImageAction->isChecked())
    {
        int i = KMessageBox::warningContinueCancel(this,
                   i18n("Loading external images gives spammers the "
                       "acknowdledgement that you received this message "
                       "so they will use your email address to spam you. "
                       "So you should only continue for very trusted messages."),
                                                  QString::null,
                                                  KStdGuiItem::cont(),
                                                  "IKnowRisksOfExternalImages");
        if (i == KMessageBox::Continue)
            tv->body()->setExternalImage( true );
    }
    else
        tv->body()->setExternalImage( false );

    setStatusBarStates();
}

void MainWindow::slotShowMessage()
{
    showMessage();
}

void MainWindow::slotMouseClickInHeaders( int button, QListViewItem* item,
                                         const QPoint& pos)
{
    if (button == Qt::RightButton)
    {
        contextMenuHeaders(item, pos);
        return;
    }
    else if (button == Qt::MidButton)
        slotNewTab();

    if (button == Qt::MidButton)
        showMessage();

    // Yes, we eat the LeftButtpn. The slotShowMessage() will be called
    // when the selection changes. This will trigger the view of the message
    // so there is no need to deal with it here.
}

void MainWindow::showMessage()
{
    HeaderListViewItem *headerItem =
            static_cast<HeaderListViewItem*>(m_headerList->currentItem());

    if (!headerItem)
        return;

    TotalView* tv = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (tv)
    {
        // Disable loading of external images.
        m_externalImageAction->setChecked(false);
        tv->body()->setExternalImage( false, false /*do not redraw old msg*/ );
        tv->setMsg(headerItem->msg());
        m_tabWidget->setTabLabel( tv, headerItem->msg()->sender() );
        setActionStates();
    }
}

void MainWindow::slotSelectAllMessages()
{
    QListViewItemIterator it( m_headerList, QListViewItemIterator::Visible );
    while ( it.current() ) {
        it.current()->setSelected(true);
        ++it;
    }
    m_headerList->triggerUpdate();
}

void MainWindow::slotSortOnYoungestChild()
{
    slotSelectMailBox();
}

void MainWindow::slotHideDeleted()
{
    m_headerList->setHideDeleted(m_hideDeletedAction->isChecked());
}

void MainWindow::slotAllMessages(const QString& mb)
{
    MailBoxListViewItem* mbi =
            static_cast<MailBoxListViewItem*>(m_mailboxList->currentItem());
    if (!mbi || mbi->fullName() != mb)
        return;

    QStringList all;
    m_db->getCurrentMessageIDs(mbi->fullName(), all);

    // Rework this, makes the search faster.
    QMap<QPair<QString,int>, bool> allnum;
    QStringList::iterator it = all.begin();
    while(it != all.end())
    {
        allnum[qMakePair(mb,(*it).toInt())] = true;
        ++it;
    }

    // Now we know all uids, we can remove the items from the list
    // which are no longer in that mailbox.
    QMap< QPair<QString,int>, HeaderListViewItem*>::Iterator ita;
    QValueList< QPair<QString,int> > deleted;
    for (ita = m_headerMap.begin(); ita != m_headerMap.end(); ++ita)
        if (allnum[ita.key()] == false)
            deleted.append(ita.key());

    // we know what to delete...
    QValueList< QPair<QString,int> >::Iterator ita2=deleted.begin();
    while (ita2 != deleted.end())
    {
        HeaderListViewItem* tmp = m_headerMap[(*ita2)];
        if (tmp)
        {
            //before we delete the item, move the childeren
            //fir now to the top level..
            while (tmp->childCount() > 0)
            {
                QListViewItem * myChild = tmp->firstChild();
                tmp->takeItem( myChild );
                m_headerList->insertItem( myChild );
            }

            // No we can delete...
            m_headerMap.remove((*ita2));
            m_threadMap.remove(tmp->msg()->messageID());
            delete tmp;
        }
        ++ita2;
    }

    // scroll down as long as we do not store the last selected mail.
    if (!m_headerList->selectedItems().count())
        m_headerList->ensureItemVisible( m_headerList->lastItem());

    // Update the search..
    m_searchLine->updateSearch();

    setActionStates();
}

//---------------------- mailbox --------------------------------//
void MainWindow::slotUpdateMessageCount(const QString& mailbox, int messages)
{
    if (!mailbox)
        return;

    //kdDebug() << "updating msg " << mailbox << ": " << messages << endl;

    MailBoxListViewItem* mb = m_mailboxMap[mailbox];
    if (!mb)
    {
        kdWarning() << "Request for mailbox which is not there: "
                << mailbox << endl;
        return;
    }

    mb->setMessages(messages);

    // if this has children, update the total column
    if (mb->firstChild() != 0)
        calculateChildMessageCount(mb, messages);

    // if it has parents then update the count for the parent.
    QListViewItem* parent = mb->parent();
    while (parent)
    {
        MailBoxListViewItem* p = static_cast<MailBoxListViewItem*>(parent);
        calculateChildMessageCount(p, p->getMessages());
        parent = p->parent();
    }
}

void MainWindow::slotUpdateUnseenMessageCount(const QString& mailbox,
                                       int messages)
{
    if (!mailbox)
        return;

    //kdDebug() << "updating unseen " << mailbox << ": " << messages << endl;

    MailBoxListViewItem* mb = m_mailboxMap[mailbox];
    if (!mb)
    {
        kdWarning() << "Request for mailbox which is not there: "
                << mailbox << endl;
        return;
    }

    if (messages > 0 && mb->getUnseen() < messages )
    {
        QString link = "<a href=\"" + mb->fullName()
            + "\">" + mb->visName() + "</a>";
        QString t = "<nobr>" + i18n("You now have one unread message in %1",
                         "You now have %n unread messages in %1",
                         messages).arg(link) + "</nobr>";

        if (KNotifyClient::getPresentation("newmail") &
            KNotifyClient::PassivePopup)
            m_tooltip->setText(mb->fullName(), t);
        else
            KNotifyClient::event(winId(), "newmail", t);
    }

    // keep this behind previous call ;-)
    mb->updateUnseen(messages);

}

void MainWindow::calculateChildMessageCount(MailBoxListViewItem* mailbox,
                                           int offset)
{
    //kdDebug() << "updating childeren " << mailbox << ": " << offset << endl;

    int total = offset;
    MailBoxListViewItem* myChild =
            static_cast<MailBoxListViewItem*>(mailbox->firstChild());
    while( myChild )
    {
        total += QMAX(myChild->getMessages(), myChild->getTotalMessages());
        myChild = static_cast<MailBoxListViewItem*>(myChild->nextSibling());
    }

    mailbox->setTotalMessages(total);
}

//------------------------ Tabs --------------------------------//
void MainWindow::slotNewTab()
{
    TotalView* widget = new TotalView( m_tabWidget);
    m_tabWidget->insertTab( widget, i18n("Message") );

    int i = m_tabWidget->indexOf(widget);
    m_tabWidget->setCurrentPage(i);

    if (m_tabWidget->count() > 1)
    {
        m_closeButton->setEnabled(true);
        m_tabWidget->setTabBarHidden(false);
    }
    widget->body()->setHTML( !m_plainTextAction->isChecked() );
    if (m_sourceAction->isChecked())
        widget->body()->setViewSource();
    widget->body()->setFixedFont( m_fixedfontAction->isChecked() );
    widget->body()->setExternalImage( m_externalImageAction->isChecked() );

    connect(widget->body(), SIGNAL(onURL(const QString&)),
        SLOT(slotSimpleMessageStatusBar(const QString&)));
    connect(widget->body(), SIGNAL(openInTab(const QString&)),
        SLOT(slotOpenURLInNewTab(const QString&)));
    connect(widget->body(), SIGNAL(openComposer(
                const QString&,const QString&,const QString&)),
        SLOT(slotOpenComposer(
                const QString&,const QString&,const QString&)));
    connect(widget->body(), SIGNAL(pageTitle(const QString&)),
        SLOT(slotUpdateTabTitle(const QString&)));
    connect(widget->headers(),
            SIGNAL(openComposer(
                const QString&,const QString&,const QString&)),
            SLOT(slotOpenComposer(
                const QString&,const QString&,const QString&)));

}

void MainWindow::slotDeleteTab()
{
    slotDeleteTab( m_tabWidget->currentPage() );

    if (m_tabWidget->count() == 1)
        {
            m_closeButton->setEnabled(false);
            kapp->config()->setGroup("General");
            if(kapp->config()->readBoolEntry("AutoHideTabBar"))
                m_tabWidget->setTabBarHidden(true);
        }
}

void MainWindow::slotDeleteTab(QWidget* tb)
{
    // so there is a timing problem. before deleting the tab, it will
    // emit a signal that the tab has changed. That slot will try to
    // clear the view, but it gets deleted at the same time.
    // Block the signal for now.


    // if not the last one, delete it.
    m_tabWidget->blockSignals(true);
    if (m_tabWidget->count() != 1)
        delete tb;
    m_tabWidget->blockSignals(false);

    // now that is done, find the current message again.
    slotCurrentTabChanged( m_tabWidget->currentPage() );
}

void MainWindow::slotCurrentTabChanged(QWidget* i)
{

    TotalView* tb = static_cast<TotalView*>(i);

    if (tb->msg())
    {
        // slotSelectMB will trigger the slotSelectMailbox which will
        // clear the view, we dont want that.
        m_mailboxList->blockSignals(true);
        slotSelectMB(tb->msg()->mb());
        m_mailboxList->blockSignals(false);

        // we call it ourselfes.
        slotSelectMailBox( false /* no clear */);

        m_plainTextAction->setChecked( !tb->body()->html() );
        m_sourceAction->setChecked( tb->body()->source() );
        m_fixedfontAction->setChecked( tb->body()->fixedfont() );
        m_externalImageAction->setChecked( tb->body()->externalImage() );

        // We have to delay this untill the headerlist is loaded.
        QTimer::singleShot(200, this, SLOT(slotSelectMessage()));
    }
    else
        setActionStates();
}

void MainWindow::slotSelectMB( const QString& mb )
{
        QListViewItem* lvi = m_mailboxMap[mb];
        if (!lvi || lvi == m_mailboxList->currentItem())
            return;

        m_mailboxList->setSelected(m_headerList->currentItem(), false);
        m_mailboxList->setSelected( lvi, true);
        m_mailboxList->setSelectionAnchor( lvi );
        m_mailboxList->ensureItemVisible( lvi );
        m_mailboxList->setCurrentItem( lvi );
}

void MainWindow::slotTabScrollUp()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    static_cast<QScrollView *>(tb->body()->widget())->scrollBy(0, -10);

}

void MainWindow::slotTabScrollDown()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    static_cast<QScrollView *>(tb->body()->widget())->scrollBy(0, 10);
}

void MainWindow::slotTabScrollPageUp()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    QScrollView* i = static_cast<QScrollView *>(tb->body()->widget());
    i->scrollBy(0, -(int)(0.85*i->height()));
}

void MainWindow::slotTabScrollPageDown()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    QScrollView* i = static_cast<QScrollView *>(tb->body()->widget());
    i->scrollBy(0, (int)(0.85*i->height()));
}


//---------------------- Menus ---------------------------------//

void MainWindow::slotContextMenuTab(QWidget*, const QPoint &point)
{
    if (m_tabWidget->count() != 1)
    {
        QPopupMenu* p = new QPopupMenu(this);
        m_closeAction->plug(p);
        p->popup(point);
    }
}

void MainWindow::contextMenuHeaders( QListViewItem* lvi, const QPoint &point)
{
    HeaderListViewItem* header = static_cast<HeaderListViewItem*>(lvi);

    if (!header)
        return;

    QPopupMenu* p = new QPopupMenu(this);

    m_msgReplyAction->plug(p);
    m_msgForwardAction->plug(p);
    m_msgReEditAction->plug(p);
    m_msgDelAction->plug(p);
    //m_relatedAction->plug(p);
    p->insertSeparator();
    m_msgUser0Action->plug(p);
    m_msgUser1Action->plug(p);
    m_msgUser2Action->plug(p);
    m_msgUser3Action->plug(p);
    m_msgUser4Action->plug(p);
    m_msgUser5Action->plug(p);
    p->popup(point);
}

void MainWindow::slotContextMenuMailbox(KListView*, QListViewItem* lvi,
                                       const QPoint &point)
{
    MailBoxListViewItem* mb = static_cast<MailBoxListViewItem*>(lvi);


    QPopupMenu* p = new QPopupMenu(this);
    int markasread=-2;
    int renamefolder=-2;
    int deletefolder=-2;
    int check=-2;
    int trashfolder=-2;
    if (mb)
    {
        markasread = p->insertItem(i18n("Mark all as read"));
        m_syncAction->plug(p); // Sync mailbox with server
        m_expungeAction->plug(p); // Remove the deleted messages
        p->insertSeparator(); // separator
    }
    int newfolder = p->insertItem(i18n("Create new folder"));
    if (mb)
    {
        if (mb->childCount() == 0 && mb->visName().lower() != "inbox")
        {
            renamefolder = p->insertItem(i18n("Rename folder"));
            deletefolder = p->insertItem(i18n("Delete folder"));
        }
        p->insertSeparator(); // separator
        check = p->insertItem(i18n("Check for new mail"));
        trashfolder = p->insertItem(i18n("Mark as trash folder"));

        p->setItemChecked(check, mb->check());
        p->setItemChecked(trashfolder,
                          m_db->getSetting("trashfolder") == mb->fullName());

    }
    int choice = p->exec(point);

    if (choice == check)
    {
        mb->setCheck(!mb->check());
        m_db->setCheckMailMailbox(mb->fullName(), mb->check());
    }
    else if (choice == trashfolder)
    {
        if (m_db->getSetting("trashfolder") == mb->fullName())
            m_db->setSetting("trashfolder", QString::null);
        else
            m_db->setSetting("trashfolder", mb->fullName());
    }
    else if (choice == markasread)
    {
        m_imapmanager->addFlag(mb->fullName(), "\\Seen");
        m_headerList->triggerUpdate();
        mb->updateUnseen(0);
    }
    else if (choice == newfolder)
    {
        // kdDebug() << " NEW " << endl;

        QRegExp rx( "[^"+ QRegExp::escape("%*./\\'\"`+~")+"]+");
        QRegExpValidator* v = new QRegExpValidator( rx, this );
        bool ok;
        QString folderName =
                KInputDialog::getText( i18n("Folder Name"),
                           i18n("Please provide the name of the folder to "
                                "create. Please dont use dots or slashes "),
                           QString::null, &ok, this, "FolderName", v,
                           QString::null);

        if (ok)
        {
            if (mb)
            {
                // we want a child, find out the seperator.
                char sep = '.';
                if (mb->fullName().find("/") != -1)
                    sep = '/';
                folderName = mb->fullName() + sep + folderName;
            }
            // kdDebug() << ok << folderName << endl;
            m_imapmanager->createMailBox(folderName);
        }
    }
    else if (choice == renamefolder)
    {
        // kdDebug() << " Rename " << endl;

        QRegExp rx( "[^"+ QRegExp::escape("%*./\\'\"`+~")+"]+");
        QRegExpValidator* v = new QRegExpValidator( rx, this );
        bool ok;
        QString folderName =
                KInputDialog::getText( i18n("Folder Name"),
                           i18n("Please provide the name of the folder to "
                                "create. Please dont use dots or slashes "),
                           mb->visName(), &ok, this, "FolderName", v,
                           QString::null);

        if (ok)
        {
            char sep = '.';
            if (mb->fullName().find("/") != -1)
                sep = '/';

            // if it's a toplevel folder, it is ok now, else create a new
            // full folder name
            QString choppedFolderName = mb->fullName().section(sep,0,-2);
            if (!choppedFolderName.isEmpty())
                folderName =  choppedFolderName + sep + folderName;

            // kdDebug() << ok << folderName << endl;
            m_imapmanager->renameMailBox(mb->fullName(), folderName);
        }
    }
    else if (choice == deletefolder)
    {
        // kdDebug() << " Delete " << endl;
        int amount = m_db->getTotalMessagesMailbox(mb->fullName());
        if (amount > 0)
        {
            int i = KMessageBox::warningContinueCancel(this,
                    i18n("This folder contains one message, it will be "
                         "deleted, are you sure?",
                        "This folder contains %n messages, they will be "
                         "deleted, are you sure?", amount),
                    i18n("Folder has content"));

            if (i != KMessageBox::Continue)
                return;
        }
        m_imapmanager->deleteMailBox(mb->fullName());
    }
}

void MainWindow::slotDropped(QDropEvent *e)
{
    // Do not use a dropped signal which emits the klistviewitem,
    // these seem to return a previous item sometimes. hence we
    // calculate the item ourselfes.

    // kdDebug() <<  "Slot dropped! " << endl;
    MailBoxListViewItem* i = (MailBoxListViewItem*)m_mailboxList->itemAt(
            m_mailboxList->contentsToViewport(e->pos()));

    if (!i)
        return;

    QString destbox = i->fullName();

    QString text;
    QTextDrag::decode( e, text );
    QStringList movable = QStringList::split("\n", text);
    QStringList::Iterator it = movable.begin();
    QMap<QString, bool> origBoxesUsed;
    while (it != movable.end())
    {
        QString uid = *it;
        ++it;

        QString origbox = *it;

        // We should not accept drops for these, but I do not understand how
        // to do that...
        if (destbox == origbox)
        {
            kdDebug() << "No, you do not want that, do you?" << endl;
            ++it;
            continue;
        }

        m_imapmanager->moveMessage(origbox, uid.toInt(), destbox);
        origBoxesUsed[origbox] = true;
        ++it;
    }

    QMapIterator<QString,bool> ita = origBoxesUsed.begin();
    for (; ita != origBoxesUsed.end(); ++ita)
        m_imapmanager->checkMail(ita.key());
    m_imapmanager->checkMail(destbox);

    if (m_hideDeletedAction->isChecked())
        QTimer::singleShot(500, this, SLOT(slotHideDeleted()));

    m_headerList->triggerUpdate();
}

//------------------------- Setup & Quit --------------------------//

void MainWindow::slotSetup()
{
    Setup setup(0,"Setup");
    if (setup.exec() != QDialog::Accepted)
        return;

    // stop the timer and start it again when there is no new connection
    // made
    m_checkMailTimer->stop();
    m_imapmanager->startConnection();
    slotStartCheckMailTimer();

    if (m_mailboxList->childCount() == 0)
        slotSyncMailBoxList();
}

void MainWindow::slotNewMessage(const QString& to)
{
    MailBoxListViewItem* mbi =
            static_cast<MailBoxListViewItem*>(m_mailboxList->currentItem());

    QString box;
    if (!mbi)
        box = "INBOX";
    else
        box = mbi->fullName();

    Composer* composer = new Composer(this, box);
    if (!to.isEmpty())
        composer->setRcpt(to, Composer::To);

    QString empty = QString::null;
    composer->setMsg(empty);
    composer->show();
}

void MainWindow::slotNewMessageMenu()
{
    messageMenu(m_msgNewActionMenu);
}

void MainWindow::slotNewMessageMenuSelected(int i)
{
    slotNewMessage(m_recentList[i].remove('&'));
}

void MainWindow::slotReplyMessage()
{
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!i)
        return;

    MessageData *msg = i->msg();

    Composer* composer = new Composer(this, msg->mb());
    if (!msg->replyTo().isEmpty())
    {
        if (!Global::myEmail(msg->replyTo()))
            composer->setRcpt(msg->replyTo(), Composer::To);
    }
    else
    {
        if (!Global::myEmail(msg->sender()))
            composer->setRcpt(msg->sender_full(false /* no company*/),
                              Composer::To);
    }

    QStringList* list = msg->to_list();
    if (list)
    {
        QStringList::Iterator it=list->begin();
        for(; it!=list->end(); ++it)
            if (!Global::myEmail((*it)))
                composer->setRcpt((*it), Composer::To);
            else
                composer->setIdentity(Global::getIdentityForEmail(*it));
    }

    list  = msg->cc_list();
    if (list)
    {
        QStringList::Iterator it=list->begin();
        for(; it!=list->end(); ++it)
            if (!Global::myEmail((*it)))
                composer->setRcpt((*it), Composer::Cc);
            else
                composer->setIdentity(Global::getIdentityForEmail(*it));
    }

    composer->inReplyTo(msg->messageID());

    if (msg->subject().startsWith("Re:", false))
        composer->setSubject(msg->subject());
    else
        composer->setSubject("Re: " + msg->subject());

    QString toQuote;
    if (i->body()->hasSelection())
        toQuote = i->body()->selectedText();
    else
        toQuote = msg->raw();

    QString text = i18n("At %1, you wrote:\n")
        .arg(KGlobal::locale()->formatDateTime(msg->date(), false))
        + quote( toQuote ) + "\n";
    composer->setMsg(text);
    composer->show();
}

void MainWindow::slotForwardMessage(const QString& to)
{
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!i)
        return;

    MessageData *msg = i->msg();
    Composer* composer = new Composer(this, msg->mb());
    composer->setSubject("Fwd: " + msg->subject());

    QString toQuote;
    if (i->body()->hasSelection())
        toQuote = i->body()->selectedText();
    else
        toQuote = msg->raw();

    QString text = i18n("At %1, %2 wrote:\n")
            .arg(KGlobal::locale()->formatDateTime(msg->date(), false),
                 msg->sender_full( false /* no company */))
            + quote( toQuote, false /*leave sig in there*/ ) + "\n";
    composer->setMsg(text);

    if (!to.isEmpty())
        composer->setRcpt(to, Composer::To);

    // try to find the right identitiy to forward with...
    QStringList* list = msg->to_list();
    if (list)
    {
        QStringList::Iterator it=list->begin();
        for(; it!=list->end(); ++it)
            if (Global::myEmail((*it)))
                composer->setIdentity(Global::getIdentityForEmail(*it));
    }

    list  = msg->cc_list();
    if (list)
    {
        QStringList::Iterator it=list->begin();
        for(; it!=list->end(); ++it)
            if (Global::myEmail((*it)))
                composer->setIdentity(Global::getIdentityForEmail(*it));
    }

    // set the attachments...
    QMap<QString,QString> list2 = msg->attachments();
    QMap<QString,QString>::Iterator ita;
    for (ita = list2.begin(); ita != list2.end(); ++ita)
        composer->addAttachment(KURL(ita.key()), ita.data());
    composer->show();
}

void MainWindow::slotForwardMessageMenu()
{
    messageMenu(m_msgForwardActionMenu);
}

void MainWindow::slotReEditMessage(const QString& to)
{
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!i)
        return;

    MessageData *msg = i->msg();
    Composer* composer = new Composer(this, msg->mb());
    composer->setSubject(msg->subject());
    composer->inReplyTo(msg->inreplyto());

    QString id = Global::getIdentityForEmail(msg->sender_email());
    if (!id.isNull())
    {
        KConfig* config = kapp->config();
        config->setGroup("identity_" + id);
        composer->setIdentity(id);

        QString m = msg->raw();
        if(config->readBoolEntry("sigEnabled", false) &&
            m.contains(config->readEntry("signature")))
        {
            QString s = config->readEntry("signature");
            composer->setOldSig(s);
            composer->setNewPos(config->readNumEntry("sigPos"));
        }
    }
// look for mailody headers.
    else
    {
    // signature
        QString xms;
        QString xmstmp = msg->getXMS();

        if (!xmstmp.isNull())
        {
            xms = QString::fromUtf8(KCodecs::base64Decode(xmstmp.utf8()));
            kdDebug() << "read-xms: " << xms <<endl;
            composer->setOldSig(xms);
        }

        // position
        kdDebug() << "read-xmsp: " << msg->getXMSP() <<endl;
        composer->setNewPos(msg->getXMSP());
    }
// end backup plan


    QString t;
    if (i->body()->hasSelection())
        t = i->body()->selectedText();
    else
    {
        t = msg->raw();
    }
    composer->setMsg(t, false);

    if (!to.isEmpty())
        composer->setRcpt(to, Composer::To);
    else
        composer->setRcpt(msg->to(), Composer::To);

    QMap<QString,QString> list2 = msg->attachments();
    QMap<QString,QString>::Iterator ita;
    for (ita = list2.begin(); ita != list2.end(); ++ita)
        composer->addAttachment(KURL(ita.key()),ita.data());

    const QString flg = "\\Deleted";
    m_imapmanager->addFlag(msg->mb(), msg->uid(), flg);
    composer->setDirty();
    composer->show();
}

void MainWindow::messageMenu(KActionMenu* am)
{
    am->popupMenu()->clear();
    m_recentList.clear();

    // add them from the current message.
    TotalView* i = static_cast<TotalView*>(m_tabWidget->currentPage());
    QStringList values;
    bool sep = false;
    if (i && i->msg() && i->headers()->isVisible())
    {
        MessageData *msg = i->msg();

        if (!msg->replyTo().isEmpty())
        {
            values.append(msg->replyTo());
            values.append(msg->replyTo());
            sep = true;
        }

        if (!msg->sender())
        {
            values.append(msg->sender());
            values.append(msg->sender_email());
            sep = true;
        }

        QStringList* list = msg->to_list();
        if (!list->isEmpty())
        {
            QStringList::Iterator it=list->begin();
            for(; it!=list->end(); ++it)
            {
                values.append(*it);
                values.append(*it);
                sep = true;
            }
        }

        list  = msg->cc_list();
        if (!list->isEmpty())
        {
            QStringList::Iterator it=list->begin();
            for(; it!=list->end(); ++it)
            {
                values.append(*it);
                values.append(*it);
                sep = true;
            }
        }
    }

    // add top 10
    QStringList values2;
    m_db->getTopTenRecentList(values2);

    if (sep && values.count() > 0)
    {
        values.append("-");
        values.append("-");
    }

    QStringList::iterator it = values2.begin();
    while(it != values2.end())
    {
        QString name = (*it);
        ++it;
        QString email = (*it);
        ++it;

        if (values.findIndex(email) == -1)
        {
            values.append(name);
            values.append(email);
        }
    }

    // make the menu
    it = values.begin();
    while(it != values.end())
    {
        QString name = (*it);
        ++it;
        QString email = (*it);
        ++it;

        if (name.isEmpty())
            name = email;

        int i;
        if (name == "-")
            i = am->popupMenu()->insertSeparator();
        else
            i = am->popupMenu()->insertItem(name);

        m_recentList[i] = email;
    }

    // still nothing???
    if (values.isEmpty())
    {
        // change after messagefreeze
        int i = am->popupMenu()->insertItem(i18n("None"));
        am->popupMenu()->setItemEnabled(i, false);
    }
}

void MainWindow::slotForwardMessageMenuSelected(int i)
{
    slotForwardMessage(m_recentList[i].remove('&'));
}

void MainWindow::slotSelectMessage()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());

    HeaderListViewItem* hi =
            m_headerMap[qMakePair(tb->msg()->mb(),tb->msg()->uid())];

    if (!hi)
    {
        kdDebug() << k_funcinfo << tb->msg()->uid() << tb->msg()->mb() << endl;
        kdDebug() << "Eiks, not found" << endl;
        return;
    }

    // We do not want to emit signals, just select the item...
    m_headerList->blockSignals(true);
    m_headerList->setSelected(m_headerList->currentItem(), false);
    m_headerList->setSelected(hi, true);
    m_headerList->setSelectionAnchor( hi );
    m_headerList->ensureItemVisible( hi );
    m_headerList->setCurrentItem( hi );
    m_headerList->blockSignals(false);

    setActionStates();
}

QString MainWindow::quote(const QString& text, bool stripSig)
{
    // We only quote untill we match a "-- ". After that the code will buffer
    // the rest. If after the "-- " a ^> is matched, then the code is added
    // again. This should quote a complete message, with a reply and sig at top.
    bool includeMore = false;
    QString result, extraResult;
    QStringList list1 = QStringList::split("\n", text, true);
    QStringList::Iterator it;

    // Maybe not very fast, but pretty stable and straightforward, non?
    for (it = list1.begin(); it != list1.end(); it++)
    {
        QString single = *it;
        while (single.length() > 80)
        {
            QString piece = single.mid(0,80);
            int amount = 0;

            // find the space, dot and comma.
            int dot = piece.findRev(".");
            int comma = piece.findRev(",");
            int space = piece.findRev(" ");
            amount = QMAX(dot,comma);
            amount = QMAX(amount, space);

            // if no dot, comma or space is found, wrap hard.
            if (amount < 1)
                amount = 80;

            includeMore ? extraResult += "> " + single.mid(0,amount) + "\n"
                : result += "> " + single.mid(0,amount) + "\n";

            single = single.mid(amount+1);
        }

        if (stripSig && single == "-- ")
            includeMore = true;

        if (includeMore && single.startsWith(">"))
        {
            includeMore = false;
            result += extraResult;
        }

        includeMore ? extraResult += "> " + single + "\n"
                :  result += "> " + single + "\n";
    }
    return result;
}

void MainWindow::startupSetup()
{
    Setup setup(0,"Setup");
    if (setup.exec() != QDialog::Accepted)
        return;
}

void MainWindow::slotNotifications()
{
    KNotifyDialog::configure(this);
}

void MainWindow::slotSave()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    kdDebug() << ":save" << tb->msg()->subject() << endl;
    QString filename = KFileDialog::getSaveFileName( tb->msg()->subject(),
            "*.eml|Email File\n*.txt|Text File", this, i18n("Save as..."));
    tb->save( filename );
}

void MainWindow::slotPrint()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    tb->print();
}

void MainWindow::slotZoomIn()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    tb->body()->setZoomFactor(tb->body()->zoomFactor()+10);
}


void MainWindow::slotZoomOut()
{
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    if (!tb)
        return;
    tb->body()->setZoomFactor(tb->body()->zoomFactor()-10);
}

void MainWindow::slotCheckMail()
{
    QStringList checkMail = m_db->getCheckMailBoxList();
    QStringList::Iterator it = checkMail.begin();
    while (it != checkMail.end())
    {
        m_imapmanager->checkMail(*it);
        ++it;
    }
}

void MainWindow::slotStartCheckMailTimer()
{
    kapp->config()->setGroup("General");
    int ci = kapp->config()->readNumEntry("checkInt",1);
    if (ci > 0)
        m_checkMailTimer->start( 60000 * ci, false);
}

void MainWindow::setActionStates()
{
    // Determine if a message is shown...
    bool message = false;
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());

    HeaderListViewItem* hi = 0;
    if (tb->msg())
        hi = m_headerMap[qMakePair(tb->msg()->mb(),tb->msg()->uid())];

    if (tb && hi)
        message = true;

    // Enable the actions.
    m_plainTextAction->setEnabled( message );
    m_fixedfontAction->setEnabled( message );
    m_externalImageAction->setEnabled( message );
    m_msgDelAction->setEnabled( message );
    //m_relatedAction->setEnabled( message );
    m_msgSaveAction->setEnabled( message );
    m_msgPrintAction->setEnabled( message );
    m_msgZoomInAction->setEnabled( message );
    m_msgZoomOutAction->setEnabled( message );
    m_msgForwardAction->setEnabled( message );
    m_msgForwardActionMenu->setEnabled( message );
    m_msgReplyAction->setEnabled( message );
    m_msgReEditAction->setEnabled( message );
    m_sourceAction->setEnabled( message );
    m_msgUser0Action->setEnabled( message );
    m_msgUser1Action->setEnabled( message );
    m_msgUser2Action->setEnabled( message );
    m_msgUser3Action->setEnabled( message );
    m_msgUser4Action->setEnabled( message );
    m_msgUser5Action->setEnabled( message );

    // Set the state of the toggle icons.
    if (message)
    {
        m_plainTextAction->setEnabled( !m_sourceAction->isChecked() );
        m_fixedfontAction->setEnabled( m_plainTextAction->isChecked() );
        m_externalImageAction->setEnabled( !m_plainTextAction->isChecked() );
        m_msgDelAction->setChecked(tb->msg()->isDeleted());

        setStatusBarStates();
    }

    // And now for the mailbox actions.
    MailBoxListViewItem* mbi =
            static_cast<MailBoxListViewItem*>(m_mailboxList->selectedItem());

    m_expungeAction->setEnabled( mbi );
    m_selectAllAction->setEnabled( mbi );
    m_childSortAction->setEnabled( mbi );
    m_hideDeletedAction->setEnabled( mbi );
    m_syncAction->setEnabled( mbi );
}

void MainWindow::setStatusBarStates()
{
    if (m_plainTextAction->isChecked())
        statusBar()->changeItem(i18n("Short for text-mode", "Plain"), 2);
    else
        statusBar()->changeItem(i18n("Short for html-mode", "HTML"), 2);


    if (m_externalImageAction->isChecked())
        statusBar()->changeItem(i18n("Short for external images", "Ext."), 3);
    else
        statusBar()->changeItem(i18n("Short for no ext. images", "No ext."), 3);
}

void MainWindow::slotSearchLineClear()
{
    m_searchLine->clear();
}

void MainWindow::slotSearchLineChange(const QString& newText)
{
    // for the searchline to work, we need to have all headers parsed,
    // else only the ones already visible are searchable.
    m_headerList->allHeadersVisible();

    static bool s_washidden=false;
    if (m_hideDeletedAction->isChecked() && !newText.isEmpty())
    {
        m_hideDeletedAction->setChecked(false);
        // the search itself will make them visible, so no need to do it.
        s_washidden = true;
    }
    else if (newText.isEmpty() && s_washidden)
    {
        m_hideDeletedAction->setChecked(true);
        //Slightly delay this as the empty search will make them all visible.
        QTimer::singleShot(200, this, SLOT(slotHideDeleted()));
        s_washidden = false;
    }
}

void MainWindow::searchLineUpdate()
{
    if (!m_searchLine->text().isEmpty())
    {
        // make sure the headers are visible. slotSearchLineChange() is not
        // called when switching mailboxes.
        m_headerList->allHeadersVisible();

        m_searchLine->updateSearch();
        m_searchLine->setPaletteBackgroundColor(
                KGlobalSettings::activeTitleColor());
        m_searchLine->setPaletteForegroundColor(
                KGlobalSettings::activeTextColor());
        QTimer::singleShot(500, this, SLOT(slotSearchLineUpdateClear()));
    }
}

void MainWindow::slotSearchLineUpdateClear()
{
    m_searchLine->setPaletteBackgroundColor(
            KGlobalSettings::baseColor());
    m_searchLine->setPaletteForegroundColor(
            KGlobalSettings::textColor());
}


void MainWindow::slotUpdateStatusBar(const QString& text)
{
    m_statusTimer->stop();
    m_lastMessage = text;
    //kdDebug() << "status: " << text << endl;
    m_statusText->setText(text);
    QApplication::setOverrideCursor(QCursor(Qt::BusyCursor), true);
}

void MainWindow::slotUpdateStatusBarRestoreMouse(const QString& text)
{
    m_statusText->setText(text);
    QApplication::restoreOverrideCursor();
    //kdDebug() << "status: " << text << endl;
    kapp->processEvents();
    m_statusTimer->start(3000, true);
}

void MainWindow::slotClearStatusBar()
{
    m_statusText->setText(
            i18n("task done","%1 [completed]").arg(m_lastMessage));
    QApplication::restoreOverrideCursor();
    m_statusTimer->start(1000, true);
}

void MainWindow::slotSimpleMessageStatusBar(const QString& text)
{
    m_statusText->setText( text );
}

void MainWindow::slotStatusBarReady()
{
    m_statusText->setText( i18n("Ready") );
}

void MainWindow::slotStatusBarClicked(int i)
{
    if (i == 2)
    {
        m_plainTextAction->setChecked(!m_plainTextAction->isChecked());
        slotToggleHTML();
    }
    else if (i == 3)
    {
        m_externalImageAction->setChecked(!m_externalImageAction->isChecked());
        slotToggleExternalImage();
    }
}

void MainWindow::slotScrollBottom()
{
    m_headerList->verticalScrollBar()->setValue(
        m_headerList->verticalScrollBar()->maxValue());
}

void MainWindow::slotIsolateItem()
{
    static MailodyBaseListViewItem* s_sep = 0;

    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    HeaderListViewItem* hi =
            m_headerMap[qMakePair(tb->msg()->mb(),tb->msg()->uid())];

    if (m_headerList->isolationActive())
    {
        if (s_sep)
        {
            delete s_sep;
            s_sep = 0;
        }
        m_headerList->clearIsolation();
        return;
    }

    m_headerList->isolateItem(hi);
    m_headerList->triggerUpdate();

    s_sep = new HeaderListViewItem(m_headerList, 0);
    s_sep->setText(0,i18n("What's related:") );
    s_sep->setSelectable(false);
    s_sep->setLevel(2);

    // Algorithm to find related items. For now chop up the subject
    // into pieces, and query for all keywords longer the three
    // characters. Will become more intelligent one day, i promise.

    QStringList search;
    QStringList keywords = QStringList::split(" ", hi->msg()->subject());
    QStringList::Iterator it = keywords.begin();
    while (it != keywords.end())
    {
        if ((*it).length() > 3)
            search.append(*it);
        ++it;
    }

    QStringList results;
    m_db->search(search, results);

    m_addheaderlist_val = results;

    //kdDebug() << "Search resulted in: " << results.count() << results << endl;

    slotAddHeaderList_process(3);

}

void MainWindow::slotOpenURLInNewTab(const QString& page)
{
    KURL kurl(page);
    QString title = kurl.hasHost() ? kurl.host() : i18n("Site");
    slotNewTab();
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    m_tabWidget->setTabLabel(tb, title);
    tb->headers()->hide();
    tb->body()->setExternalImage(true);
    tb->body()->setOpenLinksDirectly(true);
    if (!page.isEmpty())
        tb->body()->openURL( page );
}

void MainWindow::slotUpdateTabTitle(const QString& title)
{
    if (title.isEmpty())
        return;
    TotalView* tb = static_cast<TotalView*>(m_tabWidget->currentPage());
    m_tabWidget->setTabLabel(tb, title);
}

void MainWindow::slotCapableResult(const QString& something, bool possible)
{
    kdDebug() << k_funcinfo << something << possible << endl;
    if (something == "idle" && possible)
        m_idlePossible = true;
}

void MainWindow::slotQuit()
{
    exit(0);
}


}

#include "mainwindow.moc"


Generated by  Doxygen 1.6.0   Back to index