add: virtual QString key( int column, bool  ) const { KMHeaders *headers = static_cast<KMHeaders*>(listView()); int sortOrder = column; if (headers->mPaintInfo.orderOfArrival) sortOrder |= (1 << 6); if (headers->mPaintInfo.status) sortOrder |= (1 << 5);   if(mKey.isEmpty() || mKey[0] != (char)sortOrder) { KMHeaders *headers = static_cast<KMHeaders*>(listView()); KMMsgBase *msgBase = headers->folder()->getMsgBase( mMsgId ); return ((KMHeaderItem *)this)->mKey = generate_key( headers, msgBase, headers->paintInfo(), sortOrder ); } return mKey; }  void setTempKey( QString key ) { mKey = key; }  int compare( QListViewItem *i, int col, bool ascending ) const { int res = 0; KMHeaders *headers = static_cast<KMHeaders*>(listView()); if ( ( col == headers->paintInfo()->statusCol         ) || ( col == headers->paintInfo()->sizeCol           ) || ( col == headers->paintInfo()->attachmentCol     ) || ( col == headers->paintInfo()->importantCol      ) || ( col == headers->paintInfo()->spamHamCol        ) || ( col == headers->paintInfo()->signedCol         ) || ( col == headers->paintInfo()->cryptoCol         ) || ( col == headers->paintInfo()->watchedIgnoredCol ) ) { res = key( col, ascending ).compare( i->key( col, ascending ) ); } else if ( col == headers->paintInfo()->dateCol ) { res = key( col, ascending ).compare( i->key( col, ascending ) ); if (i->parent() && !ascending) res = -res; } else if ( col == headers->paintInfo()->subCol || col == headers->paintInfo()->senderCol || col == headers->paintInfo()->receiverCol ) { res = key( col, ascending ).localeAwareCompare( i->key( col, ascending ) ); } return res; }  QListViewItem* firstChildNonConst()  { enforceSortOrder(); return firstChild(); }  bool mAboutToBeDeleted; bool aboutToBeDeleted() const { return mAboutToBeDeleted; } void setAboutToBeDeleted( bool val ) { mAboutToBeDeleted = val; }  KMSortCacheItem *mSortCacheItem; void setSortCacheItem( KMSortCacheItem *item ) { mSortCacheItem = item; } KMSortCacheItem* sortCacheItem() const { return mSortCacheItem; } };   KMHeaders::KMHeaders(KMMainWidget *aOwner, QWidget *parent, const char *name) : KListView(parent, name) { static bool pixmapsLoaded = false;  KImageIO::registerFormats(); mOwner  = aOwner; mFolder = 0; noRepaint = false; getMsgIndex = -1; mTopItem = 0; setSelectionMode( QListView::Extended ); setAllColumnsShowFocus( true ); mNested = false; nestingPolicy = OpenUnread; mNestedOverride = false; mSubjThreading = true; mMousePressed = false; mSortInfo.dirty = true; mSortInfo.fakeSort = 0; mSortInfo.removed = 0; mSortInfo.column = 0; mSortInfo.ascending = false; mReaderWindowActive = false; setStyleDependantFrameWidth();  header()->setClickEnabled(true); header()->installEventFilter(this); mPopup = new KPopupMenu(this); mPopup->insertTitle(i18n("View Columns")); mPopup->setCheckable(true); mPopup->insertItem(i18n("Status"),          KPaintInfo::COL_STATUS); mPopup->insertItem(i18n("Important"),       KPaintInfo::COL_IMPORTANT); mPopup->insertItem(i18n("Attachment"),      KPaintInfo::COL_ATTACHMENT); mPopup->insertItem(i18n("Spam/Ham"),        KPaintInfo::COL_SPAM_HAM); mPopup->insertItem(i18n("Watched/Ignored"), KPaintInfo::COL_WATCHED_IGNORED); mPopup->insertItem(i18n("Signature"),       KPaintInfo::COL_SIGNED); mPopup->insertItem(i18n("Encryption"),      KPaintInfo::COL_CRYPTO); mPopup->insertItem(i18n("Size"),            KPaintInfo::COL_SIZE); mPopup->insertItem(i18n("Receiver"),        KPaintInfo::COL_RECEIVER);  connect(mPopup, SIGNAL(activated(int)), this, SLOT(slotToggleColumn(int)));  mSortCol = KMMsgList::sfDate; mSortDescending = false;  setShowSortIndicator(true); setFocusPolicy( WheelFocus );  if (!pixmapsLoaded) { pixmapsLoaded = true; pixNew                   = new QPixmap( UserIcon( "kmmsgnew"                   ) ); pixUns                   = new QPixmap( UserIcon( "kmmsgunseen"                ) ); pixDel                   = new QPixmap( UserIcon( "kmmsgdel"                   ) ); pixRead                  = new QPixmap( UserIcon( "kmmsgread"                  ) ); pixRep                   = new QPixmap( UserIcon( "kmmsgreplied"               ) ); pixQueued                = new QPixmap( UserIcon( "kmmsgqueued"                ) ); pixSent                  = new QPixmap( UserIcon( "kmmsgsent"                  ) ); pixFwd                   = new QPixmap( UserIcon( "kmmsgforwarded"             ) ); pixFlag                  = new QPixmap( UserIcon( "kmmsgflag"                  ) ); pixWatched               = new QPixmap( UserIcon( "kmmsgwatched"               ) ); pixIgnored               = new QPixmap( UserIcon( "kmmsgignored"               ) ); pixSpam                  = new QPixmap( UserIcon( "kmmsgspam"                  ) ); pixHam                   = new QPixmap( UserIcon( "kmmsgham"                   ) ); pixFullySigned           = new QPixmap( UserIcon( "kmmsgfullysigned"           ) ); pixPartiallySigned       = new QPixmap( UserIcon( "kmmsgpartiallysigned"       ) ); pixUndefinedSigned       = new QPixmap( UserIcon( "kmmsgundefinedsigned"       ) ); pixFullyEncrypted        = new QPixmap( UserIcon( "kmmsgfullyencrypted"        ) ); pixPartiallyEncrypted    = new QPixmap( UserIcon( "kmmsgpartiallyencrypted"    ) ); pixUndefinedEncrypted    = new QPixmap( UserIcon( "kmmsgundefinedencrypted"    ) ); pixEncryptionProblematic = new QPixmap( UserIcon( "kmmsgencryptionproblematic" ) ); pixSignatureProblematic  = new QPixmap( UserIcon( "kmmsgsignatureproblematic"  ) ); pixAttachment            = new QPixmap( UserIcon( "kmmsgattachment"            ) ); pixReadFwd               = new QPixmap( UserIcon( "kmmsgread_fwd"              ) ); pixReadReplied           = new QPixmap( UserIcon( "kmmsgread_replied"          ) ); pixReadFwdReplied        = new QPixmap( UserIcon( "kmmsgread_fwd_replied"      ) ); }  header()->setStretchEnabled( false ); header()->setResizeEnabled( false ); setResizeMode( QListView::NoColumn );  mPaintInfo.subCol    =   addColumn( i18n("Subject"), 310 ); mPaintInfo.senderCol   = addColumn( i18n("Sender"),  170 ); mPaintInfo.dateCol     = addColumn( i18n("Date"),    170 ); mPaintInfo.sizeCol     = addColumn( i18n("Size"),      0 ); mPaintInfo.receiverCol = addColumn( i18n("Receiver"),  0 );  mPaintInfo.statusCol         = addColumn( *pixNew           , "", 0 ); mPaintInfo.importantCol      = addColumn( *pixFlag          , "", 0 ); mPaintInfo.attachmentCol     = addColumn( *pixAttachment    , "", 0 ); mPaintInfo.spamHamCol        = addColumn( *pixSpam          , "", 0 ); mPaintInfo.watchedIgnoredCol = addColumn( *pixWatched       , "", 0 ); mPaintInfo.signedCol         = addColumn( *pixFullySigned   , "", 0 ); mPaintInfo.cryptoCol         = addColumn( *pixFullyEncrypted, "", 0 );   header()->setResizeEnabled( true, mPaintInfo.subCol ); header()->setResizeEnabled( true, mPaintInfo.senderCol ); header()->setResizeEnabled( true, mPaintInfo.dateCol );  connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint &, int )), this, SLOT( rightButtonPressed( QListViewItem*, const QPoint &, int ))); connect(this, SIGNAL(doubleClicked(QListViewItem*)), this,SLOT(selectMessage(QListViewItem*))); connect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*))); resetCurrentTime();  mSubjectLists.setAutoDelete( true ); }    KMHeaders::~KMHeaders () { if (mFolder) { writeFolderConfig(); writeSortOrder(); mFolder->close(); } writeConfig(); }   bool KMHeaders::eventFilter ( QObject *o, QEvent *e ) { if ( e->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(e)->button() == RightButton && o->isA("QHeader") ) { mPopup->popup( static_cast<QMouseEvent*>(e)->globalPos() ); return true; } return KListView::eventFilter(o, e); }    void KMHeaders::slotToggleColumn(int id, int mode) { bool *show = 0; int  *col  = 0; int  width = 0;  switch ( static_cast<KPaintInfo::ColumnIds>(id) ) { case KPaintInfo::COL_SIZE: { show  = &mPaintInfo.showSize; col   = &mPaintInfo.sizeCol; width = 80; break; } case KPaintInfo::COL_ATTACHMENT: { show  = &mPaintInfo.showAttachment; col   = &mPaintInfo.attachmentCol; width = pixAttachment->width(); break; } case KPaintInfo::COL_IMPORTANT: { show  = &mPaintInfo.showImportant; col   = &mPaintInfo.importantCol; width = pixFlag->width(); break; } case KPaintInfo::COL_SPAM_HAM: { show  = &mPaintInfo.showSpamHam; col   = &mPaintInfo.spamHamCol; width = pixSpam->width(); break; } case KPaintInfo::COL_WATCHED_IGNORED: { show  = &mPaintInfo.showWatchedIgnored; col   = &mPaintInfo.watchedIgnoredCol; width = pixWatched->width(); break; } case KPaintInfo::COL_STATUS: { show  = &mPaintInfo.showStatus; col   = &mPaintInfo.statusCol; width = pixNew->width(); break; } case KPaintInfo::COL_SIGNED: { show  = &mPaintInfo.showSigned; col   = &mPaintInfo.signedCol; width = pixFullySigned->width(); break; } case KPaintInfo::COL_CRYPTO: { show  = &mPaintInfo.showCrypto; col   = &mPaintInfo.cryptoCol; width = pixFullyEncrypted->width(); break; } case KPaintInfo::COL_RECEIVER: { show  = &mPaintInfo.showReceiver; col   = &mPaintInfo.receiverCol; width = 170; break; }  }  assert(show);  if (mode == -1) *show = !*show; else *show = mode;  mPopup->setItemChecked(id, *show);  if (*show) { header()->setResizeEnabled(true, *col); header()->setStretchEnabled(true, *col); setColumnWidth(*col, width); } else { header()->setResizeEnabled(false, *col); header()->setStretchEnabled(false, *col); hideColumn(*col); }    if ( static_cast<KPaintInfo::ColumnIds>(id) ==  KPaintInfo::COL_RECEIVER ) { QString colText = i18n( "Sender" ); if ( mFolder && (mFolder->whoField().lower() == "to") && !mPaintInfo.showReceiver) colText = i18n("Receiver"); setColumnText(mPaintInfo.senderCol, colText); }  if (mode == -1) writeConfig(); }    void KMHeaders::paintEmptyArea( QPainter * p, const QRect & rect ) { if (mPaintInfo.pixmapOn) p->drawTiledPixmap( rect.left(), rect.top(), rect.width(), rect.height(), mPaintInfo.pixmap, rect.left() + contentsX(), rect.top() + contentsY() ); else p->fillRect( rect, colorGroup().base() ); }  bool KMHeaders::event(QEvent *e) { bool result = KListView::event(e); if (e->type() == QEvent::ApplicationPaletteChange) { readColorConfig(); } return result; }    void KMHeaders::readColorConfig (void) { KConfig* config = KMKernel::config();  KConfigGroupSaver saver(config, "Reader"); QColor c1=QColor(kapp->palette().active().text()); QColor c2=QColor("red"); QColor c3=QColor("blue"); QColor c4=QColor(kapp->palette().active().base()); QColor c5=QColor(0,0x7F,0); QColor c6=KGlobalSettings::alternateBackgroundColor();  if (!config->readBoolEntry("defaultColors",true)) { mPaintInfo.colFore = config->readColorEntry("ForegroundColor",&c1); mPaintInfo.colBack = config->readColorEntry("BackgroundColor",&c4); QPalette newPal = kapp->palette(); newPal.setColor( QColorGroup::Base, mPaintInfo.colBack ); newPal.setColor( QColorGroup::Text, mPaintInfo.colFore ); setPalette( newPal ); mPaintInfo.colNew = config->readColorEntry("NewMessage",&c2); mPaintInfo.colUnread = config->readColorEntry("UnreadMessage",&c3); mPaintInfo.colFlag = config->readColorEntry("FlagMessage",&c5); c6 = config->readColorEntry("AltBackgroundColor",&c6); } else { mPaintInfo.colFore = c1; mPaintInfo.colBack = c4; QPalette newPal = kapp->palette(); newPal.setColor( QColorGroup::Base, c4 ); newPal.setColor( QColorGroup::Text, c1 ); setPalette( newPal ); mPaintInfo.colNew = c2; mPaintInfo.colUnread = c3; mPaintInfo.colFlag = c5; } setAlternateBackground(c6); }   void KMHeaders::readConfig (void) { KConfig* config = KMKernel::config();   { KConfigGroupSaver saver(config, "Pixmaps"); QString pixmapFile = config->readEntry("Headers"); mPaintInfo.pixmapOn = false; if (!pixmapFile.isEmpty()) { mPaintInfo.pixmapOn = true; mPaintInfo.pixmap = QPixmap( pixmapFile ); } }  { KConfigGroupSaver saver(config, "General"); bool show = config->readBoolEntry("showMessageSize"); slotToggleColumn(KPaintInfo::COL_SIZE, show);  show = config->readBoolEntry("showAttachmentColumn"); slotToggleColumn(KPaintInfo::COL_ATTACHMENT, show);  show = config->readBoolEntry("showImportantColumn"); slotToggleColumn(KPaintInfo::COL_IMPORTANT, show);  show = config->readBoolEntry("showSpamHamColumn"); slotToggleColumn(KPaintInfo::COL_SPAM_HAM, show);  show = config->readBoolEntry("showWatchedIgnoredColumn"); slotToggleColumn(KPaintInfo::COL_WATCHED_IGNORED, show);  show = config->readBoolEntry("showStatusColumn"); slotToggleColumn(KPaintInfo::COL_STATUS, show);  show = config->readBoolEntry("showSignedColumn"); slotToggleColumn(KPaintInfo::COL_SIGNED, show);  show = config->readBoolEntry("showCryptoColumn"); slotToggleColumn(KPaintInfo::COL_CRYPTO, show);  show = config->readBoolEntry("showReceiverColumn"); slotToggleColumn(KPaintInfo::COL_RECEIVER, show);  mPaintInfo.showCryptoIcons = config->readBoolEntry( "showCryptoIcons", false ); mPaintInfo.showAttachmentIcon = config->readBoolEntry( "showAttachmentIcon", true );  KMime::DateFormatter::FormatType t = (KMime::DateFormatter::FormatType) config->readNumEntry("dateFormat", KMime::DateFormatter::Fancy ) ; mDate.setCustomFormat( config->readEntry("customDateFormat") ); mDate.setFormat( t ); }  readColorConfig();   { KConfigGroupSaver saver(config, "Fonts"); if (!(config->readBoolEntry("defaultFonts",true))) { QFont listFont( KGlobalSettings::generalFont() ); setFont(config->readFontEntry("list-font", &listFont)); dateFont = KGlobalSettings::fixedFont(); dateFont = config->readFontEntry("list-date-font", &dateFont); } else { dateFont = KGlobalSettings::generalFont(); setFont(dateFont); } }   { KConfigGroupSaver saver(config, "Geometry"); mReaderWindowActive = config->readEntry( "readerWindowMode", "below" ) != "hide"; } }    void KMHeaders::reset(void) { int top = topItemIndex(); int id = currentItemIndex(); noRepaint = true; clear(); noRepaint = false; mItems.resize(0); updateMessageList(); setCurrentMsg(id); setTopItemByIndex(top); ensureCurrentItemVisible(); }   void KMHeaders::refreshNestedState(void) { bool oldState = isThreaded(); NestingPolicy oldNestPolicy = nestingPolicy; KConfig* config = KMKernel::config(); KConfigGroupSaver saver(config, "Geometry"); mNested = config->readBoolEntry( "nestedMessages", false );  nestingPolicy = (NestingPolicy)config->readNumEntry( "nestingPolicy", OpenUnread ); if ((nestingPolicy != oldNestPolicy) || (oldState != isThreaded())) { setRootIsDecorated( nestingPolicy != AlwaysOpen && isThreaded() ); reset(); }  }   void KMHeaders::readFolderConfig (void) { if (!mFolder) return; KConfig* config = KMKernel::config();  KConfigGroupSaver saver(config, "Folder-" + mFolder->idString()); mNestedOverride = config->readBoolEntry( "threadMessagesOverride", false ); mSortCol = config->readNumEntry("SortColumn", (int)KMMsgList::sfDate); mSortDescending = (mSortCol < 0); mSortCol = abs(mSortCol) - 1;  mTopItem = config->readNumEntry("Top", 0); mCurrentItem = config->readNumEntry("Current", 0); mCurrentItemSerNum = config->readNumEntry("CurrentSerialNum", 0);  mPaintInfo.orderOfArrival = config->readBoolEntry( "OrderOfArrival", true ); mPaintInfo.status = config->readBoolEntry( "Status", false );  { KConfigGroupSaver saver(config, "Geometry"); mNested = config->readBoolEntry( "nestedMessages", false ); nestingPolicy = (NestingPolicy)config->readNumEntry( "nestingPolicy", OpenUnread ); }  setRootIsDecorated( nestingPolicy != AlwaysOpen && isThreaded() ); mSubjThreading = config->readBoolEntry( "threadMessagesBySubject", true ); }    void KMHeaders::writeFolderConfig (void) { if (!mFolder) return; KConfig* config = KMKernel::config(); int mSortColAdj = mSortCol + 1;  KConfigGroupSaver saver(config, "Folder-" + mFolder->idString()); config->writeEntry("SortColumn", (mSortDescending ? -mSortColAdj : mSortColAdj)); config->writeEntry("Top", topItemIndex()); config->writeEntry("Current", currentItemIndex()); KMHeaderItem* current = currentHeaderItem(); ulong sernum = 0; if ( current && mFolder->getMsgBase( current->msgId() ) ) sernum = mFolder->getMsgBase( current->msgId() )->getMsgSerNum(); config->writeEntry("CurrentSerialNum", sernum);  config->writeEntry("OrderOfArrival", mPaintInfo.orderOfArrival); config->writeEntry("Status", mPaintInfo.status); }   void KMHeaders::writeConfig (void) { KConfig* config = KMKernel::config(); saveLayout(config, "Header-Geometry"); KConfigGroupSaver saver(config, "General"); config->writeEntry("showMessageSize"         , mPaintInfo.showSize); config->writeEntry("showAttachmentColumn"    , mPaintInfo.showAttachment); config->writeEntry("showImportantColumn"     , mPaintInfo.showImportant); config->writeEntry("showSpamHamColumn"       , mPaintInfo.showSpamHam); config->writeEntry("showWatchedIgnoredColumn", mPaintInfo.showWatchedIgnored); config->writeEntry("showStatusColumn"        , mPaintInfo.showStatus); config->writeEntry("showSignedColumn"        , mPaintInfo.showSigned); config->writeEntry("showCryptoColumn"        , mPaintInfo.showCrypto); config->writeEntry("showReceiverColumn"      , mPaintInfo.showReceiver); }   void KMHeaders::setFolder( KMFolder *aFolder, bool forceJumpToUnread ) { CREATE_TIMER(set_folder); START_TIMER(set_folder);  int id; QString str;  mSortInfo.fakeSort = 0; if ( mFolder && static_cast<KMFolder*>(mFolder) == aFolder ) { int top = topItemIndex(); id = currentItemIndex(); writeFolderConfig(); readFolderConfig(); updateMessageList(); setCurrentMsg(id); setTopItemByIndex(top); } else { if (mFolder) {   highlightMessage(0, false);  disconnect(mFolder, SIGNAL(numUnreadMsgsChanged(KMFolder*)), this, SLOT(setFolderInfoStatus()));  mFolder->markNewAsUnread(); writeFolderConfig(); disconnect(mFolder, SIGNAL(msgHeaderChanged(KMFolder*,int)), this, SLOT(msgHeaderChanged(KMFolder*,int))); disconnect(mFolder, SIGNAL(msgAdded(int)), this, SLOT(msgAdded(int))); disconnect(mFolder, SIGNAL(msgRemoved(int,QString, QString)), this, SLOT(msgRemoved(int,QString, QString))); disconnect(mFolder, SIGNAL(changed()), this, SLOT(msgChanged())); disconnect(mFolder, SIGNAL(cleared()), this, SLOT(folderCleared())); disconnect(mFolder, SIGNAL(expunged()), this, SLOT(folderCleared())); disconnect( mFolder, SIGNAL( statusMsg( const QString& ) ), BroadcastStatus::instance(), SLOT( setStatusMsg( const QString& ) ) ); writeSortOrder(); mFolder->close();   if (mFolder->dirty()) mFolder->writeIndex(); }  mSortInfo.removed = 0; mFolder = aFolder; mSortInfo.dirty = true; mOwner->editAction()->setEnabled(mFolder ? (kmkernel->folderIsDraftOrOutbox(mFolder)): false ); mOwner->replyListAction()->setEnabled(mFolder ? mFolder->isMailingListEnabled() : false); if (mFolder) { connect(mFolder, SIGNAL(msgHeaderChanged(KMFolder*,int)), this, SLOT(msgHeaderChanged(KMFolder*,int))); connect(mFolder, SIGNAL(msgAdded(int)), this, SLOT(msgAdded(int))); connect(mFolder, SIGNAL(msgRemoved(int,QString, QString)), this, SLOT(msgRemoved(int,QString, QString))); connect(mFolder, SIGNAL(changed()), this, SLOT(msgChanged())); connect(mFolder, SIGNAL(cleared()), this, SLOT(folderCleared())); connect(mFolder, SIGNAL(expunged()), this, SLOT(folderCleared())); connect(mFolder, SIGNAL(statusMsg(const QString&)), BroadcastStatus::instance(), SLOT( setStatusMsg( const QString& ) ) ); connect(mFolder, SIGNAL(numUnreadMsgsChanged(KMFolder*)), this, SLOT(setFolderInfoStatus()));     if (isThreaded()) { noRepaint = true; clear(); noRepaint = false; mItems.resize( 0 ); }  readFolderConfig();  CREATE_TIMER(kmfolder_open); START_TIMER(kmfolder_open); mFolder->open(); END_TIMER(kmfolder_open); SHOW_TIMER(kmfolder_open);  if (isThreaded()) { noRepaint = true; clear(); noRepaint = false; mItems.resize( 0 ); } } }  CREATE_TIMER(updateMsg); START_TIMER(updateMsg); updateMessageList(true, forceJumpToUnread); END_TIMER(updateMsg); SHOW_TIMER(updateMsg); makeHeaderVisible();  if (mFolder) setFolderInfoStatus();  QString colText = i18n( "Sender" ); if (mFolder && (mFolder->whoField().lower() == "to") && !mPaintInfo.showReceiver) colText = i18n("Receiver"); setColumnText( mPaintInfo.senderCol, colText);  colText = i18n( "Date" ); if (mPaintInfo.orderOfArrival) colText = i18n( "Date (Order of Arrival)" ); setColumnText( mPaintInfo.dateCol, colText);  colText = i18n( "Subject" ); if (mPaintInfo.status) colText = colText + i18n( " (Status)" ); setColumnText( mPaintInfo.subCol, colText);  END_TIMER(set_folder); SHOW_TIMER(set_folder); }   void KMHeaders::msgChanged() { emit maybeDeleting(); if (mFolder->count() == 0) { clear(); return; } int i = topItemIndex(); int cur = currentItemIndex(); if (!isUpdatesEnabled()) return; QString msgIdMD5; QListViewItem *item = currentItem(); KMHeaderItem *hi = dynamic_cast<KMHeaderItem*>(item); if (item && hi) { KMMsgBase *mb = mFolder->getMsgBase(hi->msgId()); if (mb) msgIdMD5 = mb->msgIdMD5(); } if (!isUpdatesEnabled()) return;  disconnect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*)));  QValueList<int> curItems = selectedItems(); updateMessageList();  setTopItemByIndex( i ); setCurrentMsg( cur ); setSelectedByIndex( curItems, true ); connect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*)));         item = currentItem(); hi = dynamic_cast<KMHeaderItem*>(item); if (item && hi) { KMMsgBase *mb = mFolder->getMsgBase(hi->msgId()); if (mb) { if (msgIdMD5.isEmpty() || (msgIdMD5 != mb->msgIdMD5())) emit selected(mFolder->getMsg(hi->msgId())); } else { emit selected(0); } } else emit selected(0); }    void KMHeaders::msgAdded(int id) { KMHeaderItem* hi = 0; if (!isUpdatesEnabled()) return;  CREATE_TIMER(msgAdded); START_TIMER(msgAdded);  assert( mFolder->getMsgBase( id ) );   KMSortCacheItem *sci = new KMSortCacheItem; sci->setId(id); if (isThreaded()) {  if (mSortCacheItems.count() == (uint)mFolder->count() || mSortCacheItems.count() == 0) { kdDebug (5006) << "KMHeaders::msgAdded - Resizing id and subject trees of " << mFolder->label() << ": before=" << mSortCacheItems.count() << " ,after=" << (mFolder->count()*2) << endl; mSortCacheItems.resize(mFolder->count()*2); mSubjectLists.resize(mFolder->count()*2); } QString msgId = mFolder->getMsgBase(id)->msgIdMD5(); if (msgId.isNull()) msgId = ""; QString replyToId = mFolder->getMsgBase(id)->replyToIdMD5();  KMSortCacheItem *parent = findParent( sci ); if (!parent && mSubjThreading) { parent = findParentBySubject( sci ); if (parent && sci->isImperfectlyThreaded()) {     if (msgId == mFolder->getMsgBase(parent->item()->msgId())->replyToIdMD5() || msgId == mFolder->getMsgBase(parent->item()->msgId())->replyToAuxIdMD5()) parent = NULL; } }  if (parent && mFolder->getMsgBase(parent->id())->isWatched()) mFolder->getMsgBase(id)->setStatus( KMMsgStatusWatched ); else if (parent && mFolder->getMsgBase(parent->id())->isIgnored()) { mFolder->getMsgBase(id)->setStatus( KMMsgStatusIgnored ); mFolder->setStatus( id, KMMsgStatusRead ); } if (parent) hi = new KMHeaderItem( parent->item(), id ); else hi = new KMHeaderItem( this, id );   hi->setSortCacheItem(sci); sci->setItem(hi);   mItems.resize( mFolder->count() ); mItems[id] = hi;  if ( !msgId.isEmpty() ) mSortCacheItems.replace(msgId, sci);  if (mSubjThreading && parent) { QString subjMD5 = mFolder->getMsgBase(id)->strippedSubjectMD5(); if (subjMD5.isEmpty()) { mFolder->getMsgBase(id)->initStrippedSubjectMD5(); subjMD5 = mFolder->getMsgBase(id)->strippedSubjectMD5(); } if( !subjMD5.isEmpty()) { if ( !mSubjectLists.find(subjMD5) ) mSubjectLists.insert(subjMD5, new QPtrList<KMSortCacheItem>());  int p=0; for (QPtrListIterator<KMSortCacheItem> it(*mSubjectLists[subjMD5]); it.current(); ++it) { KMMsgBase *mb = mFolder->getMsgBase((*it)->id()); if ( mb->date() < mFolder->getMsgBase(id)->date()) break; p++; } mSubjectLists[subjMD5]->insert( p, sci); } }     disconnect( this, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(highlightMessage(QListViewItem*)));  if ( !msgId.isEmpty() ) { QPtrListIterator<KMHeaderItem> it(mImperfectlyThreadedList); KMHeaderItem *cur; while ( (cur = it.current()) ) { ++it; int tryMe = cur->msgId();    bool perfectParent = true; KMMsgBase *otherMsg = mFolder->getMsgBase(tryMe); if ( !otherMsg ) { kdDebug(5006) << "otherMsg is NULL !!! tryMe: " << tryMe << endl; continue; } QString otherId = otherMsg->replyToIdMD5(); if (msgId != otherId) { if (msgId != otherMsg->replyToAuxIdMD5()) continue; else { if (!otherId.isEmpty() && mSortCacheItems.find(otherId)) continue; else   perfectParent = false; } } QListViewItem *newParent = mItems[id]; QListViewItem *msg = mItems[tryMe];  if (msg->parent()) msg->parent()->takeItem(msg); else takeItem(msg); newParent->insertItem(msg);  makeHeaderVisible();  if (perfectParent) { mImperfectlyThreadedList.removeRef (mItems[tryMe]);   QString sortFile = KMAIL_SORT_FILE(mFolder); FILE *sortStream = fopen(QFile::encodeName(sortFile), "r+"); if (sortStream) { mItems[tryMe]->sortCacheItem()->updateSortFile( sortStream, mFolder ); fclose (sortStream); } } } }  if (hi && hi->sortCacheItem()->isImperfectlyThreaded()) mImperfectlyThreadedList.append(hi); } else {  hi = new KMHeaderItem( this, id ); mItems.resize( mFolder->count() ); mItems[id] = hi;  hi->setSortCacheItem(sci); sci->setItem(hi); } if (mSortInfo.fakeSort) { QObject::disconnect(header(), SIGNAL(clicked(int)), this, SLOT(dirtySortOrder(int))); KListView::setSorting(mSortCol, !mSortDescending ); mSortInfo.fakeSort = 0; } appendItemToSortFile(hi);  msgHeaderChanged(mFolder,id);  if ((childCount() == 1) && hi) { setSelected( hi, true ); setCurrentItem( firstChild() ); setSelectionAnchor( currentItem() ); highlightMessage( currentItem() ); }   connect( this, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(highlightMessage(QListViewItem*)));  emit messageListUpdated(); END_TIMER(msgAdded); SHOW_TIMER(msgAdded); }    void KMHeaders::msgRemoved(int id, QString msgId, QString strippedSubjMD5) { if (!isUpdatesEnabled()) return;  if ((id < 0) || (id >= (int)mItems.size())) return;  disconnect( this, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(highlightMessage(QListViewItem*)));  KMHeaderItem *removedItem = mItems[id]; if (!removedItem) return; KMHeaderItem *curItem = currentHeaderItem();  for (int i = id; i < (int)mItems.size() - 1; ++i) { mItems[i] = mItems[i+1]; mItems[i]->setMsgId( i ); mItems[i]->sortCacheItem()->setId( i ); }  mItems.resize( mItems.size() - 1 );  if (isThreaded() && mFolder->count()) { if ( !msgId.isEmpty() && mSortCacheItems[msgId] ) { if (mSortCacheItems[msgId] == removedItem->sortCacheItem()) mSortCacheItems.remove(msgId); }   if (!strippedSubjMD5.isEmpty() && mSubjThreading && mSubjectLists[strippedSubjMD5]) mSubjectLists[strippedSubjMD5]->remove(removedItem->sortCacheItem());   QListViewItem *myParent = removedItem; QListViewItem *myChild = myParent->firstChild(); QListViewItem *threadRoot = myParent; while (threadRoot->parent()) threadRoot = threadRoot->parent(); QString key = static_cast<KMHeaderItem*>(threadRoot)->key(mSortCol, !mSortDescending);  QPtrList<QListViewItem> childList; while (myChild) { KMHeaderItem *item = static_cast<KMHeaderItem*>(myChild);  if ( !item->aboutToBeDeleted() ) { childList.append(myChild); } myChild = myChild->nextSibling(); if ( item->aboutToBeDeleted() ) { myParent->takeItem( item ); insertItem( item ); } item->setTempKey( key + item->key( mSortCol, !mSortDescending )); if (mSortInfo.fakeSort) { QObject::disconnect(header(), SIGNAL(clicked(int)), this, SLOT(dirtySortOrder(int))); KListView::setSorting(mSortCol, !mSortDescending ); mSortInfo.fakeSort = 0; } }  for (QPtrListIterator<QListViewItem> it(childList); it.current() ; ++it ) { QListViewItem *lvi = *it; KMHeaderItem *item = static_cast<KMHeaderItem*>(lvi); KMSortCacheItem *sci = item->sortCacheItem(); KMSortCacheItem *parent = findParent( sci ); if (!parent) parent = findParentBySubject( sci ); myParent->takeItem(lvi); if (parent && parent->item() != item) parent->item()->insertItem(lvi); else insertItem(lvi);  if (!parent || (sci->isImperfectlyThreaded() && !mImperfectlyThreadedList.containsRef(item))) mImperfectlyThreadedList.append(item); if (parent && !sci->isImperfectlyThreaded() && mImperfectlyThreadedList.containsRef(item)) mImperfectlyThreadedList.removeRef(item); } }  if (!mFolder->count()) folderCleared();  mImperfectlyThreadedList.removeRef(removedItem); delete removedItem;  if ( curItem && curItem != removedItem ) { setCurrentItem( curItem ); setSelectionAnchor( currentItem() ); }   connect( this, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(highlightMessage(QListViewItem*)));  }    void KMHeaders::msgHeaderChanged(KMFolder*, int msgId) { if (msgId<0 || msgId >= (int)mItems.size() || !isUpdatesEnabled()) return; KMHeaderItem *item = mItems[msgId]; if (item) { item->irefresh(); item->repaint(); } }    void KMHeaders::setMsgStatus (KMMsgStatus status, bool toggle) { SerNumList serNums; for (QListViewItemIterator it(this); it.current(); ++it) if ( it.current()->isSelected() && it.current()->isVisible() ) { KMHeaderItem *item = static_cast<KMHeaderItem*>(it.current()); KMMsgBase *msgBase = mFolder->getMsgBase(item->msgId()); serNums.append( msgBase->getMsgSerNum() ); } if (serNums.empty()) return;  KMCommand *command = new KMSetStatusCommand( status, serNums, toggle ); command->start(); }   QPtrList<QListViewItem> KMHeaders::currentThread() const { if (!mFolder) return QPtrList<QListViewItem>();   QListViewItem *curItem = currentItem(); if (!curItem) return QPtrList<QListViewItem>();   QListViewItem *topOfThread = curItem; while ( topOfThread->parent() ) topOfThread = topOfThread->parent();   QPtrList<QListViewItem> list; QListViewItem *topOfNextThread = topOfThread->nextSibling(); for ( QListViewItemIterator it( topOfThread ) ; it.current() && it.current() != topOfNextThread ; ++it ) list.append( it.current() ); return list; }  void KMHeaders::setThreadStatus(KMMsgStatus status, bool toggle) { QPtrList<QListViewItem> curThread = currentThread(); QPtrListIterator<QListViewItem> it( curThread ); SerNumList serNums;  for ( it.toFirst() ; it.current() ; ++it ) { int id = static_cast<KMHeaderItem*>(*it)->msgId(); KMMsgBase *msgBase = mFolder->getMsgBase( id ); serNums.append( msgBase->getMsgSerNum() ); }  if (serNums.empty()) return;  KMCommand *command = new KMSetStatusCommand( status, serNums, toggle ); command->start(); }   int KMHeaders::slotFilterMsg(KMMessage *msg) { msg->setTransferInProgress(false); int filterResult = kmkernel->filterMgr()->process(msg,KMFilterMgr::Explicit); if (filterResult == 2) {  kmkernel->emergencyExit( i18n("Unable to process messages: " ) + QString::fromLocal8Bit(strerror(errno))); return 2; } if (msg->parent()) { int idx = -1; KMFolder * p = 0; kmkernel->msgDict()->getLocation( msg, &p, &idx ); assert( p == msg->parent() ); assert( idx >= 0 ); p->unGetMsg( idx ); }  return filterResult; }   void KMHeaders::slotExpandOrCollapseThread( bool expand ) { if ( !isThreaded() ) return;  QListViewItem *item = currentItem(); if ( !item ) return; clearSelection(); item->setSelected( true ); while ( item->parent() ) item = item->parent(); KMHeaderItem * hdrItem = static_cast<KMHeaderItem*>(item); hdrItem->setOpenRecursive( expand ); if ( !expand ) setCurrentMsg( hdrItem->msgId() ); ensureItemVisible( currentItem() ); }  void KMHeaders::slotExpandOrCollapseAllThreads( bool expand ) { if ( !isThreaded() ) return;  QListViewItem * item = currentItem(); if( item ) { clearSelection(); item->setSelected( true ); }  for ( QListViewItem *item = firstChild() ; item ; item = item->nextSibling() ) static_cast<KMHeaderItem*>(item)->setOpenRecursive( expand ); if ( !expand ) { QListViewItem * item = currentItem(); if( item ) { while ( item->parent() ) item = item->parent(); setCurrentMsg( static_cast<KMHeaderItem*>(item)->msgId() ); } } ensureItemVisible( currentItem() ); }   void KMHeaders::setStyleDependantFrameWidth() {  int frameWidth; if( style().isA("KeramikStyle") ) frameWidth = style().pixelMetric( QStyle::PM_DefaultFrameWidth ) - 1; else frameWidth = style().pixelMetric( QStyle::PM_DefaultFrameWidth ); if ( frameWidth < 0 ) frameWidth = 0; if ( frameWidth != lineWidth() ) setLineWidth( frameWidth ); }   void KMHeaders::styleChange( QStyle& oldStyle ) { setStyleDependantFrameWidth(); KListView::styleChange( oldStyle ); }   void KMHeaders::setFolderInfoStatus () { if ( !mFolder ) return; QString str = ( static_cast<KMFolder*>(mFolder) == kmkernel->outboxFolder() ) ? i18n( "1 unsent", "%n unsent", mFolder->countUnread() ) : i18n( "1 unread", "%n unread", mFolder->countUnread() ); str = i18n( "1 message, %1.", "%n messages, %1.", mFolder->count() ) .arg( str ); if ( mFolder->isReadOnly() ) str = i18n("%1 = n messages, m unread.", "%1 Folder is read-only.").arg( str ); BroadcastStatus::instance()->setStatusMsg(str); }   void KMHeaders::applyFiltersOnMsg() { #if 0 KMFilterMgr::FilterSet set = KMFilterMgr::All; QPtrList<KMFilter> filters; filters = *( kmkernel->filterMgr() ); ActionScheduler *scheduler = new ActionScheduler( set, filters, this ); scheduler->setAutoDestruct( true );  int contentX, contentY; KMHeaderItem *nextItem = prepareMove( &contentX, &contentY ); QPtrList<KMMsgBase> msgList = *selectedMsgs(true); finalizeMove( nextItem, contentX, contentY );  for (KMMsgBase *msg = msgList.first(); msg; msg = msgList.next()) scheduler->execFilters( msg ); #else emit maybeDeleting();  disconnect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*))); KMMessageList* msgList = selectedMsgs(); int topX = contentsX(); int topY = contentsY();  if (msgList->isEmpty()) return; QListViewItem *qlvi = currentItem(); QListViewItem *next = qlvi; while (next && next->isSelected()) next = next->itemBelow(); if (!next || (next && next->isSelected())) { next = qlvi; while (next && next->isSelected()) next = next->itemAbove(); }  clearSelection(); for (KMMsgBase* msgBase=msgList->first(); msgBase; msgBase=msgList->next()) { int idx = msgBase->parent()->find(msgBase); assert(idx != -1); KMMessage * msg = msgBase->parent()->getMsg(idx); if (msg->transferInProgress()) continue; msg->setTransferInProgress(true); if ( !msg->isComplete() ) { FolderJob *job = mFolder->createJob(msg); connect(job, SIGNAL(messageRetrieved(KMMessage*)), SLOT(slotFilterMsg(KMMessage*))); job->start(); } else { if (slotFilterMsg(msg) == 2) break; } }  setContentsPos( topX, topY ); emit selected( 0 ); if (next) { setCurrentItem( next ); setSelected( next, true ); setSelectionAnchor( currentItem() ); highlightMessage( next ); } else if (currentItem()) { setSelected( currentItem(), true ); setSelectionAnchor( currentItem() ); highlightMessage( currentItem() ); } else emit selected( 0 );  makeHeaderVisible(); connect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*))); #endif }    void KMHeaders::setMsgRead (int msgId) { KMMsgBase *msgBase = mFolder->getMsgBase( msgId ); if (!msgBase) return;  SerNumList serNums; if (msgBase->isNew() || msgBase->isUnread()) { serNums.append( msgBase->getMsgSerNum() ); }  KMCommand *command = new KMSetStatusCommand( KMMsgStatusRead, serNums ); command->start(); }    void KMHeaders::deleteMsg () {  if (!mFolder) return;  int contentX, contentY; KMHeaderItem *nextItem = prepareMove( &contentX, &contentY ); KMMessageList msgList = *selectedMsgs(true); finalizeMove( nextItem, contentX, contentY );  KMCommand *command = new KMDeleteMsgCommand( mFolder, msgList ); connect( command, SIGNAL( completed( KMCommand * ) ), this, SLOT( slotMoveCompleted( KMCommand * ) ) ); command->start();  BroadcastStatus::instance()->setStatusMsg("");  }    void KMHeaders::moveSelectedToFolder( int menuId ) { if (mMenuToFolder[menuId]) moveMsgToFolder( mMenuToFolder[menuId] ); }   KMHeaderItem* KMHeaders::prepareMove( int *contentX, int *contentY ) { KMHeaderItem *ret = 0; emit maybeDeleting();  disconnect( this, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(highlightMessage(QListViewItem*)));  QListViewItem *curItem; KMHeaderItem *item; curItem = currentItem(); while (curItem && curItem->isSelected() && curItem->itemBelow()) curItem = curItem->itemBelow(); while (curItem && curItem->isSelected() && curItem->itemAbove()) curItem = curItem->itemAbove(); item = static_cast<KMHeaderItem*>(curItem);  *contentX = contentsX(); *contentY = contentsY();  if (item  && !item->isSelected()) ret = item;  return ret; }   void KMHeaders::finalizeMove( KMHeaderItem *item, int contentX, int contentY ) { emit selected( 0 );  if ( item ) { clearSelection(); setCurrentItem( item ); setSelected( item, true ); setSelectionAnchor( currentItem() ); mPrevCurrent = 0; highlightMessage( item, false); }  setContentsPos( contentX, contentY ); makeHeaderVisible(); connect( this, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(highlightMessage(QListViewItem*))); }    void KMHeaders::moveMsgToFolder ( KMFolder* destFolder, bool askForConfirmation ) { if ( destFolder == mFolder ) return;  KMMessageList msgList = *selectedMsgs(); if ( !destFolder && askForConfirmation && KMessageBox::warningContinueCancel(this, i18n("<qt>Do you really want to delete the selected message?<br>" "Once deleted, it cannot be restored.</qt>", "<qt>Do you really want to delete the %n selected messages?<br>" "Once deleted, they cannot be restored.</qt>", msgList.count() ), i18n("Delete Messages"), KGuiItem(i18n("De&lete"),"editdelete"), "NoConfirmDelete") == KMessageBox::Cancel ) return;   int contentX, contentY; KMHeaderItem *nextItem = prepareMove( &contentX, &contentY ); msgList = *selectedMsgs(true); finalizeMove( nextItem, contentX, contentY );  KMCommand *command = new KMMoveCommand( destFolder, msgList ); connect( command, SIGNAL( completed( KMCommand * ) ), this, SLOT( slotMoveCompleted( KMCommand * ) ) ); command->start();  }  void KMHeaders::slotMoveCompleted( KMCommand *command ) { kdDebug(5006) << k_funcinfo << command->result() << endl; bool deleted = static_cast<KMMoveCommand *>( command )->destFolder() == 0; if ( command->result() == KMCommand::OK ) {  makeHeaderVisible(); #if 0 BroadcastStatus::instance()->setStatusMsg( deleted ? i18nTODO("Messages deleted successfully.") : i18nTODO("Messages moved successfully") ); #else if ( !deleted ) BroadcastStatus::instance()->setStatusMsg( i18n( "Messages moved successfully" ) ); #endif } else {  for (QListViewItemIterator it(this); it.current(); it++) { KMHeaderItem *item = static_cast<KMHeaderItem*>(it.current()); if ( item->aboutToBeDeleted() ) { item->setAboutToBeDeleted ( false ); item->setSelectable ( true ); KMMsgBase *msgBase = mFolder->getMsgBase(item->msgId()); if ( msgBase->isMessage() ) { KMMessage *msg = static_cast<KMMessage *>(msgBase); if ( msg ) msg->setTransferInProgress( false, true ); } } } triggerUpdate(); #if 0 if ( command->result() == KMCommand::Failed ) BroadcastStatus::instance()->setStatusMsg( deleted ? i18nTODO("Deleting messages failed.") : i18nTODO("Moving messages failed.") ); else BroadcastStatus::instance()->setStatusMsg( deleted ? i18nTODO("Deleting messages canceled.") : i18nTODO("Moving messages canceled.") ); #else if ( !deleted ) { if ( command->result() == KMCommand::Failed ) BroadcastStatus::instance()->setStatusMsg( i18n("Moving messages failed.") ); else BroadcastStatus::instance()->setStatusMsg( i18n("Moving messages canceled.") ); } #endif } }  bool KMHeaders::canUndo() const { return ( kmkernel->undoStack()->size() > 0 ); }   void KMHeaders::undo() { kmkernel->undoStack()->undo(); }   void KMHeaders::copySelectedToFolder(int menuId ) { if (mMenuToFolder[menuId]) copyMsgToFolder( mMenuToFolder[menuId] ); }    void KMHeaders::copyMsgToFolder(KMFolder* destFolder, KMMessage* aMsg) { if ( !destFolder ) return;  KMCommand * command = 0; if (aMsg) command = new KMCopyCommand( destFolder, aMsg ); else { KMMessageList msgList = *selectedMsgs(); command = new KMCopyCommand( destFolder, msgList ); }  command->start(); }    void KMHeaders::setCurrentMsg(int cur) { if (!mFolder) return; if (cur >= mFolder->count()) cur = mFolder->count() - 1; if ((cur >= 0) && (cur < (int)mItems.size())) { clearSelection(); setCurrentItem( mItems[cur] ); setSelected( mItems[cur], true ); setSelectionAnchor( currentItem() ); } makeHeaderVisible(); setFolderInfoStatus(); }   void KMHeaders::setSelected( QListViewItem *item, bool selected ) { if ( !item ) return;  if ( item->isVisible() ) KListView::setSelected( item, selected );    if ( isThreaded() && !item->isOpen() && item->firstChild() ) { QListViewItem *nextRoot = item->itemBelow(); QListViewItemIterator it( item->firstChild() ); for( ; (*it) != nextRoot; ++it ) { if ( (*it)->isVisible() ) (*it)->setSelected( selected ); } } }  void KMHeaders::setSelectedByIndex( QValueList<int> items, bool selected ) { for ( QValueList<int>::Iterator it = items.begin(); it != items.end(); ++it ) { if ( ((*it) >= 0) && ((*it) < (int)mItems.size()) ) { setSelected( mItems[(*it)], selected ); } } }  void KMHeaders::clearSelectableAndAboutToBeDeleted( Q_UINT32 serNum ) {  for (QListViewItemIterator it(this); it.current(); it++) { KMHeaderItem *item = static_cast<KMHeaderItem*>(it.current()); if ( item->aboutToBeDeleted() ) { KMMsgBase *msgBase = mFolder->getMsgBase( item->msgId() ); if ( serNum == msgBase->getMsgSerNum() ) { item->setAboutToBeDeleted ( false ); item->setSelectable ( true ); } } } triggerUpdate(); }   KMMessageList* KMHeaders::selectedMsgs(bool toBeDeleted) { mSelMsgBaseList.clear(); for (QListViewItemIterator it(this); it.current(); it++) { if ( it.current()->isSelected() && it.current()->isVisible() ) { KMHeaderItem *item = static_cast<KMHeaderItem*>(it.current()); if (toBeDeleted) {  item->setAboutToBeDeleted ( true ); item->setSelectable ( false ); } KMMsgBase *msgBase = mFolder->getMsgBase(item->msgId()); mSelMsgBaseList.append(msgBase); } } return &mSelMsgBaseList; }   QValueList<int> KMHeaders::selectedItems() { QValueList<int> items; for ( QListViewItemIterator it(this); it.current(); it++ ) { if ( it.current()->isSelected() && it.current()->isVisible() ) { KMHeaderItem* item = static_cast<KMHeaderItem*>( it.current() ); items.append( item->msgId() ); } } return items; }   int KMHeaders::firstSelectedMsg() const { int selectedMsg = -1; QListViewItem *item; for (item = firstChild(); item; item = item->itemBelow()) if (item->isSelected()) { selectedMsg = (static_cast<KMHeaderItem*>(item))->msgId(); break; } return selectedMsg; }   void KMHeaders::nextMessage() { QListViewItem *lvi = currentItem(); if (lvi && lvi->itemBelow()) { clearSelection(); setSelected( lvi, false ); selectNextMessage(); setSelectionAnchor( currentItem() ); ensureCurrentItemVisible(); } }  void KMHeaders::selectNextMessage() { QListViewItem *lvi = currentItem(); if( lvi ) { QListViewItem *below = lvi->itemBelow(); QListViewItem *temp = lvi; if (lvi && below ) { while (temp) { temp->firstChild(); temp = temp->parent(); } lvi->repaint();  (below->isSelected() ? setSelected(lvi, false) : setSelected(below, true)); setCurrentItem(below); makeHeaderVisible(); setFolderInfoStatus(); } } }   void KMHeaders::prevMessage() { QListViewItem *lvi = currentItem(); if (lvi && lvi->itemAbove()) { clearSelection(); setSelected( lvi, false ); selectPrevMessage(); setSelectionAnchor( currentItem() ); ensureCurrentItemVisible(); } }  void KMHeaders::selectPrevMessage() { QListViewItem *lvi = currentItem(); if( lvi ) { QListViewItem *above = lvi->itemAbove(); QListViewItem *temp = lvi;  if (lvi && above) { while (temp) { temp->firstChild(); temp = temp->parent(); } lvi->repaint();  (above->isSelected() ? setSelected(lvi, false) : setSelected(above, true)); setCurrentItem(above); makeHeaderVisible(); setFolderInfoStatus(); } } }   void KMHeaders::findUnreadAux( KMHeaderItem*& item, bool & foundUnreadMessage, bool onlyNew, bool aDirNext ) { KMMsgBase* msgBase = 0; KMHeaderItem *lastUnread = 0;  if (aDirNext) { while (item) { msgBase = mFolder->getMsgBase(item->msgId()); if (!msgBase) continue; if (msgBase->isUnread() || msgBase->isNew()) foundUnreadMessage = true;  if (!onlyNew && (msgBase->isUnread() || msgBase->isNew())) break; if (onlyNew && msgBase->isNew()) break; item = static_cast<KMHeaderItem*>(item->itemBelow()); } } else { KMHeaderItem *newItem = static_cast<KMHeaderItem*>(firstChild()); while (newItem) { msgBase = mFolder->getMsgBase(newItem->msgId()); if (!msgBase) continue; if (msgBase->isUnread() || msgBase->isNew()) foundUnreadMessage = true; if (!onlyNew && (msgBase->isUnread() || msgBase->isNew()) || onlyNew && msgBase->isNew()) lastUnread = newItem; if (newItem == item) break; newItem = static_cast<KMHeaderItem*>(newItem->itemBelow()); } item = lastUnread; } }   int KMHeaders::findUnread(bool aDirNext, int aStartAt, bool onlyNew, bool acceptCurrent) { KMHeaderItem *item, *pitem; bool foundUnreadMessage = false;  if (!mFolder) return -1; if (!(mFolder->count()) > 0) return -1;  if ((aStartAt >= 0) && (aStartAt < (int)mItems.size())) item = mItems[aStartAt]; else { item = currentHeaderItem(); if (!item) { if (aDirNext) item = static_cast<KMHeaderItem*>(firstChild()); else item = static_cast<KMHeaderItem*>(lastChild()); } if (!item) return -1;  if ( !acceptCurrent ) if (aDirNext) item = static_cast<KMHeaderItem*>(item->itemBelow()); else item = static_cast<KMHeaderItem*>(item->itemAbove()); }  pitem =  item;  findUnreadAux( item, foundUnreadMessage, onlyNew, aDirNext );       if (item) { QListViewItem *next = item; while (next->parent()) next = next->parent(); next = static_cast<KMHeaderItem*>(next)->firstChildNonConst(); while (next && (next != item)) if (static_cast<KMHeaderItem*>(next)->firstChildNonConst()) next = next->firstChild(); else if (next->nextSibling()) next = next->nextSibling(); else { while (next && (next != item)) { next = next->parent(); if (next == item) break; if (next && next->nextSibling()) { next = next->nextSibling(); break; } } } }  item = pitem;  findUnreadAux( item, foundUnreadMessage, onlyNew, aDirNext ); if (item) return item->msgId();    int unread = mFolder->countUnread(); if (((unread == 0) && foundUnreadMessage) || ((unread > 0) && !foundUnreadMessage)) { mFolder->correctUnreadMsgsCount(); } return -1; }   bool KMHeaders::nextUnreadMessage(bool acceptCurrent) { if ( !mFolder || !mFolder->countUnread() ) return false; int i = findUnread(true, -1, false, acceptCurrent); if ( i < 0 && GlobalSettings::loopOnGotoUnread() != GlobalSettings::EnumLoopOnGotoUnread::DontLoop ) { KMHeaderItem * first = static_cast<KMHeaderItem*>(firstChild()); if ( first ) i = findUnread(true, first->msgId(), false, acceptCurrent); } if ( i < 0 ) return false; setCurrentMsg(i); ensureCurrentItemVisible(); return true; }  void KMHeaders::ensureCurrentItemVisible() { int i = currentItemIndex(); if ((i >= 0) && (i < (int)mItems.size())) center( contentsX(), itemPos(mItems[i]), 0, 9.0 ); }   bool KMHeaders::prevUnreadMessage() { if ( !mFolder || !mFolder->countUnread() ) return false; int i = findUnread(false); if ( i < 0 && GlobalSettings::loopOnGotoUnread() != GlobalSettings::EnumLoopOnGotoUnread::DontLoop ) { KMHeaderItem * last = static_cast<KMHeaderItem*>(lastItem()); if ( last ) i = findUnread(false, last->msgId() ); } if ( i < 0 ) return false; setCurrentMsg(i); ensureCurrentItemVisible(); return true; }    void KMHeaders::slotNoDrag() { mMousePressed = false; }    void KMHeaders::makeHeaderVisible() { if (currentItem()) ensureItemVisible( currentItem() ); }   void KMHeaders::highlightMessage(QListViewItem* lvi, bool markitread) {  if (lvi && !lvi->isSelectable()) return;  KMHeaderItem *item = static_cast<KMHeaderItem*>(lvi); if (lvi != mPrevCurrent) { if (mPrevCurrent && mFolder) { KMMessage *prevMsg = mFolder->getMsg(mPrevCurrent->msgId()); if (prevMsg && mReaderWindowActive) { mFolder->ignoreJobsForMessage(prevMsg); if (!prevMsg->transferInProgress()) mFolder->unGetMsg(mPrevCurrent->msgId()); } } mPrevCurrent = item; }  if (!item) { emit selected( 0 ); return; }  int idx = item->msgId(); if (mReaderWindowActive) { KMMessage *msg = mFolder->getMsg(idx); if (!msg || msg->transferInProgress()) { emit selected( 0 ); mPrevCurrent = 0; return; } }  BroadcastStatus::instance()->setStatusMsg(""); if (markitread && idx >= 0) setMsgRead(idx); mItems[idx]->irefresh(); mItems[idx]->repaint(); emit selected(mFolder->getMsg(idx)); setFolderInfoStatus(); }  void KMHeaders::resetCurrentTime() { mDate.reset(); QTimer::singleShot( 1000, this, SLOT( resetCurrentTime() ) ); }   void KMHeaders::selectMessage(QListViewItem* lvi) { KMHeaderItem *item = static_cast<KMHeaderItem*>(lvi); if (!item) return;  int idx = item->msgId(); KMMessage *msg = mFolder->getMsg(idx); if (!msg->transferInProgress()) { emit activated(mFolder->getMsg(idx)); }    }    void KMHeaders::updateMessageList( bool set_selection, bool forceJumpToUnread ) { mPrevCurrent = 0; noRepaint = true; clear(); noRepaint = false; KListView::setSorting( mSortCol, !mSortDescending ); if (!mFolder) { mItems.resize(0); repaint(); return; } readSortOrder( set_selection, forceJumpToUnread ); emit messageListUpdated(); }                   void KMHeaders::keyPressEvent( QKeyEvent * e ) { bool cntrl = (e->state() & ControlButton ); bool shft = (e->state() & ShiftButton ); QListViewItem *cur = currentItem();  if (!e || !firstChild()) return;   if (!cur) { setCurrentItem( firstChild() ); setSelectionAnchor( currentItem() ); return; }   if (cur->isSelectable() && e->ascii() == ' ' ) { setSelected( cur, !cur->isSelected() ); highlightMessage( cur, false); return; }  if (cntrl) { if (!shft) disconnect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*))); switch (e->key()) { case Key_Down: case Key_Up: case Key_Home: case Key_End: case Key_Next: case Key_Prior: case Key_Escape: KListView::keyPressEvent( e ); } if (!shft) connect(this,SIGNAL(currentChanged(QListViewItem*)), this,SLOT(highlightMessage(QListViewItem*))); } }    void KMHeaders::rightButtonPressed( QListViewItem *lvi, const QPoint &, int ) { if (!lvi) return;  if (!(lvi->isSelected())) { clearSelection(); } setSelected( lvi, true ); slotRMB(); }   void KMHeaders::contentsMousePressEvent(QMouseEvent* e) { mPressPos = e->pos(); QListViewItem *lvi = itemAt( contentsToViewport( e->pos() )); bool wasSelected = false; bool rootDecoClicked = false; if (lvi) { wasSelected = lvi->isSelected(); rootDecoClicked = (  mPressPos.x() <= header()->cellPos(  header()->mapToActual(  0 ) ) + treeStepSize() * (  lvi->depth() + (  rootIsDecorated() ? 1 : 0 ) ) + itemMargin() ) && (  mPressPos.x() >= header()->cellPos(  header()->mapToActual(  0 ) ) );  if ( rootDecoClicked ) {     if ( !lvi->isOpen() && lvi->firstChild() ) { QListViewItem *nextRoot = lvi->itemBelow(); QListViewItemIterator it( lvi->firstChild() ); for( ; (*it) != nextRoot; ++it ) (*it)->setSelected( false ); } } }   KListView::contentsMousePressEvent(e);  if ( e->state() & ShiftButton ) { QListViewItemIterator it( this, QListViewItemIterator::Invisible ); while ( it.current() ) { it.current()->setSelected( false ); ++it; } }  if ( rootDecoClicked ) {  if ( lvi && !lvi->isOpen() && lvi->isSelected() ) setSelected( lvi, true ); }  if ( lvi && !rootDecoClicked ) { if ( lvi != currentItem() ) highlightMessage( lvi );    if ( !( e->state() & ControlButton ) && !wasSelected ) setSelected( lvi, true );  if ( e->state() & ControlButton ) setSelected( lvi, !wasSelected );  if ((e->button() == LeftButton) ) mMousePressed = true; } }   void KMHeaders::contentsMouseReleaseEvent(QMouseEvent* e) { if (e->button() != RightButton) KListView::contentsMouseReleaseEvent(e);  mMousePressed = false; }   void KMHeaders::contentsMouseMoveEvent( QMouseEvent* e ) { if (mMousePressed && (e->pos() - mPressPos).manhattanLength() > KGlobalSettings::dndEventDelay()) { mMousePressed = false; QListViewItem *item = itemAt( contentsToViewport(mPressPos) ); if ( item ) { MailList mailList; unsigned int count = 0; for( QListViewItemIterator it(this); it.current(); it++ ) if( it.current()->isSelected() ) { KMHeaderItem *item = static_cast<KMHeaderItem*>(it.current()); KMMsgBase *msg = mFolder->getMsgBase(item->msgId()); MailSummary mailSummary( msg->getMsgSerNum(), msg->msgIdMD5(), msg->subject(), msg->fromStrip(), msg->toStrip(), msg->date() ); mailList.append( mailSummary ); ++count; } MailListDrag *d = new MailListDrag( mailList, viewport() );   QPixmap pixmap; if( count == 1 ) pixmap = QPixmap( DesktopIcon("message", KIcon::SizeSmall) ); else pixmap = QPixmap( DesktopIcon("kmultiple", KIcon::SizeSmall) );   if( !pixmap.isNull() ) { QPoint hotspot( pixmap.width() / 2, pixmap.height() / 2 ); d->setPixmap( pixmap, hotspot ); } d->drag(); } } }  void KMHeaders::highlightMessage(QListViewItem* i) { highlightMessage( i, false ); }   void KMHeaders::slotRMB() { if (!topLevelWidget()) return;  QPopupMenu *menu = new QPopupMenu(this);  mMenuToFolder.clear();  mOwner->updateMessageMenu();  bool out_folder = kmkernel->folderIsDraftOrOutbox(mFolder); if ( out_folder ) mOwner->editAction()->plug(menu); else {  mOwner->replyAction()->plug(menu); mOwner->replyAllAction()->plug(menu); mOwner->replyAuthorAction()->plug( menu ); mOwner->replyListAction()->plug(menu); mOwner->forwardMenu()->plug(menu); mOwner->bounceAction()->plug(menu); mOwner->sendAgainAction()->plug(menu); } menu->insertSeparator();  QPopupMenu *msgCopyMenu = new QPopupMenu(menu); KMCopyCommand::folderToPopupMenu( false, this, &mMenuToFolder, msgCopyMenu ); menu->insertItem(i18n("&Copy To"), msgCopyMenu);  if ( mFolder->isReadOnly() ) { int id = menu->insertItem( i18n("&Move To") ); menu->setItemEnabled( id, false ); } else { QPopupMenu *msgMoveMenu = new QPopupMenu(menu); KMMoveCommand::folderToPopupMenu( true, this, &mMenuToFolder, msgMoveMenu ); menu->insertItem(i18n("&Move To"), msgMoveMenu); }  if ( !out_folder ) { mOwner->statusMenu()->plug( menu ); if ( mOwner->threadStatusMenu()->isEnabled() ) { mOwner->threadStatusMenu()->plug( menu ); } }  if (mOwner->watchThreadAction()->isEnabled() ) { menu->insertSeparator(); mOwner->watchThreadAction()->plug(menu); mOwner->ignoreThreadAction()->plug(menu); } menu->insertSeparator(); mOwner->trashAction()->plug(menu); mOwner->deleteAction()->plug(menu);  menu->insertSeparator(); mOwner->saveAsAction()->plug(menu); mOwner->saveAttachmentsAction()->plug(menu); mOwner->printAction()->plug(menu);  if ( !out_folder ) { menu->insertSeparator(); mOwner->action("apply_filters")->plug(menu); mOwner->filterMenu()->plug( menu ); }  mOwner->action("apply_filter_actions")->plug(menu);  KAcceleratorManager::manage(menu); kmkernel->setContextMenuShown( true ); menu->exec(QCursor::pos(), 0); kmkernel->setContextMenuShown( false ); delete menu; }   KMMessage* KMHeaders::currentMsg() { KMHeaderItem *hi = currentHeaderItem(); if (!hi) return 0; else return mFolder->getMsg(hi->msgId()); }   KMHeaderItem* KMHeaders::currentHeaderItem() { return static_cast<KMHeaderItem*>(currentItem()); }   int KMHeaders::currentItemIndex() { KMHeaderItem* item = currentHeaderItem(); if (item) return item->msgId(); else return -1; }   void KMHeaders::setCurrentItemByIndex(int msgIdx) { if ((msgIdx >= 0) && (msgIdx < (int)mItems.size())) { clearSelection(); bool unchanged = (currentItem() == mItems[msgIdx]); setCurrentItem( mItems[msgIdx] ); setSelected( mItems[msgIdx], true ); setSelectionAnchor( currentItem() ); if (unchanged) highlightMessage( mItems[msgIdx], false); } }   int KMHeaders::topItemIndex() { KMHeaderItem *item = static_cast<KMHeaderItem*>(itemAt(QPoint(1,1))); if (item) return item->msgId(); else return -1; }    void KMHeaders::showNewMail() { if (mSortCol != mPaintInfo.dateCol) return; for( int i = 0; i < (int)mItems.size(); ++i) if (mFolder->getMsgBase(i)->isNew()) { if (!mSortDescending) setTopItemByIndex( currentItemIndex() ); break; } }   void KMHeaders::setTopItemByIndex( int aMsgIdx) { int msgIdx = aMsgIdx; if (msgIdx < 0) msgIdx = 0; else if (msgIdx >= (int)mItems.size()) msgIdx = mItems.size() - 1; if ((msgIdx >= 0) && (msgIdx < (int)mItems.size())) setContentsPos( 0, itemPos( mItems[msgIdx] )); }   void KMHeaders::setNestedOverride( bool override ) { mSortInfo.dirty = true; mNestedOverride = override; setRootIsDecorated( nestingPolicy != AlwaysOpen && isThreaded() ); QString sortFile = mFolder->indexLocation() + ".sorted"; unlink(QFile::encodeName(sortFile)); reset(); }   void KMHeaders::setSubjectThreading( bool aSubjThreading ) { mSortInfo.dirty = true; mSubjThreading = aSubjThreading; QString sortFile = mFolder->indexLocation() + ".sorted"; unlink(QFile::encodeName(sortFile)); reset(); }   void KMHeaders::setOpen( QListViewItem *item, bool open ) { if ((nestingPolicy != AlwaysOpen)|| open) ((KMHeaderItem*)item)->setOpenRecursive( open ); }   const KMMsgBase* KMHeaders::getMsgBaseForItem( const QListViewItem *item ) const { const KMHeaderItem *hi = static_cast<const KMHeaderItem *> ( item ); return mFolder->getMsgBase( hi->msgId() ); }   void KMHeaders::setSorting( int column, bool ascending ) { if (column != -1) {    if(mSortInfo.dirty || column != mSortInfo.column || ascending != mSortInfo.ascending) { QObject::disconnect(header(), SIGNAL(clicked(int)), this, SLOT(dirtySortOrder(int))); mSortInfo.dirty = true; }  mSortCol = column; mSortDescending = !ascending;  if (!ascending && (column == mPaintInfo.dateCol)) mPaintInfo.orderOfArrival = !mPaintInfo.orderOfArrival;  if (!ascending && (column == mPaintInfo.subCol)) mPaintInfo.status = !mPaintInfo.status;  QString colText = i18n( "Date" ); if (mPaintInfo.orderOfArrival) colText = i18n( "Date (Order of Arrival)" ); setColumnText( mPaintInfo.dateCol, colText);  colText = i18n( "Subject" ); if (mPaintInfo.status) colText = colText + i18n( " (Status)" ); setColumnText( mPaintInfo.subCol, colText); } KListView::setSorting( column, ascending ); ensureCurrentItemVisible();   if ( mFolder ) { writeFolderConfig(); writeSortOrder(); } }   static void internalWriteItem(FILE *sortStream, KMFolder *folder, int msgid, int parent_id, QString key, bool update_discover=true) { unsigned long msgSerNum; unsigned long parentSerNum; msgSerNum = kmkernel->msgDict()->getMsgSerNum( folder, msgid ); if (parent_id >= 0) parentSerNum = kmkernel->msgDict()->getMsgSerNum( folder, parent_id ) + KMAIL_RESERVED; else parentSerNum = (unsigned long)(parent_id + KMAIL_RESERVED);  fwrite(&msgSerNum, sizeof(msgSerNum), 1, sortStream); fwrite(&parentSerNum, sizeof(parentSerNum), 1, sortStream); Q_INT32 len = key.length() * sizeof(QChar); fwrite(&len, sizeof(len), 1, sortStream); if (len) fwrite(key.unicode(), QMIN(len, KMAIL_MAX_KEY_LEN), 1, sortStream);  if (update_discover) {  Q_INT32 discovered_count = 0; fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 20, SEEK_SET); fread(&discovered_count, sizeof(discovered_count), 1, sortStream); discovered_count++; fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 20, SEEK_SET); fwrite(&discovered_count, sizeof(discovered_count), 1, sortStream); } }  void KMHeaders::folderCleared() { mSortCacheItems.clear(); mSubjectLists.clear(); mImperfectlyThreadedList.clear(); mPrevCurrent = 0; emit selected(0); }  bool KMHeaders::writeSortOrder() { QString sortFile = KMAIL_SORT_FILE(mFolder);  if (!mSortInfo.dirty) { struct stat stat_tmp; if(stat(QFile::encodeName(sortFile), &stat_tmp) == -1) { mSortInfo.dirty = true; } } if (mSortInfo.dirty) { if (!mFolder->count()) {  unlink(QFile::encodeName(sortFile)); return true; } QString tempName = sortFile + ".temp"; unlink(QFile::encodeName(tempName)); FILE *sortStream = fopen(QFile::encodeName(tempName), "w"); if (!sortStream) return false;  mSortInfo.ascending = !mSortDescending; mSortInfo.dirty = false; mSortInfo.column = mSortCol; fprintf(sortStream, KMAIL_SORT_HEADER, KMAIL_SORT_VERSION);  Q_INT32 byteOrder = 0x12345678; Q_INT32 column = mSortCol; Q_INT32 ascending= !mSortDescending; Q_INT32 threaded = isThreaded(); Q_INT32 appended=0; Q_INT32 discovered_count = 0; Q_INT32 sorted_count=0; fwrite(&byteOrder, sizeof(byteOrder), 1, sortStream); fwrite(&column, sizeof(column), 1, sortStream); fwrite(&ascending, sizeof(ascending), 1, sortStream); fwrite(&threaded, sizeof(threaded), 1, sortStream); fwrite(&appended, sizeof(appended), 1, sortStream); fwrite(&discovered_count, sizeof(discovered_count), 1, sortStream); fwrite(&sorted_count, sizeof(sorted_count), 1, sortStream);  QPtrStack<KMHeaderItem> items; { QPtrStack<QListViewItem> s; for (QListViewItem * i = firstChild(); i; ) { items.push((KMHeaderItem *)i); if ( i->firstChild() ) { s.push( i ); i = i->firstChild(); } else if( i->nextSibling()) { i = i->nextSibling(); } else { for(i=0; !i && s.count(); i = s.pop()->nextSibling()); } } }  KMMsgBase *kmb; while(KMHeaderItem *i = items.pop()) { int parent_id = -1; if (threaded) { kmb = mFolder->getMsgBase( i->mMsgId ); assert(kmb);  QString replymd5 = kmb->replyToIdMD5(); QString replyToAuxId = kmb->replyToAuxIdMD5(); KMSortCacheItem *p = NULL; if(!replymd5.isEmpty()) p = mSortCacheItems[replymd5];  if (p) parent_id = p->id();      if (replymd5.isEmpty() && replyToAuxId.isEmpty() && !kmb->subjectIsPrefixed() ) parent_id = -2;    } internalWriteItem(sortStream, mFolder, i->mMsgId, parent_id, i->key(mSortCol, !mSortDescending), false);  sorted_count++; }   fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET, SEEK_SET); fwrite(&byteOrder, sizeof(byteOrder), 1, sortStream); fwrite(&column, sizeof(column), 1, sortStream); fwrite(&ascending, sizeof(ascending), 1, sortStream); fwrite(&threaded, sizeof(threaded), 1, sortStream); fwrite(&appended, sizeof(appended), 1, sortStream); fwrite(&discovered_count, sizeof(discovered_count), 1, sortStream); fwrite(&sorted_count, sizeof(sorted_count), 1, sortStream); if (sortStream && ferror(sortStream)) { fclose(sortStream); unlink(QFile::encodeName(sortFile)); kdWarning(5006) << "Error: Failure modifying " << sortFile << " (No space left on device?)" << endl; kdWarning(5006) << __FILE__ << ":" << __LINE__ << endl; kmkernel->emergencyExit( i18n("Failure modifying %1\n(No space left on device?)").arg( sortFile )); } fclose(sortStream); ::rename(QFile::encodeName(tempName), QFile::encodeName(sortFile)); }  return true; }  void KMHeaders::appendItemToSortFile(KMHeaderItem *khi) { QString sortFile = KMAIL_SORT_FILE(mFolder); if(FILE *sortStream = fopen(QFile::encodeName(sortFile), "r+")) { int parent_id = -1;  if (isThreaded()) { KMSortCacheItem *sci = khi->sortCacheItem(); KMMsgBase *kmb = mFolder->getMsgBase( khi->mMsgId ); if(sci->parent() && !sci->isImperfectlyThreaded()) parent_id = sci->parent()->id(); else if(kmb->replyToIdMD5().isEmpty() && kmb->replyToAuxIdMD5().isEmpty() && !kmb->subjectIsPrefixed()) parent_id = -2; }  internalWriteItem(sortStream, mFolder, khi->mMsgId, parent_id, khi->key(mSortCol, !mSortDescending), false);   Q_INT32 appended = 1; fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET); fwrite(&appended, sizeof(appended), 1, sortStream); fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);  if (sortStream && ferror(sortStream)) { fclose(sortStream); unlink(QFile::encodeName(sortFile)); kdWarning(5006) << "Error: Failure modifying " << sortFile << " (No space left on device?)" << endl; kdWarning(5006) << __FILE__ << ":" << __LINE__ << endl; kmkernel->emergencyExit( i18n("Failure modifying %1\n(No space left on device?)").arg( sortFile )); } fclose(sortStream); } else { mSortInfo.dirty = true; } }  void KMHeaders::dirtySortOrder(int column) { mSortInfo.dirty = true; QObject::disconnect(header(), SIGNAL(clicked(int)), this, SLOT(dirtySortOrder(int))); setSorting(column, mSortInfo.column == column ? !mSortInfo.ascending : true); } void KMSortCacheItem::updateSortFile( FILE *sortStream, KMFolder *folder, bool waiting_for_parent, bool update_discover) { if(mSortOffset == -1) { fseek(sortStream, 0, SEEK_END); mSortOffset = ftell(sortStream); } else { fseek(sortStream, mSortOffset, SEEK_SET); }  int parent_id = -1; if(!waiting_for_parent) { if(mParent && !isImperfectlyThreaded()) parent_id = mParent->id(); } internalWriteItem(sortStream, folder, mId, parent_id, mKey, update_discover); }  static bool compare_ascending = false; static bool compare_toplevel = true; static int compare_KMSortCacheItem(const void *s1, const void *s2) { if ( !s1 || !s2 ) return 0; KMSortCacheItem **b1 = (KMSortCacheItem **)s1; KMSortCacheItem **b2 = (KMSortCacheItem **)s2; int ret = (*b1)->key().compare((*b2)->key()); if(compare_ascending || !compare_toplevel) ret = -ret; return ret; }   void KMHeaders::buildThreadingTree( QMemArray<KMSortCacheItem *> sortCache ) { mSortCacheItems.clear(); mSortCacheItems.resize( mFolder->count() * 2 );   for(int x = 0; x < mFolder->count(); x++) { KMMsgBase *mi = mFolder->getMsgBase(x); QString md5 = mi->msgIdMD5(); if(!md5.isEmpty()) mSortCacheItems.replace(md5, sortCache[x]); } }   void KMHeaders::buildSubjectThreadingTree( QMemArray<KMSortCacheItem *> sortCache ) { mSubjectLists.clear(); mSubjectLists.resize( mFolder->count() * 2 );  for(int x = 0; x < mFolder->count(); x++) {  if ( sortCache[x]->parent() && sortCache[x]->parent()->id() != -666 ) continue; KMMsgBase *mi = mFolder->getMsgBase(x); QString subjMD5 = mi->strippedSubjectMD5(); if (subjMD5.isEmpty()) { mFolder->getMsgBase(x)->initStrippedSubjectMD5(); subjMD5 = mFolder->getMsgBase(x)->strippedSubjectMD5(); } if( subjMD5.isEmpty() ) continue;   if (!mSubjectLists.find(subjMD5)) mSubjectLists.insert(subjMD5, new QPtrList<KMSortCacheItem>());  int p=0; for (QPtrListIterator<KMSortCacheItem> it(*mSubjectLists[subjMD5]); it.current(); ++it) { KMMsgBase *mb = mFolder->getMsgBase((*it)->id()); if ( mb->date() < mi->date()) break; p++; } mSubjectLists[subjMD5]->insert( p, sortCache[x]); } }   KMSortCacheItem* KMHeaders::findParent(KMSortCacheItem *item) { KMSortCacheItem *parent = NULL; if (!item) return parent; KMMsgBase *msg =  mFolder->getMsgBase(item->id()); QString replyToIdMD5 = msg->replyToIdMD5(); item->setImperfectlyThreaded(true);  if(!replyToIdMD5.isEmpty()) { parent = mSortCacheItems[replyToIdMD5]; if (parent) item->setImperfectlyThreaded(false); } if (!parent) {       QString  ref = msg->replyToAuxIdMD5(); if (!ref.isEmpty()) parent = mSortCacheItems[ref]; } return parent; }  KMSortCacheItem* KMHeaders::findParentBySubject(KMSortCacheItem *item) { KMSortCacheItem *parent = NULL; if (!item) return parent;  KMMsgBase *msg =  mFolder->getMsgBase(item->id());     if (!msg->subjectIsPrefixed()) return parent;  QString replyToIdMD5 = msg->replyToIdMD5(); QString subjMD5 = msg->strippedSubjectMD5(); if (!subjMD5.isEmpty() && mSubjectLists[subjMD5]) {  for (QPtrListIterator<KMSortCacheItem> it2(*mSubjectLists[subjMD5]); it2.current(); ++it2) { KMMsgBase *mb = mFolder->getMsgBase((*it2)->id()); if ( !mb ) return parent;  if ( item == (*it2) ) continue; int delta = msg->date() - mb->date();   if (delta > 0 ) {  if (delta < 3628899) parent = (*it2); break; } } } return parent; }  bool KMHeaders::readSortOrder( bool set_selection, bool forceJumpToUnread ) {  Q_INT32 column, ascending, threaded, discovered_count, sorted_count, appended; Q_INT32 deleted_count = 0; bool unread_exists = false; bool jumpToUnread = (GlobalSettings::actionEnterFolder() == GlobalSettings::EnumActionEnterFolder::SelectFirstUnreadNew) || forceJumpToUnread; QMemArray<KMSortCacheItem *> sortCache(mFolder->count()); KMSortCacheItem root; root.setId(-666); bool error = false;   QPtrList<KMSortCacheItem> unparented; mImperfectlyThreadedList.clear();   mItems.fill( 0, mFolder->count() ); sortCache.fill( 0 );  QString sortFile = KMAIL_SORT_FILE(mFolder); FILE *sortStream = fopen(QFile::encodeName(sortFile), "r+"); mSortInfo.fakeSort = 0;  if(sortStream) { mSortInfo.fakeSort = 1; int version = 0; if (fscanf(sortStream, KMAIL_SORT_HEADER, &version) != 1) version = -1; if(version == KMAIL_SORT_VERSION) { Q_INT32 byteOrder = 0; fread(&byteOrder, sizeof(byteOrder), 1, sortStream); if (byteOrder == 0x12345678) { fread(&column, sizeof(column), 1, sortStream); fread(&ascending, sizeof(ascending), 1, sortStream); fread(&threaded, sizeof(threaded), 1, sortStream); fread(&appended, sizeof(appended), 1, sortStream); fread(&discovered_count, sizeof(discovered_count), 1, sortStream); fread(&sorted_count, sizeof(sorted_count), 1, sortStream);   KListView::setSorting(-1); header()->setSortIndicator(column, ascending); QObject::connect(header(), SIGNAL(clicked(int)), this, SLOT(dirtySortOrder(int)));  mSortInfo.dirty = false; mSortInfo.column = (short)column; mSortInfo.ascending = (compare_ascending = ascending);  KMSortCacheItem *item; unsigned long serNum, parentSerNum; int id, len, parent, x; QChar *tmp_qchar = 0; int tmp_qchar_len = 0; const int mFolderCount = mFolder->count(); QString key;  CREATE_TIMER(parse); START_TIMER(parse); for(x = 0; !feof(sortStream) && !error; x++) { off_t offset = ftell(sortStream); KMFolder *folder;  if(!fread(&serNum, sizeof(serNum), 1, sortStream) || !fread(&parentSerNum, sizeof(parentSerNum), 1, sortStream) || !fread(&len, sizeof(len), 1, sortStream)) { break; } if ((len < 0) || (len > KMAIL_MAX_KEY_LEN)) { kdDebug(5006) << "Whoa.2! len " << len << " " << __FILE__ << ":" << __LINE__ << endl; error = true; continue; } if(len) { if(len > tmp_qchar_len) { tmp_qchar = (QChar *)realloc(tmp_qchar, len); tmp_qchar_len = len; } if(!fread(tmp_qchar, len, 1, sortStream)) break; key = QString(tmp_qchar, len / 2); } else { key = QString(""); }  kmkernel->msgDict()->getLocation(serNum, &folder, &id); if (folder != mFolder) { ++deleted_count; continue; } if (parentSerNum < KMAIL_RESERVED) { parent = (int)parentSerNum - KMAIL_RESERVED; } else { kmkernel->msgDict()->getLocation(parentSerNum - KMAIL_RESERVED, &folder, &parent); if (folder != mFolder) parent = -1; } if ((id < 0) || (id >= mFolderCount) || (parent < -2) || (parent >= mFolderCount)) { kdDebug(5006) << "Whoa.1! " << __FILE__ << ":" << __LINE__ << endl; error = true; continue; }  if ((item=sortCache[id])) { if (item->id() != -1) { kdDebug(5006) << "Whoa.3! " << __FILE__ << ":" << __LINE__ << endl; error = true; continue; } item->setKey(key); item->setId(id); item->setOffset(offset); } else { item = sortCache[id] = new KMSortCacheItem(id, key, offset); } if (threaded && parent != -2) { if(parent == -1) { unparented.append(item); root.addUnsortedChild(item); } else { if( ! sortCache[parent] ) sortCache[parent] = new KMSortCacheItem; sortCache[parent]->addUnsortedChild(item); } } else { if(x < sorted_count ) root.addSortedChild(item); else { root.addUnsortedChild(item); } } } if (error || (x != sorted_count + discovered_count)) { kdDebug(5006) << endl << "Whoa: x " << x << ", sorted_count " << sorted_count << ", discovered_count " << discovered_count << ", count " << mFolder->count() << endl << endl; fclose(sortStream); sortStream = 0; }  if(tmp_qchar) free(tmp_qchar); END_TIMER(parse); SHOW_TIMER(parse); } else { fclose(sortStream); sortStream = 0; } } else { fclose(sortStream); sortStream = 0; } }  if (!sortStream) { mSortInfo.dirty = true; mSortInfo.column = column = mSortCol; mSortInfo.ascending = ascending = !mSortDescending; threaded = (isThreaded()); sorted_count = discovered_count = appended = 0; KListView::setSorting( mSortCol, !mSortDescending ); }  if((sorted_count + discovered_count - deleted_count) < mFolder->count()) { CREATE_TIMER(holes); START_TIMER(holes); KMMsgBase *msg = 0; for(int x = 0; x < mFolder->count(); x++) { if((!sortCache[x] || (sortCache[x]->id() < 0)) && (msg=mFolder->getMsgBase(x))) { int sortOrder = column; if (mPaintInfo.orderOfArrival) sortOrder |= (1 << 6); if (mPaintInfo.status) sortOrder |= (1 << 5); sortCache[x] = new KMSortCacheItem( x, KMHeaderItem::generate_key( this, msg, &mPaintInfo, sortOrder )); if(threaded) unparented.append(sortCache[x]); else root.addUnsortedChild(sortCache[x]); if(sortStream) sortCache[x]->updateSortFile(sortStream, mFolder, true, true); discovered_count++; appended = 1; } } END_TIMER(holes); SHOW_TIMER(holes); }    if (threaded) buildThreadingTree( sortCache ); QPtrList<KMSortCacheItem> toBeSubjThreaded;  if (threaded && !unparented.isEmpty()) { CREATE_TIMER(reparent); START_TIMER(reparent);  for(QPtrListIterator<KMSortCacheItem> it(unparented); it.current(); ++it) { KMSortCacheItem *item = (*it); KMSortCacheItem *parent = findParent( item );  if ( parent && (parent != (*it)) ) { parent->addUnsortedChild((*it)); if(sortStream) (*it)->updateSortFile(sortStream, mFolder); } else {   if (mSubjThreading) toBeSubjThreaded.append((*it)); else root.addUnsortedChild((*it)); } }  if (mSubjThreading) { buildSubjectThreadingTree( sortCache ); for(QPtrListIterator<KMSortCacheItem> it(toBeSubjThreaded); it.current(); ++it) { KMSortCacheItem *item = (*it); KMSortCacheItem *parent = findParentBySubject( item );  if ( parent ) { parent->addUnsortedChild((*it)); if(sortStream) (*it)->updateSortFile(sortStream, mFolder); } else {  root.addUnsortedChild((*it)); } } } END_TIMER(reparent); SHOW_TIMER(reparent); }  CREATE_TIMER(header_creation); START_TIMER(header_creation); KMHeaderItem *khi; KMSortCacheItem *i, *new_kci; QPtrQueue<KMSortCacheItem> s; s.enqueue(&root); compare_toplevel = true; do { i = s.dequeue(); const QPtrList<KMSortCacheItem> *sorted = i->sortedChildren(); int unsorted_count, unsorted_off=0; KMSortCacheItem **unsorted = i->unsortedChildren(unsorted_count); if(unsorted) qsort(unsorted, unsorted_count, sizeof(KMSortCacheItem *), compare_KMSortCacheItem);   for(QPtrListIterator<KMSortCacheItem> it(*sorted); (unsorted && unsorted_off < unsorted_count) || it.current(); ) {  if( it.current() && ( !unsorted || unsorted_off >= unsorted_count || ( ( !ascending || (ascending && !compare_toplevel) ) && (*it)->key() < unsorted[unsorted_off]->key() ) || (  ascending && (*it)->key() >= unsorted[unsorted_off]->key() ) ) ) { new_kci = (*it); ++it; } else {  new_kci = unsorted[unsorted_off++]; } if(new_kci->item() || new_kci->parent() != i) continue;  if(threaded && i->item()) {   if (mFolder->getMsgBase(i->id())->isWatched()) mFolder->getMsgBase(new_kci->id())->setStatus(KMMsgStatusWatched); if (mFolder->getMsgBase(i->id())->isIgnored()) { mFolder->getMsgBase(new_kci->id())->setStatus(KMMsgStatusIgnored); mFolder->setStatus(new_kci->id(), KMMsgStatusRead); } khi = new KMHeaderItem(i->item(), new_kci->id(), new_kci->key()); } else { khi = new KMHeaderItem(this, new_kci->id(), new_kci->key()); } new_kci->setItem(mItems[new_kci->id()] = khi); if(new_kci->hasChildren()) s.enqueue(new_kci);   if ( ( mFolder->getMsgBase(new_kci->id())->isNew() && GlobalSettings::actionEnterFolder() == GlobalSettings::EnumActionEnterFolder::SelectFirstNew ) || ( mFolder->getMsgBase(new_kci->id())->isUnread() && jumpToUnread ) ) { unread_exists = true; } }    if (mSortCol == paintInfo()->dateCol) compare_toplevel = false; } while(!s.isEmpty());  for(int x = 0; x < mFolder->count(); x++) { if (!sortCache[x]) { continue; }  if (!sortCache[x]->item()) { kdDebug(5006) << "KMHeaders::readSortOrder - msg could not be threaded. " << endl << "Please talk to your threading counselor asap. " <<  endl; khi = new KMHeaderItem(this, sortCache[x]->id(), sortCache[x]->key()); sortCache[x]->setItem(mItems[sortCache[x]->id()] = khi); }    if (threaded && sortCache[x]->isImperfectlyThreaded()) { mImperfectlyThreadedList.append(sortCache[x]->item()); }   sortCache[x]->item()->setSortCacheItem(sortCache[x]); }  if (getNestingPolicy()<2) for (KMHeaderItem *khi=static_cast<KMHeaderItem*>(firstChild()); khi!=0;khi=static_cast<KMHeaderItem*>(khi->nextSibling())) khi->setOpen(true);  END_TIMER(header_creation); SHOW_TIMER(header_creation);  if(sortStream) {  if( discovered_count * discovered_count > sorted_count - deleted_count ) { mSortInfo.dirty = true; } else {  appended = 0; fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET); fwrite(&appended, sizeof(appended), 1, sortStream); } }   CREATE_TIMER(selection); START_TIMER(selection); if(set_selection) { int first_unread = -1; if (unread_exists) { KMHeaderItem *item = static_cast<KMHeaderItem*>(firstChild()); while (item) { if ( ( mFolder->getMsgBase(item->msgId())->isNew() && GlobalSettings::actionEnterFolder() == GlobalSettings::EnumActionEnterFolder::SelectFirstNew ) || ( mFolder->getMsgBase(item->msgId())->isUnread() && jumpToUnread ) ) { first_unread = item->msgId(); break; } item = static_cast<KMHeaderItem*>(item->itemBelow()); } }  if(first_unread == -1 ) { setTopItemByIndex(mTopItem); if ( mCurrentItem >= 0 ) setCurrentItemByIndex( mCurrentItem ); else if ( mCurrentItemSerNum > 0 ) setCurrentItemBySerialNum( mCurrentItemSerNum ); else setCurrentItemByIndex( 0 ); } else { setCurrentItemByIndex(first_unread); makeHeaderVisible(); center( contentsX(), itemPos(mItems[first_unread]), 0, 9.0 ); } } else {  if (mCurrentItem <= 0) { setTopItemByIndex(mTopItem); setCurrentItemByIndex(0); } } END_TIMER(selection); SHOW_TIMER(selection); if (error || (sortStream && ferror(sortStream))) { if ( sortStream ) fclose(sortStream); unlink(QFile::encodeName(sortFile)); kdWarning(5006) << "Error: Failure modifying " << sortFile << " (No space left on device?)" << endl; kdWarning(5006) << __FILE__ << ":" << __LINE__ << endl;  } if(sortStream) fclose(sortStream);  return true; }   void KMHeaders::setCurrentItemBySerialNum( unsigned long serialNum ) {    for (int i = 0; i < (int)mItems.size() - 1; ++i) { KMMsgBase *mMsgBase = mFolder->getMsgBase( i ); if ( mMsgBase->getMsgSerNum() == serialNum ) { bool unchanged = (currentItem() == mItems[i]); setCurrentItem( mItems[i] ); setSelected( mItems[i], true ); setSelectionAnchor( currentItem() ); if ( unchanged ) highlightMessage( currentItem(), false ); ensureCurrentItemVisible(); return; } }  kdDebug(5006) << "KMHeaders::setCurrentItem item with serial number " << serialNum << " NOT FOUND" << endl; }  #include "kmheaders.moc"
context:   static QString generate_key( KMHeaders *headers, KMMsgBase *msg, const KPaintInfo *paintInfo, int sortOrder )  {    // It appears, that QListView in Qt-3.0 asks for the key    // in QListView::clear(), which is called from    // readSortOrder()    if (!msg) return QString::null;    int column = sortOrder & ((1 << 5) - 1);    QString ret = QChar( (char)sortOrder );    QString sortArrival = QString( "%1" ).arg( msg->getMsgSerNum(), 0, 36 );    while (sortArrival.length() < 7) sortArrival = '0' + sortArrival;    if (column == paintInfo->dateCol) {      if (paintInfo->orderOfArrival)        return ret + sortArrival;      else {        QString d = QString::number(msg->date());        while (d.length() <= 10) d = '0' + d;        return ret + d + sortArrival;      }    } else if (column == paintInfo->senderCol) {      QString tmp;      if (headers->folder()->whoField().lower() == "to")        tmp = msg->toStrip();      else        tmp = msg->fromStrip();      return ret + tmp.lower() + ' ' + sortArrival;    } else if (column == paintInfo->subCol) {      QString tmp;      tmp = ret;      if (paintInfo->status) {        tmp += msg->statusToSortRank() + ' ';      }      tmp += KMMessage::stripOffPrefixes( msg->subject().lower() ) + ' ' + sortArrival;      return tmp;    }    else if (column == paintInfo->sizeCol) {      QString len;      if ( msg->parent()->folderType() == KMFolderTypeImap )      {        len = QString::number( msg->msgSizeServer() );      } else {        len = QString::number( msg->msgSize() );      }      while (len.length() < 9) len = '0' + len;      return ret + len + sortArrival;    }    return ret + "missing key"; //you forgot something!!  }