7 #include "headeritem.h" 10 #include "kcursorsaver.h" 11 #include "kmcommands.h" 12 #include "kmmainwidget.h" 13 #include "kmfiltermgr.h" 14 #include "undostack.h" 15 #include "kmmsgdict.h" 17 #include "kmfoldertree.h" 18 #include "folderjob.h" 19 using KMail::FolderJob;
20 #include "actionscheduler.h" 21 using KMail::ActionScheduler;
22 #include "messagecopyhelper.h" 24 #include "broadcaststatus.h" 25 using KPIM::BroadcastStatus;
26 #include "progressmanager.h" 27 using KPIM::ProgressManager;
28 using KPIM::ProgressItem;
29 #include <maillistdrag.h> 30 #include "globalsettings.h" 32 #include "messageactions.h" 34 #include <tdeapplication.h> 35 #include <tdeaccelmanager.h> 36 #include <tdeglobalsettings.h> 37 #include <tdemessagebox.h> 38 #include <kiconloader.h> 39 #include <tdepopupmenu.h> 41 #include <tdeconfig.h> 42 #include <tdelocale.h> 46 #include <tqeventloop.h> 49 #include <tqptrstack.h> 50 #include <tqptrqueue.h> 51 #include <tqpainter.h> 52 #include <tqtextcodec.h> 54 #include <tqlistview.h> 56 #include <mimelib/enum.h> 57 #include <mimelib/field.h> 58 #include <mimelib/mimepp.h> 63 #include "textsource.h" 65 TQPixmap* KMHeaders::pixNew = 0;
66 TQPixmap* KMHeaders::pixUns = 0;
67 TQPixmap* KMHeaders::pixDel = 0;
68 TQPixmap* KMHeaders::pixRead = 0;
69 TQPixmap* KMHeaders::pixRep = 0;
70 TQPixmap* KMHeaders::pixQueued = 0;
71 TQPixmap* KMHeaders::pixTodo = 0;
72 TQPixmap* KMHeaders::pixSent = 0;
73 TQPixmap* KMHeaders::pixFwd = 0;
74 TQPixmap* KMHeaders::pixFlag = 0;
75 TQPixmap* KMHeaders::pixWatched = 0;
76 TQPixmap* KMHeaders::pixIgnored = 0;
77 TQPixmap* KMHeaders::pixSpam = 0;
78 TQPixmap* KMHeaders::pixHam = 0;
79 TQPixmap* KMHeaders::pixFullySigned = 0;
80 TQPixmap* KMHeaders::pixPartiallySigned = 0;
81 TQPixmap* KMHeaders::pixUndefinedSigned = 0;
82 TQPixmap* KMHeaders::pixFullyEncrypted = 0;
83 TQPixmap* KMHeaders::pixPartiallyEncrypted = 0;
84 TQPixmap* KMHeaders::pixUndefinedEncrypted = 0;
85 TQPixmap* KMHeaders::pixEncryptionProblematic = 0;
86 TQPixmap* KMHeaders::pixSignatureProblematic = 0;
87 TQPixmap* KMHeaders::pixAttachment = 0;
88 TQPixmap* KMHeaders::pixInvitation = 0;
89 TQPixmap* KMHeaders::pixReadFwd = 0;
90 TQPixmap* KMHeaders::pixReadReplied = 0;
91 TQPixmap* KMHeaders::pixReadFwdReplied = 0;
95 KMHeaders::KMHeaders(KMMainWidget *aOwner, TQWidget *parent,
97 TDEListView( parent, name ),
98 mIgnoreSortOrderChanges( false )
100 static bool pixmapsLoaded =
false;
102 KImageIO::registerFormats();
108 setSelectionMode( TQListView::Extended );
109 setAllColumnsShowFocus(
true );
111 nestingPolicy = OpenUnread;
112 mNestedOverride =
false;
113 mSubjThreading =
true;
114 mMousePressed =
false;
115 mSortInfo.dirty =
true;
116 mSortInfo.fakeSort = 0;
117 mSortInfo.removed = 0;
118 mSortInfo.column = 0;
120 mSortDescending =
false;
121 mSortInfo.ascending =
false;
122 mReaderWindowActive =
false;
125 setStyleDependantFrameWidth();
127 header()->setClickEnabled(
true);
128 header()->installEventFilter(
this);
129 mPopup =
new TDEPopupMenu(
this);
130 mPopup->insertTitle(i18n(
"View Columns"));
131 mPopup->setCheckable(
true);
132 mPopup->insertItem(i18n(
"Status"), KPaintInfo::COL_STATUS);
133 mPopup->insertItem(i18n(
"Important"), KPaintInfo::COL_IMPORTANT);
134 mPopup->insertItem(i18n(
"Action Item"), KPaintInfo::COL_TODO);
135 mPopup->insertItem(i18n(
"Attachment"), KPaintInfo::COL_ATTACHMENT);
136 mPopup->insertItem(i18n(
"Invitation"), KPaintInfo::COL_INVITATION);
137 mPopup->insertItem(i18n(
"Spam/Ham"), KPaintInfo::COL_SPAM_HAM);
138 mPopup->insertItem(i18n(
"Watched/Ignored"), KPaintInfo::COL_WATCHED_IGNORED);
139 mPopup->insertItem(i18n(
"Signature"), KPaintInfo::COL_SIGNED);
140 mPopup->insertItem(i18n(
"Encryption"), KPaintInfo::COL_CRYPTO);
141 mPopup->insertItem(i18n(
"Size"), KPaintInfo::COL_SIZE);
142 mPopup->insertItem(i18n(
"Receiver"), KPaintInfo::COL_RECEIVER);
144 connect(mPopup, TQT_SIGNAL(activated(
int)),
this, TQT_SLOT(slotToggleColumn(
int)));
146 setShowSortIndicator(
true);
147 setFocusPolicy( TQ_WheelFocus );
151 pixmapsLoaded =
true;
152 pixNew =
new TQPixmap( UserIcon(
"kmmsgnew" ) );
153 pixUns =
new TQPixmap( UserIcon(
"kmmsgunseen" ) );
154 pixDel =
new TQPixmap( UserIcon(
"kmmsgdel" ) );
155 pixRead =
new TQPixmap( UserIcon(
"kmmsgread" ) );
156 pixRep =
new TQPixmap( UserIcon(
"kmmsgreplied" ) );
157 pixQueued =
new TQPixmap( UserIcon(
"kmmsgqueued" ) );
158 pixTodo =
new TQPixmap( UserIcon(
"kmmsgtodo" ) );
159 pixSent =
new TQPixmap( UserIcon(
"kmmsgsent" ) );
160 pixFwd =
new TQPixmap( UserIcon(
"kmmsgforwarded" ) );
161 pixFlag =
new TQPixmap( UserIcon(
"kmmsgflag" ) );
162 pixWatched =
new TQPixmap( UserIcon(
"kmmsgwatched" ) );
163 pixIgnored =
new TQPixmap( UserIcon(
"kmmsgignored" ) );
164 pixSpam =
new TQPixmap( UserIcon(
"kmmsgspam" ) );
165 pixHam =
new TQPixmap( UserIcon(
"kmmsgham" ) );
166 pixFullySigned =
new TQPixmap( UserIcon(
"kmmsgfullysigned" ) );
167 pixPartiallySigned =
new TQPixmap( UserIcon(
"kmmsgpartiallysigned" ) );
168 pixUndefinedSigned =
new TQPixmap( UserIcon(
"kmmsgundefinedsigned" ) );
169 pixFullyEncrypted =
new TQPixmap( UserIcon(
"kmmsgfullyencrypted" ) );
170 pixPartiallyEncrypted =
new TQPixmap( UserIcon(
"kmmsgpartiallyencrypted" ) );
171 pixUndefinedEncrypted =
new TQPixmap( UserIcon(
"kmmsgundefinedencrypted" ) );
172 pixEncryptionProblematic =
new TQPixmap( UserIcon(
"kmmsgencryptionproblematic" ) );
173 pixSignatureProblematic =
new TQPixmap( UserIcon(
"kmmsgsignatureproblematic" ) );
174 pixAttachment =
new TQPixmap( UserIcon(
"kmmsgattachment" ) );
175 pixInvitation =
new TQPixmap( UserIcon(
"kmmsginvitation" ) );
176 pixReadFwd =
new TQPixmap( UserIcon(
"kmmsgread_fwd" ) );
177 pixReadReplied =
new TQPixmap( UserIcon(
"kmmsgread_replied" ) );
178 pixReadFwdReplied =
new TQPixmap( UserIcon(
"kmmsgread_fwd_replied" ) );
181 header()->setStretchEnabled(
false );
182 header()->setResizeEnabled(
false );
184 mPaintInfo.subCol = addColumn( i18n(
"Subject"), 310 );
185 mPaintInfo.senderCol = addColumn( i18n(
"Sender"), 170 );
186 mPaintInfo.dateCol = addColumn( i18n(
"Date"), 170 );
187 mPaintInfo.sizeCol = addColumn( i18n(
"Size"), 0 );
188 mPaintInfo.receiverCol = addColumn( i18n(
"Receiver"), 0 );
190 mPaintInfo.statusCol = addColumn( *pixNew ,
"", 0 );
191 mPaintInfo.importantCol = addColumn( *pixFlag ,
"", 0 );
192 mPaintInfo.todoCol = addColumn( *pixTodo ,
"", 0 );
193 mPaintInfo.attachmentCol = addColumn( *pixAttachment ,
"", 0 );
194 mPaintInfo.invitationCol = addColumn( *pixInvitation ,
"", 0 );
195 mPaintInfo.spamHamCol = addColumn( *pixSpam ,
"", 0 );
196 mPaintInfo.watchedIgnoredCol = addColumn( *pixWatched ,
"", 0 );
197 mPaintInfo.signedCol = addColumn( *pixFullySigned ,
"", 0 );
198 mPaintInfo.cryptoCol = addColumn( *pixFullyEncrypted,
"", 0 );
200 setResizeMode( TQListView::NoColumn );
203 header()->setResizeEnabled(
true, mPaintInfo.subCol );
204 header()->setResizeEnabled(
true, mPaintInfo.senderCol );
205 header()->setResizeEnabled(
true, mPaintInfo.dateCol );
207 connect(
this, TQT_SIGNAL( contextMenuRequested( TQListViewItem*,
const TQPoint &,
int )),
208 this, TQT_SLOT( rightButtonPressed( TQListViewItem*,
const TQPoint &,
int )));
209 connect(
this, TQT_SIGNAL(doubleClicked(TQListViewItem*)),
210 this,TQT_SLOT(selectMessage(TQListViewItem*)));
211 connect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
212 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
215 mSubjectLists.setAutoDelete(
true );
217 mMoveMessages =
false;
218 connect(
this, TQT_SIGNAL(selectionChanged()), TQT_SLOT(updateActions()) );
223 KMHeaders::~KMHeaders ()
229 mFolder->
close(
"kmheaders");
236 bool KMHeaders::eventFilter ( TQObject *o, TQEvent *e )
238 if ( e->type() == TQEvent::MouseButtonPress &&
239 TQT_TQMOUSEEVENT(e)->button() == Qt::RightButton &&
240 o->isA(TQHEADER_OBJECT_NAME_STRING) )
244 if ( mPaintInfo.showReceiver )
245 mPopup->changeItem(KPaintInfo::COL_RECEIVER, i18n(
"Receiver"));
247 if ( mFolder && (mFolder->
whoField().lower() ==
"to") )
248 mPopup->changeItem(KPaintInfo::COL_RECEIVER, i18n(
"Sender"));
250 mPopup->changeItem(KPaintInfo::COL_RECEIVER, i18n(
"Receiver"));
252 mPopup->popup( TQT_TQMOUSEEVENT(e)->globalPos() );
255 return TDEListView::eventFilter(o, e);
267 switch ( static_cast<KPaintInfo::ColumnIds>(
id) )
269 case KPaintInfo::COL_SIZE:
271 show = &mPaintInfo.showSize;
272 col = &mPaintInfo.sizeCol;
276 case KPaintInfo::COL_ATTACHMENT:
278 show = &mPaintInfo.showAttachment;
279 col = &mPaintInfo.attachmentCol;
280 width = pixAttachment->width() + 8;
281 if ( *col == header()->mapToIndex( *col ) )
285 case KPaintInfo::COL_INVITATION:
287 show = &mPaintInfo.showInvitation;
288 col = &mPaintInfo.invitationCol;
289 width = pixAttachment->width() + 8;
290 if ( *col == header()->mapToIndex( *col ) )
294 case KPaintInfo::COL_IMPORTANT:
296 show = &mPaintInfo.showImportant;
297 col = &mPaintInfo.importantCol;
298 width = pixFlag->width() + 8;
299 if ( *col == header()->mapToIndex( *col ) )
303 case KPaintInfo::COL_TODO:
305 show = &mPaintInfo.showTodo;
306 col = &mPaintInfo.todoCol;
307 width = pixTodo->width() + 8;
308 if ( *col == header()->mapToIndex( *col ) )
312 case KPaintInfo::COL_SPAM_HAM:
314 show = &mPaintInfo.showSpamHam;
315 col = &mPaintInfo.spamHamCol;
316 width = pixSpam->width() + 8;
317 if ( *col == header()->mapToIndex( *col ) )
321 case KPaintInfo::COL_WATCHED_IGNORED:
323 show = &mPaintInfo.showWatchedIgnored;
324 col = &mPaintInfo.watchedIgnoredCol;
325 width = pixWatched->width() + 8;
326 if ( *col == header()->mapToIndex( *col ) )
330 case KPaintInfo::COL_STATUS:
332 show = &mPaintInfo.showStatus;
333 col = &mPaintInfo.statusCol;
334 width = pixNew->width() + 8;
335 if ( *col == header()->mapToIndex( *col ) )
339 case KPaintInfo::COL_SIGNED:
341 show = &mPaintInfo.showSigned;
342 col = &mPaintInfo.signedCol;
343 width = pixFullySigned->width() + 8;
344 if ( *col == header()->mapToIndex( *col ) )
348 case KPaintInfo::COL_CRYPTO:
350 show = &mPaintInfo.showCrypto;
351 col = &mPaintInfo.cryptoCol;
352 width = pixFullyEncrypted->width() + 8;
353 if ( *col == header()->mapToIndex( *col ) )
357 case KPaintInfo::COL_RECEIVER:
359 show = &mPaintInfo.showReceiver;
360 col = &mPaintInfo.receiverCol;
364 case KPaintInfo::COL_SCORE: ;
375 mPopup->setItemChecked(
id, *show);
378 header()->setResizeEnabled(
true, *col);
379 setColumnWidth(*col, width);
380 if ( moveToCol >= 0 )
381 header()->moveSection( *col, moveToCol );
384 header()->setResizeEnabled(
false, *col);
385 header()->setStretchEnabled(
false, *col);
391 if ( static_cast<KPaintInfo::ColumnIds>(
id) == KPaintInfo::COL_RECEIVER ) {
392 TQString colText = i18n(
"Sender" );
393 if ( mFolder && (mFolder->
whoField().lower() ==
"to") && !mPaintInfo.showReceiver)
394 colText = i18n(
"Receiver" );
395 setColumnText( mPaintInfo.senderCol, colText );
406 if (mPaintInfo.pixmapOn)
407 p->drawTiledPixmap( rect.left(), rect.top(), rect.width(), rect.height(),
409 rect.left() + contentsX(),
410 rect.top() + contentsY() );
412 p->fillRect( rect, colorGroup().base() );
417 bool result = TDEListView::event(e);
418 if (e->type() == TQEvent::ApplicationPaletteChange)
429 TDEConfig* config = KMKernel::config();
431 TDEConfigGroupSaver saver(config,
"Reader");
432 TQColor c1=TQColor(kapp->palette().active().text());
433 TQColor c2=TQColor(
"red");
434 TQColor c3=TQColor(
"blue");
435 TQColor c4=TQColor(kapp->palette().active().base());
436 TQColor c5=TQColor(0,0x7F,0);
437 TQColor c6=TQColor(0,0x98,0);
438 TQColor c7=TDEGlobalSettings::alternateBackgroundColor();
440 if (!config->readBoolEntry(
"defaultColors",
true)) {
441 mPaintInfo.colFore = config->readColorEntry(
"ForegroundColor",&c1);
442 mPaintInfo.colBack = config->readColorEntry(
"BackgroundColor",&c4);
443 TQPalette newPal = kapp->palette();
444 newPal.setColor( TQColorGroup::Base, mPaintInfo.colBack );
445 newPal.setColor( TQColorGroup::Text, mPaintInfo.colFore );
446 setPalette( newPal );
447 mPaintInfo.colNew = config->readColorEntry(
"NewMessage",&c2);
448 mPaintInfo.colUnread = config->readColorEntry(
"UnreadMessage",&c3);
449 mPaintInfo.colFlag = config->readColorEntry(
"FlagMessage",&c5);
450 mPaintInfo.colTodo = config->readColorEntry(
"TodoMessage",&c6);
451 c7 = config->readColorEntry(
"AltBackgroundColor",&c7);
454 mPaintInfo.colFore = c1;
455 mPaintInfo.colBack = c4;
456 TQPalette newPal = kapp->palette();
457 newPal.setColor( TQColorGroup::Base, c4 );
458 newPal.setColor( TQColorGroup::Text, c1 );
459 setPalette( newPal );
460 mPaintInfo.colNew = c2;
461 mPaintInfo.colUnread = c3;
462 mPaintInfo.colFlag = c5;
463 mPaintInfo.colTodo = c6;
465 setAlternateBackground(c7);
471 TDEConfig* config = KMKernel::config();
475 TDEConfigGroupSaver saver(config,
"Pixmaps");
476 TQString pixmapFile = config->readEntry(
"Headers");
477 mPaintInfo.pixmapOn =
false;
478 if (!pixmapFile.isEmpty()) {
479 mPaintInfo.pixmapOn =
true;
480 mPaintInfo.pixmap = TQPixmap( pixmapFile );
485 TDEConfigGroupSaver saver(config,
"General");
486 bool show = config->readBoolEntry(
"showMessageSize");
487 slotToggleColumn(KPaintInfo::COL_SIZE, show);
489 show = config->readBoolEntry(
"showAttachmentColumn");
490 slotToggleColumn(KPaintInfo::COL_ATTACHMENT, show);
492 show = config->readBoolEntry(
"showInvitationColumn");
493 slotToggleColumn(KPaintInfo::COL_INVITATION, show);
495 show = config->readBoolEntry(
"showImportantColumn");
496 slotToggleColumn(KPaintInfo::COL_IMPORTANT, show);
498 show = config->readBoolEntry(
"showTodoColumn");
499 slotToggleColumn(KPaintInfo::COL_TODO, show);
501 show = config->readBoolEntry(
"showSpamHamColumn");
502 slotToggleColumn(KPaintInfo::COL_SPAM_HAM, show);
504 show = config->readBoolEntry(
"showWatchedIgnoredColumn");
505 slotToggleColumn(KPaintInfo::COL_WATCHED_IGNORED, show);
507 show = config->readBoolEntry(
"showStatusColumn");
508 slotToggleColumn(KPaintInfo::COL_STATUS, show);
510 show = config->readBoolEntry(
"showSignedColumn");
511 slotToggleColumn(KPaintInfo::COL_SIGNED, show);
513 show = config->readBoolEntry(
"showCryptoColumn");
514 slotToggleColumn(KPaintInfo::COL_CRYPTO, show);
516 show = config->readBoolEntry(
"showReceiverColumn");
517 slotToggleColumn(KPaintInfo::COL_RECEIVER, show);
519 mPaintInfo.showCryptoIcons = config->readBoolEntry(
"showCryptoIcons",
false );
520 mPaintInfo.showAttachmentIcon = config->readBoolEntry(
"showAttachmentIcon",
true );
521 mPaintInfo.showInvitationIcon = config->readBoolEntry(
"showInvitationIcon",
false );
523 KMime::DateFormatter::FormatType t =
524 (KMime::DateFormatter::FormatType) config->readNumEntry(
"dateFormat", KMime::DateFormatter::Fancy ) ;
525 mDate.setCustomFormat( config->readEntry(
"customDateFormat") );
526 mDate.setFormat( t );
533 TDEConfigGroupSaver saver(config,
"Fonts");
534 if (!(config->readBoolEntry(
"defaultFonts",
true)))
536 TQFont listFont( TDEGlobalSettings::generalFont() );
537 listFont = config->readFontEntry(
"list-font", &listFont );
539 mNewFont = config->readFontEntry(
"list-new-font", &listFont );
540 mUnreadFont = config->readFontEntry(
"list-unread-font", &listFont );
541 mImportantFont = config->readFontEntry(
"list-important-font", &listFont );
542 mTodoFont = config->readFontEntry(
"list-todo-font", &listFont );
543 mDateFont = TDEGlobalSettings::fixedFont();
544 mDateFont = config->readFontEntry(
"list-date-font", &mDateFont );
546 mNewFont= mUnreadFont = mImportantFont = mDateFont = mTodoFont =
547 TDEGlobalSettings::generalFont();
548 setFont( mDateFont );
554 TDEConfigGroupSaver saver(config,
"Geometry");
555 mReaderWindowActive = config->readEntry(
"readerWindowMode",
"below" ) !=
"hide";
565 mIgnoreSortOrderChanges =
true;
566 restoreLayout( config, group );
567 mIgnoreSortOrderChanges =
false;
573 int top = topItemIndex();
574 int id = currentItemIndex();
577 TQString colText = i18n(
"Sender" );
578 if ( mFolder && (mFolder->
whoField().lower() ==
"to") && !mPaintInfo.showReceiver)
579 colText = i18n(
"Receiver" );
580 setColumnText( mPaintInfo.senderCol, colText );
585 setTopItemByIndex(top);
586 ensureCurrentItemVisible();
592 bool oldState = isThreaded();
593 NestingPolicy oldNestPolicy = nestingPolicy;
594 TDEConfig* config = KMKernel::config();
595 TDEConfigGroupSaver saver(config,
"Geometry");
596 mNested = config->readBoolEntry(
"nestedMessages",
false );
598 nestingPolicy = (NestingPolicy)config->readNumEntry(
"nestingPolicy", OpenUnread );
599 if ((nestingPolicy != oldNestPolicy) ||
600 (oldState != isThreaded()))
602 setRootIsDecorated( nestingPolicy != AlwaysOpen && isThreaded() );
611 if (!mFolder)
return;
612 TDEConfig* config = KMKernel::config();
614 TDEConfigGroupSaver saver(config,
"Folder-" + mFolder->
idString());
615 mNestedOverride = config->readBoolEntry(
"threadMessagesOverride",
false );
616 mSortCol = config->readNumEntry(
"SortColumn", mSortCol+1 );
617 mSortDescending = (mSortCol < 0);
618 mSortCol = abs(mSortCol) - 1;
620 mTopItem = config->readNumEntry(
"Top", 0);
621 mCurrentItem = config->readNumEntry(
"Current", 0);
622 mCurrentItemSerNum = config->readNumEntry(
"CurrentSerialNum", 0);
624 mPaintInfo.orderOfArrival = config->readBoolEntry(
"OrderOfArrival",
false );
625 mPaintInfo.status = config->readBoolEntry(
"Status",
false );
628 TDEConfigGroupSaver saver(config,
"Geometry");
629 mNested = config->readBoolEntry(
"nestedMessages",
false );
630 nestingPolicy = (NestingPolicy)config->readNumEntry(
"nestingPolicy", OpenUnread );
633 setRootIsDecorated( nestingPolicy != AlwaysOpen && isThreaded() );
634 mSubjThreading = config->readBoolEntry(
"threadMessagesBySubject",
true );
641 if (!mFolder)
return;
642 TDEConfig* config = KMKernel::config();
643 int mSortColAdj = mSortCol + 1;
645 TDEConfigGroupSaver saver(config,
"Folder-" + mFolder->
idString());
646 config->writeEntry(
"SortColumn", (mSortDescending ? -mSortColAdj : mSortColAdj));
647 config->writeEntry(
"Top", topItemIndex());
648 config->writeEntry(
"Current", currentItemIndex());
653 config->writeEntry(
"CurrentSerialNum", sernum);
655 config->writeEntry(
"OrderOfArrival", mPaintInfo.orderOfArrival);
656 config->writeEntry(
"Status", mPaintInfo.status);
662 TDEConfig* config = KMKernel::config();
663 saveLayout(config,
"Header-Geometry");
664 TDEConfigGroupSaver saver(config,
"General");
665 config->writeEntry(
"showMessageSize" , mPaintInfo.showSize);
666 config->writeEntry(
"showAttachmentColumn" , mPaintInfo.showAttachment);
667 config->writeEntry(
"showInvitationColumn" , mPaintInfo.showInvitation);
668 config->writeEntry(
"showImportantColumn" , mPaintInfo.showImportant);
669 config->writeEntry(
"showTodoColumn" , mPaintInfo.showTodo);
670 config->writeEntry(
"showSpamHamColumn" , mPaintInfo.showSpamHam);
671 config->writeEntry(
"showWatchedIgnoredColumn", mPaintInfo.showWatchedIgnored);
672 config->writeEntry(
"showStatusColumn" , mPaintInfo.showStatus);
673 config->writeEntry(
"showSignedColumn" , mPaintInfo.showSigned);
674 config->writeEntry(
"showCryptoColumn" , mPaintInfo.showCrypto);
675 config->writeEntry(
"showReceiverColumn" , mPaintInfo.showReceiver);
681 CREATE_TIMER(set_folder);
682 START_TIMER(set_folder);
687 mSortInfo.fakeSort = 0;
688 if ( mFolder && static_cast<KMFolder*>(mFolder) == aFolder ) {
689 int top = topItemIndex();
690 id = currentItemIndex();
695 setTopItemByIndex(top);
700 highlightMessage(0,
false);
703 this, TQT_SLOT(setFolderInfoStatus()));
709 disconnect(mFolder, TQT_SIGNAL(
msgAdded(
int)),
711 disconnect(mFolder, TQT_SIGNAL(
msgRemoved(
int, TQString ) ),
712 this, TQT_SLOT(
msgRemoved(
int, TQString ) ) );
713 disconnect(mFolder, TQT_SIGNAL(
changed()),
715 disconnect(mFolder, TQT_SIGNAL(
cleared()),
716 this, TQT_SLOT(folderCleared()));
718 this, TQT_SLOT(folderCleared()));
719 disconnect(mFolder, TQT_SIGNAL(
closed()),
720 this, TQT_SLOT(folderClosed()));
721 disconnect( mFolder, TQT_SIGNAL(
statusMsg(
const TQString& ) ),
722 BroadcastStatus::instance(), TQT_SLOT( setStatusMsg(
const TQString& ) ) );
723 disconnect(mFolder, TQT_SIGNAL(viewConfigChanged()),
this, TQT_SLOT(reset()));
725 mFolder->
close(
"kmheaders");
731 mSortInfo.removed = 0;
733 mSortInfo.
dirty =
true;
735 mOwner->useAction()->setEnabled( mFolder ?
736 ( kmkernel->folderIsTemplates( mFolder ) ) :
false );
737 mOwner->messageActions()->replyListAction()->setEnabled( mFolder ?
738 mFolder->isMailingListEnabled() : false );
742 connect(mFolder, TQT_SIGNAL(
msgAdded(
int)),
744 connect(mFolder, TQT_SIGNAL(
msgRemoved(
int,TQString)),
746 connect(mFolder, TQT_SIGNAL(
changed()),
748 connect(mFolder, TQT_SIGNAL(
cleared()),
749 this, TQT_SLOT(folderCleared()));
751 this, TQT_SLOT(folderCleared()));
752 connect(mFolder, TQT_SIGNAL(
closed()),
753 this, TQT_SLOT(folderClosed()));
754 connect(mFolder, TQT_SIGNAL(
statusMsg(
const TQString&)),
755 BroadcastStatus::instance(), TQT_SLOT( setStatusMsg(
const TQString& ) ) );
757 this, TQT_SLOT(setFolderInfoStatus()));
758 connect(mFolder, TQT_SIGNAL(viewConfigChanged()),
this, TQT_SLOT(reset()));
772 CREATE_TIMER(kmfolder_open);
773 START_TIMER(kmfolder_open);
774 mFolder->
open(
"kmheaders");
775 END_TIMER(kmfolder_open);
776 SHOW_TIMER(kmfolder_open);
786 CREATE_TIMER(updateMsg);
787 START_TIMER(updateMsg);
788 updateMessageList(
true, forceJumpToUnread);
789 END_TIMER(updateMsg);
790 SHOW_TIMER(updateMsg);
792 setFolderInfoStatus();
794 TQString colText = i18n(
"Sender" );
795 if (mFolder && (mFolder->
whoField().lower() ==
"to") && !mPaintInfo.showReceiver)
796 colText = i18n(
"Receiver");
797 setColumnText( mPaintInfo.senderCol, colText);
799 colText = i18n(
"Date" );
800 if (mPaintInfo.orderOfArrival)
801 colText = i18n(
"Order of Arrival" );
802 setColumnText( mPaintInfo.dateCol, colText);
804 colText = i18n(
"Subject" );
805 if (mPaintInfo.status)
806 colText = colText + i18n(
" (Status)" );
807 setColumnText( mPaintInfo.subCol, colText);
812 END_TIMER(set_folder);
813 SHOW_TIMER(set_folder);
819 if (mFolder->
count() == 0) {
824 if (!isUpdatesEnabled())
return;
827 const TQValueList<int> oldSelectedItems = selectedItems();
828 const int oldCurrentItemIndex = currentItemIndex();
829 const bool scrollbarAtTop = verticalScrollBar() &&
830 verticalScrollBar()->value() == verticalScrollBar()->minValue();
831 const bool scrollbarAtBottom = verticalScrollBar() &&
832 verticalScrollBar()->value() == verticalScrollBar()->maxValue();
833 const HeaderItem *
const oldFirstVisibleItem =
dynamic_cast<HeaderItem*
>( itemAt( TQPoint( 0, 0 ) ) );
834 const int oldOffsetOfFirstVisibleItem = itemRect( oldFirstVisibleItem ).y();
835 const uint oldSerNumOfFirstVisibleItem = oldFirstVisibleItem ? oldFirstVisibleItem->msgSerNum() : 0;
838 TQListViewItem *item = currentItem();
844 msgIdMD5 = mb->msgIdMD5();
848 disconnect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
849 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
854 setCurrentMsg( oldCurrentItemIndex );
855 setSelectedByIndex( oldSelectedItems,
true );
856 if ( scrollbarAtTop ) {
857 setContentsPos( 0, 0 );
858 }
else if ( scrollbarAtBottom ) {
859 setContentsPos( 0, contentsHeight() );
860 }
else if ( oldSerNumOfFirstVisibleItem > 0 ) {
861 for ( uint i = 0; i < mItems.size(); ++i ) {
862 const KMMsgBase *
const mMsgBase = mFolder->
getMsgBase( i );
863 if ( mMsgBase->getMsgSerNum() == oldSerNumOfFirstVisibleItem ) {
864 setContentsPos( 0, itemPos( mItems[i] ) - oldOffsetOfFirstVisibleItem );
870 connect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
871 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
880 item = currentItem();
885 if (msgIdMD5.isEmpty() || (msgIdMD5 != mb->msgIdMD5()))
899 if (!isUpdatesEnabled())
return;
911 if (mSortCacheItems.count() == (uint)mFolder->
count()
912 || mSortCacheItems.count() == 0) {
913 kdDebug (5006) <<
"KMHeaders::msgAdded - Resizing id and subject trees of " << mFolder->
label()
914 <<
": before=" << mSortCacheItems.count() <<
" ,after=" << (mFolder->
count()*2) << endl;
915 mSortCacheItems.resize(mFolder->
count()*2);
916 mSubjectLists.resize(mFolder->
count()*2);
924 if (!parent && mSubjThreading) {
925 parent = findParentBySubject( sci );
937 if (parent && mFolder->
getMsgBase(parent->id())->isWatched())
938 mFolder->
getMsgBase(
id)->setStatus( KMMsgStatusWatched );
939 else if (parent && mFolder->
getMsgBase(parent->id())->isIgnored())
940 mFolder->
getMsgBase(
id)->setStatus( KMMsgStatusIgnored );
951 mItems.resize( mFolder->
count() );
954 if ( !msgId.isEmpty() )
955 mSortCacheItems.replace(msgId, sci);
958 if (mSubjThreading && parent) {
959 TQString subjMD5 = mFolder->
getMsgBase(
id)->strippedSubjectMD5();
960 if (subjMD5.isEmpty()) {
961 mFolder->
getMsgBase(
id)->initStrippedSubjectMD5();
962 subjMD5 = mFolder->
getMsgBase(
id)->strippedSubjectMD5();
964 if( !subjMD5.isEmpty()) {
965 if ( !mSubjectLists.find(subjMD5) )
966 mSubjectLists.insert(subjMD5,
new TQPtrList<SortCacheItem>());
969 for (TQPtrListIterator<SortCacheItem> it(*mSubjectLists[subjMD5]);
970 it.current(); ++it) {
971 KMMsgBase *mb = mFolder->
getMsgBase((*it)->id());
972 if ( mb->date() < mFolder->
getMsgBase(
id)->date())
976 mSubjectLists[subjMD5]->insert( p, sci);
977 sci->setSubjectThreadingList( mSubjectLists[subjMD5] );
986 disconnect(
this, TQT_SIGNAL(currentChanged(TQListViewItem*)),
987 this, TQT_SLOT(highlightMessage(TQListViewItem*)));
989 if ( !msgId.isEmpty() ) {
990 TQPtrListIterator<HeaderItem> it(mImperfectlyThreadedList);
992 while ( (cur = it.current()) ) {
994 int tryMe = cur->
msgId();
998 bool perfectParent =
true;
999 KMMsgBase *otherMsg = mFolder->
getMsgBase(tryMe);
1001 kdDebug(5006) <<
"otherMsg is NULL !!! tryMe: " << tryMe << endl;
1004 TQString otherId = otherMsg->replyToIdMD5();
1005 if (msgId != otherId) {
1006 if (msgId != otherMsg->replyToAuxIdMD5())
1009 if (!otherId.isEmpty() && mSortCacheItems.find(otherId))
1014 perfectParent =
false;
1017 TQListViewItem *newParent = mItems[
id];
1018 TQListViewItem *msg = mItems[tryMe];
1021 msg->parent()->takeItem(msg);
1024 newParent->insertItem(msg);
1028 makeHeaderVisible();
1030 if (perfectParent) {
1031 mImperfectlyThreadedList.removeRef (mItems[tryMe]);
1034 TQString sortFile = KMAIL_SORT_FILE(mFolder);
1035 FILE *sortStream = fopen(TQFile::encodeName(sortFile),
"r+");
1037 mItems[tryMe]->sortCacheItem()->updateSortFile( sortStream, mFolder );
1038 fclose (sortStream);
1045 mImperfectlyThreadedList.append(hi);
1049 mItems.resize( mFolder->
count() );
1055 if (mSortInfo.fakeSort) {
1056 TQObject::disconnect(header(), TQT_SIGNAL(clicked(
int)),
this, TQT_SLOT(dirtySortOrder(
int)));
1057 TDEListView::setSorting(mSortCol, !mSortDescending );
1058 mSortInfo.fakeSort = 0;
1060 appendItemToSortFile(hi);
1064 if ((childCount() == 1) && hi) {
1065 setSelected( hi,
true );
1066 setCurrentItem( firstChild() );
1067 setSelectionAnchor( currentItem() );
1068 highlightMessage( currentItem() );
1072 connect(
this, TQT_SIGNAL(currentChanged(TQListViewItem*)),
1073 this, TQT_SLOT(highlightMessage(TQListViewItem*)));
1075 emit msgAddedToListView( hi );
1084 if (!isUpdatesEnabled())
return;
1086 if ((
id < 0) || (
id >= (
int)mItems.size()))
1093 disconnect(
this, TQT_SIGNAL(currentChanged(TQListViewItem*)),
1094 this, TQT_SLOT(highlightMessage(TQListViewItem*)));
1097 if (!removedItem)
return;
1100 for (
int i =
id; i < (int)mItems.size() - 1; ++i) {
1101 mItems[i] = mItems[i+1];
1102 mItems[i]->setMsgId( i );
1103 mItems[i]->sortCacheItem()->setId( i );
1106 mItems.resize( mItems.size() - 1 );
1108 if (isThreaded() && mFolder->
count()) {
1109 if ( !msgId.isEmpty() && mSortCacheItems[
msgId] ) {
1111 mSortCacheItems.remove(msgId);
1119 TQListViewItem *myParent = removedItem;
1120 TQListViewItem *myChild = myParent->firstChild();
1121 TQListViewItem *threadRoot = myParent;
1122 while (threadRoot->parent())
1123 threadRoot = threadRoot->parent();
1124 TQString key =
static_cast<HeaderItem*
>(threadRoot)->key(mSortCol, !mSortDescending);
1126 TQPtrList<TQListViewItem> childList;
1131 childList.append(myChild);
1133 myChild = myChild->nextSibling();
1135 myParent->takeItem( item );
1139 item->setTempKey( key + item->key( mSortCol, !mSortDescending ));
1140 if (mSortInfo.fakeSort) {
1141 TQObject::disconnect(header(), TQT_SIGNAL(clicked(
int)),
this, TQT_SLOT(dirtySortOrder(
int)));
1142 TDEListView::setSorting(mSortCol, !mSortDescending );
1143 mSortInfo.fakeSort = 0;
1147 for (TQPtrListIterator<TQListViewItem> it(childList); it.current() ; ++it ) {
1148 TQListViewItem *lvi = *it;
1152 if ( !parent && mSubjThreading )
1153 parent = findParentBySubject( sci );
1155 Q_ASSERT( !parent || parent->
item() != removedItem );
1156 myParent->takeItem(lvi);
1157 if ( parent && parent->
item() != item && parent->
item() != removedItem ) {
1158 parent->
item()->insertItem(lvi);
1162 mRoot->addSortedChild( sci );
1166 && !mImperfectlyThreadedList.containsRef(item))
1167 mImperfectlyThreadedList.append(item);
1170 && mImperfectlyThreadedList.containsRef(item))
1171 mImperfectlyThreadedList.removeRef(item);
1175 if (!mFolder->
count())
1178 mImperfectlyThreadedList.removeRef( removedItem );
1181 while ( mImperfectlyThreadedList.findRef( removedItem ) != -1 ) {
1182 mImperfectlyThreadedList.remove();
1183 kdDebug(5006) <<
"Remove doubled item from mImperfectlyThreadedList: " << removedItem << endl;
1189 if ( curItem != removedItem ) {
1190 setCurrentItem( curItem );
1191 setSelectionAnchor( currentItem() );
1198 emit maybeDeleting();
1199 int contentX, contentY;
1200 HeaderItem *nextItem = prepareMove( &contentX, &contentY );
1201 finalizeMove( nextItem, contentX, contentY );
1205 connect(
this, TQT_SIGNAL(currentChanged(TQListViewItem*)),
1206 this, TQT_SLOT(highlightMessage(TQListViewItem*)));
1213 if (msgId<0 || msgId >= (
int)mItems.size() || !isUpdatesEnabled())
return;
1226 SerNumList serNums = selectedVisibleSernums();
1227 if (serNums.empty())
1230 KMCommand *command =
new KMSeStatusCommand( status, serNums, toggle );
1237 if (!mFolder)
return TQPtrList<TQListViewItem>();
1240 TQListViewItem *curItem = currentItem();
1241 if (!curItem)
return TQPtrList<TQListViewItem>();
1244 TQListViewItem *topOfThread = curItem;
1245 while ( topOfThread->parent() )
1246 topOfThread = topOfThread->parent();
1249 TQPtrList<TQListViewItem> list;
1250 TQListViewItem *topOfNextThread = topOfThread->nextSibling();
1251 for ( TQListViewItemIterator it( topOfThread ) ;
1252 it.current() && it.current() != topOfNextThread ; ++it )
1253 list.append( it.current() );
1259 TQPtrList<TQListViewItem> curThread;
1262 TQPtrList<TQListViewItem> topOfThreads;
1265 for (TQListViewItem *item = firstChild(); item; item = item->itemBelow())
1266 if (item->isSelected() ) {
1268 TQListViewItem *top = item;
1269 while ( top->parent() )
1270 top = top->parent();
1271 if (!topOfThreads.contains(top)) {
1272 topOfThreads.append(top);
1277 for ( TQPtrListIterator<TQListViewItem> it( topOfThreads ) ;
1278 it.current() ; ++ it ) {
1279 TQListViewItem *top = *it;
1282 TQListViewItem *topOfNextThread = top->nextSibling();
1283 for ( TQListViewItemIterator it( top ) ;
1284 it.current() && it.current() != topOfNextThread ; ++it )
1285 curThread.append( it.current() );
1289 TQPtrListIterator<TQListViewItem> it( curThread );
1292 for ( it.toFirst() ; it.current() ; ++it ) {
1294 KMMsgBase *msgBase = mFolder->
getMsgBase(
id );
1295 serNums.append( msgBase->getMsgSerNum() );
1298 if (serNums.empty())
1301 KMCommand *command =
new KMSeStatusCommand( status, serNums, toggle );
1308 if ( !msg )
return 2;
1310 int filterResult = kmkernel->filterMgr()->process(msg,KMFilterMgr::Explicit);
1311 if (filterResult == 2) {
1313 kmkernel->emergencyExit( i18n(
"Unable to process messages: " ) + TQString::fromLocal8Bit(strerror(errno)));
1316 if (msg->parent()) {
1320 assert( p == msg->parent() ); assert( idx >= 0 );
1324 return filterResult;
1330 if ( !isThreaded() )
return;
1332 TQListViewItem *item = currentItem();
1333 if ( !item )
return;
1335 item->setSelected(
true );
1336 while ( item->parent() )
1337 item = item->parent();
1341 setCurrentMsg( hdrItem->
msgId() );
1342 ensureItemVisible( currentItem() );
1347 if ( !isThreaded() )
return;
1349 TQListViewItem * item = currentItem();
1352 item->setSelected(
true );
1355 for ( TQListViewItem *item = firstChild() ;
1356 item ; item = item->nextSibling() )
1357 static_cast<HeaderItem*>(item)->setOpenRecursive( expand );
1359 TQListViewItem * item = currentItem();
1361 while ( item->parent() )
1362 item = item->parent();
1363 setCurrentMsg( static_cast<HeaderItem*>(item)->
msgId() );
1366 ensureItemVisible( currentItem() );
1374 if( style().isA(
"KeramikStyle") )
1375 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth ) - 1;
1377 frameWidth = style().pixelMetric( TQStyle::PM_DefaultFrameWidth );
1378 if ( frameWidth < 0 )
1380 if ( frameWidth != lineWidth() )
1381 setLineWidth( frameWidth );
1387 setStyleDependantFrameWidth();
1388 TDEListView::styleChange( oldStyle );
1394 if ( !mFolder )
return;
1397 if ( static_cast<KMFolder*>(mFolder) == kmkernel->outboxFolder() )
1398 str = unread ? i18n(
"1 unsent",
"%n unsent", unread ) : i18n(
"0 unsent" );
1400 str = unread ? i18n(
"1 unread",
"%n unread", unread ) : i18n(
"0 unread" );
1402 str = count ? i18n(
"1 message, %1.",
"%n messages, %1.", count ).arg( str )
1403 : i18n(
"0 messages" );
1405 str = i18n(
"%1 = n messages, m unread.",
"%1 Folder is read-only.").arg( str );
1406 BroadcastStatus::instance()->setStatusMsg(str);
1410 void KMHeaders::applyFiltersOnMsg()
1412 if (ActionScheduler::isEnabled() ||
1413 kmkernel->filterMgr()->atLeastOneOnlineImapFolderTarget()) {
1415 KMFilterMgr::FilterSet
set = KMFilterMgr::Explicit;
1416 TQValueList<KMFilter*> filters = kmkernel->filterMgr()->filters();
1417 ActionScheduler *scheduler =
new ActionScheduler(
set, filters,
this );
1418 scheduler->setAutoDestruct(
true );
1420 int contentX, contentY;
1421 HeaderItem *nextItem = prepareMove( &contentX, &contentY );
1422 TQPtrList<KMMsgBase> msgList = *selectedMsgs(
true);
1423 finalizeMove( nextItem, contentX, contentY );
1425 for (KMMsgBase *msg = msgList.first(); msg; msg = msgList.next())
1426 scheduler->execFilters( msg );
1428 int contentX, contentY;
1429 HeaderItem *nextItem = prepareMove( &contentX, &contentY );
1433 if ( serNums.isEmpty() )
1436 finalizeMove( nextItem, contentX, contentY );
1437 CREATE_TIMER(filter);
1438 START_TIMER(filter);
1442 int msgCountToFilter = serNums.count();
1443 ProgressItem* progressItem =
1444 ProgressManager::createProgressItem(
"filter"+ProgressManager::getUniqueID(),
1445 i18n(
"Filtering messages" ) );
1446 progressItem->setTotalItems( msgCountToFilter );
1448 for ( TQValueList<unsigned long>::ConstIterator it = serNums.constBegin();
1449 it != serNums.constEnd(); ++it ) {
1451 if ( msgCountToFilter - msgCount < 10 || !( msgCount % 20 ) || msgCount <= 10 ) {
1452 progressItem->updateProgress();
1453 TQString
statusMsg = i18n(
"Filtering message %1 of %2");
1454 statusMsg = statusMsg.arg( msgCount ).arg( msgCountToFilter );
1455 KPIM::BroadcastStatus::instance()->setStatusMsg( statusMsg );
1456 TDEApplication::kApplication()->eventLoop()->processEvents( TQEventLoop::ExcludeUserInput, 50 );
1464 msg = folder->
getMsg(idx);
1470 FolderJob *job = mFolder->
createJob(msg);
1471 connect(job, TQT_SIGNAL(messageRetrieved(
KMMessage*)),
1472 this, TQT_SLOT(slotFilterMsg(
KMMessage*)));
1475 if (slotFilterMsg(msg) == 2)
1479 kdDebug (5006) <<
"####### KMHeaders::applyFiltersOnMsg -" 1480 " A message went missing during filtering " << endl;
1482 progressItem->incCompletedItems();
1484 progressItem->setComplete();
1493 void KMHeaders::setMsgRead (
int msgId)
1495 KMMsgBase *msgBase = mFolder->
getMsgBase( msgId );
1500 if (msgBase->isNew() || msgBase->isUnread()) {
1501 serNums.append( msgBase->getMsgSerNum() );
1504 KMCommand *command =
new KMSeStatusCommand( KMMsgStatusRead, serNums );
1510 void KMHeaders::deleteMsg ()
1516 int contentX, contentY;
1517 HeaderItem *nextItem = prepareMove( &contentX, &contentY );
1518 KMMessageList msgList = *selectedMsgs(
true);
1519 finalizeMove( nextItem, contentX, contentY );
1521 KMCommand *command =
new KMDeleteMsgCommand( mFolder, msgList );
1522 connect( command, TQT_SIGNAL( completed( KMCommand * ) ),
1523 this, TQT_SLOT( slotMoveCompleted( KMCommand * ) ) );
1526 BroadcastStatus::instance()->setStatusMsg(
"");
1534 if (mMenuToFolder[menuId])
1535 moveMsgToFolder( mMenuToFolder[menuId] );
1539 HeaderItem* KMHeaders::prepareMove(
int *contentX,
int *contentY )
1542 emit maybeDeleting();
1544 disconnect(
this, TQT_SIGNAL(currentChanged(TQListViewItem*)),
1545 this, TQT_SLOT(highlightMessage(TQListViewItem*)));
1547 TQListViewItem *curItem;
1549 curItem = currentItem();
1550 while (curItem && curItem->isSelected() && curItem->itemBelow())
1551 curItem = curItem->itemBelow();
1552 while (curItem && curItem->isSelected() && curItem->itemAbove())
1553 curItem = curItem->itemAbove();
1556 *contentX = contentsX();
1557 *contentY = contentsY();
1559 if (item && !item->isSelected())
1566 void KMHeaders::finalizeMove(
HeaderItem *item,
int contentX,
int contentY )
1572 setCurrentItem( item );
1573 setSelected( item,
true );
1574 setSelectionAnchor( currentItem() );
1576 highlightMessage( item,
false);
1579 setContentsPos( contentX, contentY );
1580 makeHeaderVisible();
1581 connect(
this, TQT_SIGNAL(currentChanged(TQListViewItem*)),
1582 this, TQT_SLOT(highlightMessage(TQListViewItem*)));
1589 if ( destFolder == mFolder )
return;
1592 KMMessageList msgList = *selectedMsgs();
1593 if ( msgList.isEmpty() )
return;
1594 if ( !destFolder && askForConfirmation &&
1595 KMessageBox::warningContinueCancel(
this,
1596 i18n(
"<qt>Do you really want to delete the selected message?<br>" 1597 "Once deleted, it cannot be restored.</qt>",
1598 "<qt>Do you really want to delete the %n selected messages?<br>" 1599 "Once deleted, they cannot be restored.</qt>", msgList.count() ),
1600 msgList.count()>1 ? i18n(
"Delete Messages") : i18n(
"Delete Message"), KStdGuiItem::del(),
1601 "NoConfirmDelete") == KMessageBox::Cancel )
1605 int contentX, contentY;
1606 HeaderItem *nextItem = prepareMove( &contentX, &contentY );
1607 msgList = *selectedMsgs(
true);
1608 finalizeMove( nextItem, contentX, contentY );
1610 KMCommand *command =
new KMMoveCommand( destFolder, msgList );
1611 connect( command, TQT_SIGNAL( completed( KMCommand * ) ),
1612 this, TQT_SLOT( slotMoveCompleted( KMCommand * ) ) );
1616 void KMHeaders::slotMoveCompleted( KMCommand *command )
1618 kdDebug(5006) << k_funcinfo << command->result() << endl;
1619 bool deleted =
static_cast<KMMoveCommand *
>( command )->destFolder() == 0;
1620 if ( command->result() == KMCommand::OK ) {
1622 makeHeaderVisible();
1623 BroadcastStatus::instance()->setStatusMsg(
1624 deleted ? i18n(
"Messages deleted successfully.") : i18n(
"Messages moved successfully") );
1632 for (TQListViewItemIterator it(
this); it.current(); it++) {
1636 item->setSelectable (
true );
1638 if ( msgBase->isMessage() ) {
1645 if ( command->result() == KMCommand::Failed )
1646 BroadcastStatus::instance()->setStatusMsg(
1647 deleted ? i18n(
"Deleting messages failed.") : i18n(
"Moving messages failed.") );
1649 BroadcastStatus::instance()->setStatusMsg(
1650 deleted ? i18n(
"Deleting messages canceled.") : i18n(
"Moving messages canceled.") );
1652 mOwner->updateMessageActions();
1655 bool KMHeaders::canUndo()
const 1657 return ( kmkernel->undoStack()->size() > 0 );
1661 void KMHeaders::undo()
1663 kmkernel->undoStack()->undo();
1669 if (mMenuToFolder[menuId])
1670 copyMsgToFolder( mMenuToFolder[menuId] );
1680 KMCommand * command = 0;
1682 command =
new KMCopyCommand( destFolder, aMsg );
1684 KMMessageList msgList = *selectedMsgs();
1685 command =
new KMCopyCommand( destFolder, msgList );
1695 if (!mFolder)
return;
1696 if (cur >= mFolder->
count()) cur = mFolder->
count() - 1;
1697 if ((cur >= 0) && (cur < (
int)mItems.size())) {
1699 setCurrentItem( mItems[cur] );
1700 setSelected( mItems[cur],
true );
1701 setSelectionAnchor( currentItem() );
1703 makeHeaderVisible();
1704 setFolderInfoStatus();
1713 if ( item->isVisible() )
1714 TDEListView::setSelected( item, selected );
1718 if ( isThreaded() && !item->isOpen() && item->firstChild() ) {
1719 TQListViewItem *nextRoot = item->itemBelow();
1720 TQListViewItemIterator it( item->firstChild() );
1721 for( ; (*it) != nextRoot; ++it ) {
1722 if ( (*it)->isVisible() )
1723 (*it)->setSelected( selected );
1730 for ( TQValueList<int>::Iterator it = items.begin(); it != items.end(); ++it )
1732 if ( ((*it) >= 0) && ((*it) < (int)mItems.size()) )
1734 setSelected( mItems[(*it)], selected );
1742 for (TQListViewItemIterator it(
this); it.current(); it++) {
1746 if ( serNum == msgBase->getMsgSerNum() ) {
1748 item->setSelectable (
true );
1758 mSelMsgBaseList.clear();
1759 for (TQListViewItemIterator it(
this); it.current(); it++) {
1760 if ( it.current()->isSelected() && it.current()->isVisible() ) {
1766 item->setSelectable (
false );
1769 mSelMsgBaseList.append(msgBase);
1773 return &mSelMsgBaseList;
1779 TQValueList<int> items;
1780 for ( TQListViewItemIterator it(
this); it.current(); it++ )
1782 if ( it.current()->isSelected() && it.current()->isVisible() )
1785 items.append( item->
msgId() );
1794 int selectedMsg = -1;
1795 TQListViewItem *item;
1796 for (item = firstChild(); item; item = item->itemBelow())
1797 if (item->isSelected()) {
1807 TQListViewItem *lvi = currentItem();
1808 if (lvi && lvi->itemBelow()) {
1810 setSelected( lvi,
false );
1811 selectNextMessage();
1812 setSelectionAnchor( currentItem() );
1813 ensureCurrentItemVisible();
1820 if ( cm && cm->isBeingParsed() )
1822 TQListViewItem *lvi = currentItem();
1824 TQListViewItem *below = lvi->itemBelow();
1825 TQListViewItem *temp = lvi;
1826 if (lvi && below ) {
1829 temp = temp->parent();
1833 (below->isSelected() ? setSelected(lvi,
false) : setSelected(below,
true));
1834 setCurrentItem(below);
1835 makeHeaderVisible();
1836 setFolderInfoStatus();
1844 TQListViewItem *lvi = currentItem();
1845 if (lvi && lvi->itemAbove()) {
1847 setSelected( lvi,
false );
1848 selectPrevMessage();
1849 setSelectionAnchor( currentItem() );
1850 ensureCurrentItemVisible();
1857 if ( cm && cm->isBeingParsed() )
1859 TQListViewItem *lvi = currentItem();
1861 TQListViewItem *above = lvi->itemAbove();
1862 TQListViewItem *temp = lvi;
1867 temp = temp->parent();
1871 (above->isSelected() ? setSelected(lvi,
false) : setSelected(above,
true));
1872 setCurrentItem(above);
1873 makeHeaderVisible();
1874 setFolderInfoStatus();
1883 if ( cm && cm->isBeingParsed() )
1885 TQListViewItem *lvi = currentItem();
1886 if ( lvi && lvi->itemBelow() ) {
1888 disconnect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
1889 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
1890 setCurrentItem( lvi->itemBelow() );
1891 ensureCurrentItemVisible();
1893 connect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
1894 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
1901 if ( cm && cm->isBeingParsed() )
1903 TQListViewItem *lvi = currentItem();
1904 if ( lvi && lvi->itemAbove() ) {
1905 disconnect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
1906 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
1907 setCurrentItem( lvi->itemAbove() );
1908 ensureCurrentItemVisible();
1910 connect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
1911 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
1917 setCurrentMsg( currentItemIndex() );
1918 highlightMessage( currentItem() );
1923 bool & foundUnreadMessage,
1927 KMMsgBase* msgBase = 0;
1934 if (!msgBase)
continue;
1935 if (msgBase->isUnread() || msgBase->isNew())
1936 foundUnreadMessage =
true;
1938 if (!onlyNew && (msgBase->isUnread() || msgBase->isNew()))
break;
1939 if (onlyNew && msgBase->isNew())
break;
1940 item =
static_cast<HeaderItem*
>(item->itemBelow());
1947 if (!msgBase)
continue;
1948 if (msgBase->isUnread() || msgBase->isNew())
1949 foundUnreadMessage =
true;
1950 if ( ( !onlyNew && (msgBase->isUnread() || msgBase->isNew()) )
1951 || ( onlyNew && msgBase->isNew() ) )
1952 lastUnread = newItem;
1953 if (newItem == item)
break;
1954 newItem =
static_cast<HeaderItem*
>(newItem->itemBelow());
1964 bool foundUnreadMessage =
false;
1966 if (!mFolder)
return -1;
1967 if (mFolder->
count() <= 0)
return -1;
1969 if ((aStartAt >= 0) && (aStartAt < (int)mItems.size()))
1970 item = mItems[aStartAt];
1972 item = currentHeaderItem();
1975 item =
static_cast<HeaderItem*
>(firstChild());
1977 item =
static_cast<HeaderItem*
>(lastChild());
1982 if ( !acceptCurrent ) {
1984 item =
static_cast<HeaderItem*
>(item->itemBelow());
1987 item =
static_cast<HeaderItem*
>(item->itemAbove());
1994 findUnreadAux( item, foundUnreadMessage, onlyNew, aDirNext );
2002 TQListViewItem *next = item;
2003 while (next->parent())
2004 next = next->parent();
2005 next =
static_cast<HeaderItem*
>(next)->firstChildNonConst();
2006 while (next && (next != item))
2007 if (static_cast<HeaderItem*>(next)->firstChildNonConst())
2008 next = next->firstChild();
2009 else if (next->nextSibling())
2010 next = next->nextSibling();
2012 while (next && (next != item)) {
2013 next = next->parent();
2016 if (next && next->nextSibling()) {
2017 next = next->nextSibling();
2026 findUnreadAux( item, foundUnreadMessage, onlyNew, aDirNext );
2028 return item->
msgId();
2033 if (((unread == 0) && foundUnreadMessage) ||
2034 ((unread > 0) && !foundUnreadMessage)) {
2043 if ( !mFolder || !mFolder->
countUnread() )
return false;
2044 int i = findUnread(
true, -1,
false, acceptCurrent);
2045 if ( i < 0 && GlobalSettings::self()->loopOnGotoUnread() !=
2046 GlobalSettings::EnumLoopOnGotoUnread::DontLoop )
2050 i = findUnread(
true, first->
msgId(),
false, acceptCurrent);
2055 ensureCurrentItemVisible();
2059 void KMHeaders::ensureCurrentItemVisible()
2061 int i = currentItemIndex();
2062 if ((i >= 0) && (i < (
int)mItems.size()))
2063 center( contentsX(), itemPos(mItems[i]), 0, 9.0 );
2069 if ( !mFolder || !mFolder->
countUnread() )
return false;
2070 int i = findUnread(
false);
2071 if ( i < 0 && GlobalSettings::self()->loopOnGotoUnread() !=
2072 GlobalSettings::EnumLoopOnGotoUnread::DontLoop )
2076 i = findUnread(
false, last->
msgId() );
2081 ensureCurrentItemVisible();
2102 ensureItemVisible( currentItem() );
2106 void KMHeaders::highlightMessage(TQListViewItem* lvi,
bool markitread)
2109 if (lvi && !lvi->isSelectable())
return;
2112 if (lvi != mPrevCurrent) {
2113 if (mPrevCurrent && mFolder)
2116 if (prevMsg && mReaderWindowActive)
2120 mFolder->
unGetMsg(mPrevCurrent->msgId());
2123 mPrevCurrent = item;
2127 emit selected( 0 );
return;
2130 int idx = item->
msgId();
2132 if (mReaderWindowActive && !msg) {
2138 BroadcastStatus::instance()->setStatusMsg(
"");
2139 if (markitread && idx >= 0) setMsgRead(idx);
2140 mItems[idx]->irefresh();
2141 mItems[idx]->repaint();
2142 emit selected( msg );
2143 setFolderInfoStatus();
2146 void KMHeaders::highlightCurrentThread()
2148 TQPtrList<TQListViewItem> curThread = currentThread();
2149 TQPtrListIterator<TQListViewItem> it( curThread );
2151 for ( it.toFirst() ; it.current() ; ++it ) {
2152 TQListViewItem *lvi = *it;
2153 lvi->setSelected(
true );
2162 TQTimer::singleShot( ( 60-TQTime::currentTime().second() ) * 1000,
2163 this, TQT_SLOT( resetCurrentTime() ) );
2173 int idx = item->
msgId();
2177 emit activated(mFolder->
getMsg(idx));
2186 void KMHeaders::updateMessageList(
bool set_selection,
bool forceJumpToUnread )
2193 TDEListView::setSorting( mSortCol, !mSortDescending );
2198 readSortOrder( set_selection, forceJumpToUnread );
2199 emit messageListUpdated();
2219 void KMHeaders::keyPressEvent( TQKeyEvent * e )
2221 bool cntrl = (e->state() & ControlButton );
2222 bool shft = (e->state() & ShiftButton );
2223 TQListViewItem *cur = currentItem();
2225 if (!e || !firstChild())
2230 setCurrentItem( firstChild() );
2231 setSelectionAnchor( currentItem() );
2236 if (cur->isSelectable() && e->ascii() ==
' ' ) {
2237 setSelected( cur, !cur->isSelected() );
2238 highlightMessage( cur,
false);
2244 disconnect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
2245 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
2254 TDEListView::keyPressEvent( e );
2257 connect(
this,TQT_SIGNAL(currentChanged(TQListViewItem*)),
2258 this,TQT_SLOT(highlightMessage(TQListViewItem*)));
2269 if (!(lvi->isSelected())) {
2272 setSelected( lvi,
true );
2279 mPressPos = e->pos();
2280 TQListViewItem *lvi = itemAt( contentsToViewport( e->pos() ));
2281 bool wasSelected =
false;
2282 bool rootDecoClicked =
false;
2284 wasSelected = lvi->isSelected();
2286 ( mPressPos.x() <= header()->cellPos( header()->mapToActual( 0 ) ) +
2287 treeStepSize() * ( lvi->depth() + ( rootIsDecorated() ? 1 : 0 ) ) + itemMargin() )
2288 && ( mPressPos.x() >= header()->cellPos( header()->mapToActual( 0 ) ) );
2290 if ( rootDecoClicked ) {
2295 if ( !lvi->isOpen() && lvi->firstChild() ) {
2296 TQListViewItem *nextRoot = lvi->itemBelow();
2297 TQListViewItemIterator it( lvi->firstChild() );
2298 for( ; (*it) != nextRoot; ++it )
2299 (*it)->setSelected(
false );
2305 TDEListView::contentsMousePressEvent(e);
2309 if ( e->state() & ShiftButton ) {
2310 TQListViewItemIterator it(
this, TQListViewItemIterator::Invisible );
2311 while ( it.current() ) {
2312 it.current()->setSelected(
false );
2317 if ( rootDecoClicked ) {
2319 if ( lvi && !lvi->isOpen() && lvi->isSelected() )
2320 setSelected( lvi,
true );
2323 if ( lvi && !rootDecoClicked ) {
2324 if ( lvi != currentItem() )
2325 highlightMessage( lvi );
2330 if ( !( e->state() & ControlButton ) && !wasSelected )
2331 setSelected( lvi,
true );
2333 if ( e->state() & ControlButton )
2334 setSelected( lvi, !wasSelected );
2336 if ((e->button() == Qt::LeftButton) )
2337 mMousePressed =
true;
2341 if ( lvi && e->button() == Qt::LeftButton && !( e->state() & (ShiftButton | ControlButton | AltButton | MetaButton) ) ) {
2342 bool flagsToggleable = GlobalSettings::self()->allowLocalFlags() || !(mFolder ? mFolder->
isReadOnly() :
true);
2343 int section = header()->sectionAt( e->pos().x() );
2346 if ( section == mPaintInfo.flagCol && flagsToggleable ) {
2347 setMsgStatus( KMMsgStatusFlag,
true );
2348 }
else if ( section == mPaintInfo.importantCol && flagsToggleable ) {
2349 setMsgStatus( KMMsgStatusFlag,
true );
2350 }
else if ( section == mPaintInfo.todoCol && flagsToggleable ) {
2351 setMsgStatus( KMMsgStatusTodo,
true );
2352 }
else if ( section == mPaintInfo.watchedIgnoredCol && flagsToggleable ) {
2353 if ( msg->isWatched() || msg->isIgnored() )
2354 setMsgStatus( KMMsgStatusIgnored,
true );
2356 setMsgStatus( KMMsgStatusWatched,
true );
2357 }
else if ( section == mPaintInfo.statusCol ) {
2358 if ( msg->isUnread() || msg->isNew() )
2359 setMsgStatus( KMMsgStatusRead );
2361 setMsgStatus( KMMsgStatusUnread );
2367 void KMHeaders::contentsMouseReleaseEvent(TQMouseEvent* e)
2369 if (e->button() != Qt::RightButton)
2370 TDEListView::contentsMouseReleaseEvent(e);
2372 mMousePressed =
false;
2378 if (mMousePressed &&
2379 (e->pos() - mPressPos).manhattanLength() > TDEGlobalSettings::dndEventDelay()) {
2380 mMousePressed =
false;
2381 TQListViewItem *item = itemAt( contentsToViewport(mPressPos) );
2384 unsigned int count = 0;
2385 for( TQListViewItemIterator it(
this); it.current(); it++ )
2386 if( it.current()->isSelected() ) {
2391 MailSummary mailSummary( msg->getMsgSerNum(), msg->msgIdMD5(),
2392 msg->subject(), msg->fromStrip(),
2393 msg->toStrip(), msg->date() );
2394 mailList.append( mailSummary );
2397 MailListDrag *d =
new MailListDrag( mailList, viewport(),
new KMTextSource );
2402 pixmap = TQPixmap( DesktopIcon(
"message", TDEIcon::SizeSmall) );
2404 pixmap = TQPixmap( DesktopIcon(
"application-vnd.tde.tdemultiple", TDEIcon::SizeSmall) );
2407 if( !pixmap.isNull() ) {
2408 TQPoint hotspot( pixmap.width() / 2, pixmap.height() / 2 );
2409 d->setPixmap( pixmap, hotspot );
2419 void KMHeaders::highlightMessage(TQListViewItem* i)
2421 highlightMessage( i,
false );
2427 if (!topLevelWidget())
return;
2428 mOwner->updateMessageActions();
2431 TQListViewItem *item = itemAt( viewport()->mapFromGlobal( TQCursor::pos() ) );
2433 int section = header()->sectionAt( viewportToContents( viewport()->mapFromGlobal( TQCursor::pos() ) ).x() );
2434 if ( section == mPaintInfo.flagCol || section == mPaintInfo.importantCol
2435 || section == mPaintInfo.todoCol || section == mPaintInfo.statusCol ) {
2436 mOwner->statusMenu()->popup( TQCursor::pos() );
2439 if ( section == mPaintInfo.watchedIgnoredCol ) {
2440 mOwner->threadStatusMenu()->popup( TQCursor::pos() );
2445 TQPopupMenu *menu =
new TQPopupMenu(
this);
2447 mMenuToFolder.clear();
2449 mOwner->updateMessageMenu();
2451 bool out_folder = kmkernel->folderIsDraftOrOutbox( mFolder );
2452 bool tem_folder = kmkernel->folderIsTemplates( mFolder );
2454 mOwner->useAction()->plug( menu );
2457 mOwner->messageActions()->replyMenu()->plug( menu );
2458 mOwner->forwardMenu()->plug( menu );
2459 if( mOwner->sendAgainAction()->isEnabled() ) {
2460 mOwner->sendAgainAction()->plug( menu );
2462 mOwner->editAction()->plug( menu );
2465 menu->insertSeparator();
2467 TQPopupMenu *msgCopyMenu =
new TQPopupMenu(menu);
2468 mOwner->folderTree()->folderToPopupMenu( KMFolderTree::CopyMessage, TQT_TQOBJECT(
this),
2469 &mMenuToFolder, msgCopyMenu );
2470 menu->insertItem(i18n(
"&Copy To"), msgCopyMenu);
2473 int id = menu->insertItem( i18n(
"&Move To") );
2474 menu->setItemEnabled(
id,
false );
2476 TQPopupMenu *msgMoveMenu =
new TQPopupMenu(menu);
2477 mOwner->folderTree()->folderToPopupMenu( KMFolderTree::MoveMessage, TQT_TQOBJECT(
this),
2478 &mMenuToFolder, msgMoveMenu );
2479 menu->insertItem(i18n(
"&Move To"), msgMoveMenu);
2481 menu->insertSeparator();
2482 mOwner->statusMenu()->plug( menu );
2483 if ( mOwner->threadStatusMenu()->isEnabled() ) {
2484 mOwner->threadStatusMenu()->plug( menu );
2487 if ( !out_folder && !tem_folder ) {
2488 menu->insertSeparator();
2489 mOwner->filterMenu()->plug( menu );
2490 mOwner->action(
"apply_filter_actions" )->plug( menu );
2493 menu->insertSeparator();
2494 mOwner->printAction()->plug(menu);
2495 mOwner->saveAsAction()->plug(menu);
2496 mOwner->saveAttachmentsAction()->plug(menu);
2497 menu->insertSeparator();
2499 mOwner->deleteAction()->plug(menu);
2500 if ( mOwner->trashThreadAction()->isEnabled() )
2501 mOwner->deleteThreadAction()->plug(menu);
2503 mOwner->trashAction()->plug(menu);
2504 if ( mOwner->trashThreadAction()->isEnabled() )
2505 mOwner->trashThreadAction()->plug(menu);
2507 menu->insertSeparator();
2508 mOwner->messageActions()->createTodoAction()->plug( menu );
2510 TDEAcceleratorManager::manage(menu);
2511 kmkernel->setContextMenuShown(
true );
2512 menu->exec(TQCursor::pos(), 0);
2513 kmkernel->setContextMenuShown(
false );
2530 return static_cast<HeaderItem*
>(currentItem());
2538 return item->
msgId();
2546 if (!mFolder->
isOpened()) setFolder(mFolder);
2548 if ((msgIdx >= 0) && (msgIdx < (int)mItems.size())) {
2550 bool unchanged = (currentItem() == mItems[msgIdx]);
2551 setCurrentItem( mItems[msgIdx] );
2552 setSelected( mItems[msgIdx],
true );
2553 setSelectionAnchor( currentItem() );
2555 highlightMessage( mItems[msgIdx],
false);
2556 makeHeaderVisible();
2565 return item->
msgId();
2573 if ( aMsgIdx < 0 || static_cast<unsigned int>( aMsgIdx ) >= mItems.size() )
2575 const TQListViewItem *
const item = mItems[aMsgIdx];
2577 setContentsPos( 0, itemPos( item ) );
2581 void KMHeaders::setNestedOverride(
bool override )
2583 mSortInfo.dirty =
true;
2584 mNestedOverride =
override;
2585 setRootIsDecorated( nestingPolicy != AlwaysOpen
2588 unlink(TQFile::encodeName(sortFile));
2593 void KMHeaders::setSubjectThreading(
bool aSubjThreading )
2595 mSortInfo.dirty =
true;
2596 mSubjThreading = aSubjThreading;
2598 unlink(TQFile::encodeName(sortFile));
2605 if ((nestingPolicy != AlwaysOpen)|| open)
2606 ((
HeaderItem*)item)->setOpenRecursive( open );
2619 if ( mIgnoreSortOrderChanges )
2626 if(mSortInfo.dirty || column != mSortInfo.column || ascending != mSortInfo.ascending) {
2627 TQObject::disconnect(header(), TQT_SIGNAL(clicked(
int)),
this, TQT_SLOT(dirtySortOrder(
int)));
2628 mSortInfo.dirty =
true;
2631 assert(column >= 0);
2633 mSortDescending = !ascending;
2635 if (!ascending && (column == mPaintInfo.dateCol))
2636 mPaintInfo.orderOfArrival = !mPaintInfo.orderOfArrival;
2638 if (!ascending && (column == mPaintInfo.subCol))
2639 mPaintInfo.status = !mPaintInfo.status;
2641 TQString colText = i18n(
"Date" );
2642 if (mPaintInfo.orderOfArrival)
2643 colText = i18n(
"Order of Arrival" );
2644 setColumnText( mPaintInfo.dateCol, colText);
2646 colText = i18n(
"Subject" );
2647 if (mPaintInfo.status)
2648 colText = colText + i18n(
" (Status)" );
2649 setColumnText( mPaintInfo.subCol, colText);
2651 TDEListView::setSorting( column, ascending );
2652 ensureCurrentItemVisible();
2656 writeFolderConfig();
2662 static void internalWriteItem(FILE *sortStream,
KMFolder *folder,
int msgid,
2663 int parent_id, TQString key,
2664 bool update_discover=
true)
2666 unsigned long msgSerNum;
2667 unsigned long parentSerNum;
2672 parentSerNum = (
unsigned long)(parent_id + KMAIL_RESERVED);
2674 fwrite(&msgSerNum,
sizeof(msgSerNum), 1, sortStream);
2675 fwrite(&parentSerNum,
sizeof(parentSerNum), 1, sortStream);
2676 TQ_INT32 len = key.length() *
sizeof(TQChar);
2677 fwrite(&len,
sizeof(len), 1, sortStream);
2679 fwrite(key.unicode(), TQMIN(len, KMAIL_MAX_KEY_LEN), 1, sortStream);
2681 if (update_discover) {
2683 TQ_INT32 discovered_count = 0;
2684 fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 20, SEEK_SET);
2685 fread(&discovered_count,
sizeof(discovered_count), 1, sortStream);
2687 fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 20, SEEK_SET);
2688 fwrite(&discovered_count,
sizeof(discovered_count), 1, sortStream);
2694 mSortCacheItems.clear();
2695 mSubjectLists.clear();
2696 mImperfectlyThreadedList.clear();
2704 if ( mFolder->
open(
"kmheaders" ) == 0 )
2705 updateMessageList();
2710 bool KMHeaders::writeSortOrder()
2712 TQString sortFile = KMAIL_SORT_FILE(mFolder);
2714 if (!mSortInfo.dirty) {
2715 struct stat stat_tmp;
2716 if(stat(TQFile::encodeName(sortFile), &stat_tmp) == -1) {
2717 mSortInfo.dirty =
true;
2720 if (mSortInfo.dirty) {
2721 if (!mFolder->
count()) {
2723 unlink(TQFile::encodeName(sortFile));
2726 TQString tempName = sortFile +
".temp";
2727 unlink(TQFile::encodeName(tempName));
2728 FILE *sortStream = fopen(TQFile::encodeName(tempName),
"w");
2732 mSortInfo.ascending = !mSortDescending;
2733 mSortInfo.dirty =
false;
2734 mSortInfo.column = mSortCol;
2735 fprintf(sortStream, KMAIL_SORT_HEADER, KMAIL_SORT_VERSION);
2737 TQ_INT32 byteOrder = 0x12345678;
2738 TQ_INT32 column = mSortCol;
2739 TQ_INT32 ascending= !mSortDescending;
2740 TQ_INT32 threaded = isThreaded();
2741 TQ_INT32 appended=0;
2742 TQ_INT32 discovered_count = 0;
2743 TQ_INT32 sorted_count=0;
2744 fwrite(&byteOrder,
sizeof(byteOrder), 1, sortStream);
2745 fwrite(&column,
sizeof(column), 1, sortStream);
2746 fwrite(&ascending,
sizeof(ascending), 1, sortStream);
2747 fwrite(&threaded,
sizeof(threaded), 1, sortStream);
2748 fwrite(&appended,
sizeof(appended), 1, sortStream);
2749 fwrite(&discovered_count,
sizeof(discovered_count), 1, sortStream);
2750 fwrite(&sorted_count,
sizeof(sorted_count), 1, sortStream);
2752 TQPtrStack<HeaderItem> items;
2754 TQPtrStack<TQListViewItem> s;
2755 for (TQListViewItem * i = firstChild(); i; ) {
2757 if ( i->firstChild() ) {
2759 i = i->firstChild();
2760 }
else if( i->nextSibling()) {
2761 i = i->nextSibling();
2763 for(i=0; !i && s.count(); i = s.pop()->nextSibling())
2777 TQString replymd5 = kmb->replyToIdMD5();
2778 TQString replyToAuxId = kmb->replyToAuxIdMD5();
2780 if(!replymd5.isEmpty())
2781 p = mSortCacheItems[replymd5];
2784 parent_id = p->id();
2790 if (replymd5.isEmpty()
2791 && replyToAuxId.isEmpty()
2792 && !kmb->subjectIsPrefixed() )
2798 internalWriteItem(sortStream, mFolder, i->msgId(), parent_id,
2799 i->key(mSortCol, !mSortDescending),
false);
2805 fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET, SEEK_SET);
2806 fwrite(&byteOrder,
sizeof(byteOrder), 1, sortStream);
2807 fwrite(&column,
sizeof(column), 1, sortStream);
2808 fwrite(&ascending,
sizeof(ascending), 1, sortStream);
2809 fwrite(&threaded,
sizeof(threaded), 1, sortStream);
2810 fwrite(&appended,
sizeof(appended), 1, sortStream);
2811 fwrite(&discovered_count,
sizeof(discovered_count), 1, sortStream);
2812 fwrite(&sorted_count,
sizeof(sorted_count), 1, sortStream);
2813 if (sortStream && ferror(sortStream)) {
2815 unlink(TQFile::encodeName(sortFile));
2816 kdWarning(5006) <<
"Error: Failure modifying " << sortFile <<
" (No space left on device?)" << endl;
2817 kdWarning(5006) << __FILE__ <<
":" << __LINE__ << endl;
2818 kmkernel->emergencyExit( i18n(
"Failure modifying %1\n(No space left on device?)").arg( sortFile ));
2821 ::rename(TQFile::encodeName(tempName), TQFile::encodeName(sortFile));
2827 void KMHeaders::appendItemToSortFile(
HeaderItem *khi)
2829 TQString sortFile = KMAIL_SORT_FILE(mFolder);
2830 if(FILE *sortStream = fopen(TQFile::encodeName(sortFile),
"r+")) {
2837 parent_id = sci->
parent()->id();
2838 else if(kmb->replyToIdMD5().isEmpty()
2839 && kmb->replyToAuxIdMD5().isEmpty()
2840 && !kmb->subjectIsPrefixed())
2844 internalWriteItem(sortStream, mFolder, khi->
msgId(), parent_id,
2845 khi->key(mSortCol, !mSortDescending),
false);
2848 TQ_INT32 appended = 1;
2849 fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);
2850 fwrite(&appended,
sizeof(appended), 1, sortStream);
2851 fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);
2853 if (sortStream && ferror(sortStream)) {
2855 unlink(TQFile::encodeName(sortFile));
2856 kdWarning(5006) <<
"Error: Failure modifying " << sortFile <<
" (No space left on device?)" << endl;
2857 kdWarning(5006) << __FILE__ <<
":" << __LINE__ << endl;
2858 kmkernel->emergencyExit( i18n(
"Failure modifying %1\n(No space left on device?)").arg( sortFile ));
2862 mSortInfo.dirty =
true;
2868 mSortInfo.dirty =
true;
2869 TQObject::disconnect(header(), TQT_SIGNAL(clicked(
int)),
this, TQT_SLOT(dirtySortOrder(
int)));
2870 setSorting(column, mSortInfo.column == column ? !mSortInfo.ascending :
true);
2874 void SortCacheItem::updateSortFile( FILE *sortStream,
KMFolder *folder,
2875 bool waiting_for_parent,
bool update_discover)
2877 if(mSortOffset == -1) {
2878 fseek(sortStream, 0, SEEK_END);
2879 mSortOffset = ftell(sortStream);
2881 fseek(sortStream, mSortOffset, SEEK_SET);
2885 if(!waiting_for_parent) {
2886 if(mParent && !isImperfectlyThreaded())
2887 parent_id = mParent->id();
2889 internalWriteItem(sortStream, folder, mId, parent_id, mKey, update_discover);
2892 static bool compare_ascending =
false;
2893 static bool compare_toplevel =
true;
2894 static int compare_SortCacheItem(
const void *s1,
const void *s2)
2900 int ret = (*b1)->
key().compare((*b2)->key());
2901 if(compare_ascending || !compare_toplevel)
2907 void KMHeaders::printSubjectThreadingTree()
2909 TQDictIterator< TQPtrList< SortCacheItem > > it ( mSubjectLists );
2910 kdDebug(5006) <<
"SubjectThreading tree: " << endl;
2911 for( ; it.current(); ++it ) {
2912 TQPtrList<SortCacheItem> list = *( it.current() );
2913 TQPtrListIterator<SortCacheItem> it2( list ) ;
2914 kdDebug(5006) <<
"Subject MD5: " << it.currentKey() <<
" list: " << endl;
2915 for( ; it2.current(); ++it2 ) {
2917 kdDebug(5006) <<
" item:" << sci <<
" sci id: " << sci->id() << endl;
2920 kdDebug(5006) << endl;
2923 void KMHeaders::printThreadingTree()
2925 kdDebug(5006) <<
"Threading tree: " << endl;
2926 TQDictIterator<SortCacheItem> it( mSortCacheItems );
2927 kdDebug(5006) << endl;
2928 for( ; it.current(); ++it ) {
2930 kdDebug(5006) <<
"MsgId MD5: " << it.currentKey() <<
" message id: " << sci->id() << endl;
2932 for (
int i = 0; i < (int)mItems.size(); ++i) {
2935 kdDebug( 5006 ) <<
"SortCacheItem: " << item->
sortCacheItem()->id() <<
" parent: " << parentCacheId << endl;
2938 kdDebug(5006) << endl;
2943 void KMHeaders::buildThreadingTree( TQMemArray<SortCacheItem *> sortCache )
2945 mSortCacheItems.clear();
2946 mSortCacheItems.resize( mFolder->
count() * 2 );
2949 for(
int x = 0; x < mFolder->
count(); x++) {
2951 TQString md5 = mi->msgIdMD5();
2953 mSortCacheItems.replace(md5, sortCache[x]);
2958 void KMHeaders::buildSubjectThreadingTree( TQMemArray<SortCacheItem *> sortCache )
2960 mSubjectLists.clear();
2961 mSubjectLists.resize( mFolder->
count() * 2 );
2963 for(
int x = 0; x < mFolder->
count(); x++) {
2965 if ( sortCache[x]->parent()
2966 && sortCache[x]->parent()->id() != -666 )
continue;
2968 TQString subjMD5 = mi->strippedSubjectMD5();
2969 if (subjMD5.isEmpty()) {
2970 mFolder->
getMsgBase(x)->initStrippedSubjectMD5();
2971 subjMD5 = mFolder->
getMsgBase(x)->strippedSubjectMD5();
2973 if( subjMD5.isEmpty() )
continue;
2977 if (!mSubjectLists.find(subjMD5))
2978 mSubjectLists.insert(subjMD5,
new TQPtrList<SortCacheItem>());
2984 for (TQPtrListIterator<SortCacheItem> it(*mSubjectLists[subjMD5]);
2985 it.current(); ++it) {
2986 KMMsgBase *mb = mFolder->
getMsgBase((*it)->id());
2987 if ( mb->date() < mi->date())
2991 mSubjectLists[subjMD5]->insert( p, sortCache[x]);
2992 sortCache[x]->setSubjectThreadingList( mSubjectLists[subjMD5] );
3000 if (!item)
return parent;
3001 KMMsgBase *msg = mFolder->
getMsgBase(item->id());
3002 TQString replyToIdMD5 = msg->replyToIdMD5();
3006 if(!replyToIdMD5.isEmpty()) {
3007 parent = mSortCacheItems[replyToIdMD5];
3018 TQString ref = msg->replyToAuxIdMD5();
3020 parent = mSortCacheItems[ref];
3028 if (!item)
return parent;
3030 KMMsgBase *msg = mFolder->
getMsgBase(item->id());
3035 if (!msg->subjectIsPrefixed())
3038 TQString replyToIdMD5 = msg->replyToIdMD5();
3039 TQString subjMD5 = msg->strippedSubjectMD5();
3040 if (!subjMD5.isEmpty() && mSubjectLists[subjMD5]) {
3043 for (TQPtrListIterator<SortCacheItem> it2(*mSubjectLists[subjMD5]);
3044 it2.current(); ++it2) {
3045 KMMsgBase *mb = mFolder->
getMsgBase((*it2)->id());
3046 if ( !mb )
return parent;
3048 if ( item == (*it2) )
continue;
3049 int delta = msg->date() - mb->date();
3054 if (delta < 3628899)
3063 bool KMHeaders::readSortOrder(
bool set_selection,
bool forceJumpToUnread )
3068 TQ_INT32 column, ascending, threaded, discovered_count, sorted_count, appended;
3069 TQ_INT32 deleted_count = 0;
3070 bool unread_exists =
false;
3071 bool jumpToUnread = (GlobalSettings::self()->actionEnterFolder() ==
3072 GlobalSettings::EnumActionEnterFolder::SelectFirstUnreadNew) ||
3076 TQMemArray<SortCacheItem *> sortCache(mFolder->
count());
3080 TQPtrList<SortCacheItem> unparented;
3081 mImperfectlyThreadedList.clear();
3084 mItems.fill( 0, mFolder->
count() );
3085 sortCache.fill( 0 );
3087 mRoot->clearChildren();
3089 TQString sortFile = KMAIL_SORT_FILE(mFolder);
3090 FILE *sortStream = fopen(TQFile::encodeName(sortFile),
"r+");
3091 mSortInfo.fakeSort = 0;
3094 mSortInfo.fakeSort = 1;
3096 if (fscanf(sortStream, KMAIL_SORT_HEADER, &version) != 1)
3098 if(version == KMAIL_SORT_VERSION) {
3099 TQ_INT32 byteOrder = 0;
3100 fread(&byteOrder,
sizeof(byteOrder), 1, sortStream);
3101 if (byteOrder == 0x12345678)
3103 fread(&column,
sizeof(column), 1, sortStream);
3104 fread(&ascending,
sizeof(ascending), 1, sortStream);
3105 fread(&threaded,
sizeof(threaded), 1, sortStream);
3106 fread(&appended,
sizeof(appended), 1, sortStream);
3107 fread(&discovered_count,
sizeof(discovered_count), 1, sortStream);
3108 fread(&sorted_count,
sizeof(sorted_count), 1, sortStream);
3111 TDEListView::setSorting(-1);
3112 header()->setSortIndicator(column, ascending);
3113 TQObject::connect(header(), TQT_SIGNAL(clicked(
int)),
this, TQT_SLOT(dirtySortOrder(
int)));
3115 mSortInfo.dirty =
false;
3116 mSortInfo.column = (short)column;
3117 mSortInfo.ascending = (compare_ascending = ascending);
3120 unsigned long serNum, parentSerNum;
3121 int id, len, parent, x;
3122 TQChar *tmp_qchar = 0;
3123 int tmp_qchar_len = 0;
3124 const int mFolderCount = mFolder->
count();
3127 CREATE_TIMER(parse);
3129 for(x = 0; !feof(sortStream) && !error; x++) {
3130 off_t offset = ftell(sortStream);
3133 if(!fread(&serNum,
sizeof(serNum), 1, sortStream) ||
3134 !fread(&parentSerNum,
sizeof(parentSerNum), 1, sortStream) ||
3135 !fread(&len,
sizeof(len), 1, sortStream)) {
3138 if ((len < 0) || (len > KMAIL_MAX_KEY_LEN)) {
3139 kdDebug(5006) <<
"Whoa.2! len " << len <<
" " << __FILE__ <<
":" << __LINE__ << endl;
3144 if(len > tmp_qchar_len) {
3145 tmp_qchar = (TQChar *)realloc(tmp_qchar, len);
3146 tmp_qchar_len = len;
3148 if(!fread(tmp_qchar, len, 1, sortStream))
3150 key = TQString(tmp_qchar, len / 2);
3156 if (folder != mFolder) {
3160 if (parentSerNum < KMAIL_RESERVED) {
3161 parent = (int)parentSerNum - KMAIL_RESERVED;
3164 if (folder != mFolder)
3167 if ((
id < 0) || (
id >= mFolderCount) ||
3168 (parent < -2) || (parent >= mFolderCount)) {
3169 kdDebug(5006) <<
"Whoa.1! " << __FILE__ <<
":" << __LINE__ << endl;
3174 if ((item=sortCache[
id])) {
3175 if (item->id() != -1) {
3176 kdDebug(5006) <<
"Whoa.3! " << __FILE__ <<
":" << __LINE__ << endl;
3182 item->setOffset(offset);
3186 if (threaded && parent != -2) {
3188 unparented.append(item);
3189 mRoot->addUnsortedChild(item);
3191 if( ! sortCache[parent] ) {
3194 sortCache[parent]->addUnsortedChild(item);
3197 if(x < sorted_count )
3198 mRoot->addSortedChild(item);
3200 mRoot->addUnsortedChild(item);
3204 if (error || (x != sorted_count + discovered_count)) {
3205 kdDebug(5006) << endl <<
"Whoa: x " << x <<
", sorted_count " << sorted_count <<
", discovered_count " << discovered_count <<
", count " << mFolder->
count() << endl << endl;
3226 mSortInfo.dirty =
true;
3227 mSortInfo.column = column = mSortCol;
3228 mSortInfo.ascending = ascending = !mSortDescending;
3229 threaded = (isThreaded());
3230 sorted_count = discovered_count = appended = 0;
3231 TDEListView::setSorting( mSortCol, !mSortDescending );
3234 if((sorted_count + discovered_count - deleted_count) < mFolder->
count()) {
3235 CREATE_TIMER(holes);
3238 for(
int x = 0; x < mFolder->
count(); x++) {
3239 if((!sortCache[x] || (sortCache[x]->
id() < 0)) && (msg=mFolder->
getMsgBase(x))) {
3240 int sortOrder = column;
3241 if (mPaintInfo.orderOfArrival)
3242 sortOrder |= (1 << 6);
3243 if (mPaintInfo.status)
3244 sortOrder |= (1 << 5);
3246 x, HeaderItem::generate_key(
this, msg, &mPaintInfo, sortOrder ));
3248 unparented.append(sortCache[x]);
3250 mRoot->addUnsortedChild(sortCache[x]);
3252 sortCache[x]->updateSortFile(sortStream, mFolder,
true,
true);
3263 if (threaded) buildThreadingTree( sortCache );
3264 TQPtrList<SortCacheItem> toBeSubjThreaded;
3266 if (threaded && !unparented.isEmpty()) {
3267 CREATE_TIMER(reparent);
3268 START_TIMER(reparent);
3270 for(TQPtrListIterator<SortCacheItem> it(unparented); it.current(); ++it) {
3274 if ( parent && (parent != (*it)) ) {
3277 (*it)->updateSortFile(sortStream, mFolder);
3282 toBeSubjThreaded.append((*it));
3284 mRoot->addUnsortedChild((*it));
3288 if (mSubjThreading) {
3289 buildSubjectThreadingTree( sortCache );
3290 for(TQPtrListIterator<SortCacheItem> it(toBeSubjThreaded); it.current(); ++it) {
3297 (*it)->updateSortFile(sortStream, mFolder);
3300 mRoot->addUnsortedChild((*it));
3304 END_TIMER(reparent);
3305 SHOW_TIMER(reparent);
3308 CREATE_TIMER(header_creation);
3309 START_TIMER(header_creation);
3312 TQPtrQueue<SortCacheItem> s;
3314 compare_toplevel =
true;
3318 int unsorted_count, unsorted_off=0;
3322 compare_SortCacheItem);
3328 for(TQPtrListIterator<SortCacheItem> it(*sorted);
3329 (unsorted && unsorted_off < unsorted_count) || it.current(); ) {
3336 ( !unsorted || unsorted_off >= unsorted_count
3338 ( ( !ascending || (ascending && !compare_toplevel) )
3339 && (*it)->key() < unsorted[unsorted_off]->
key() )
3341 ( ascending && (*it)->key() >= unsorted[unsorted_off]->
key() )
3349 new_kci = unsorted[unsorted_off++];
3351 if(new_kci->
item() || new_kci->
parent() != i)
3354 if(threaded && i->
item()) {
3357 if (mFolder->
getMsgBase(i->id())->isWatched())
3359 if (mFolder->
getMsgBase(i->id())->isIgnored())
3365 new_kci->
setItem(mItems[new_kci->id()] = khi);
3370 if ( ( mFolder->
getMsgBase(new_kci->id())->isNew() &&
3371 GlobalSettings::self()->actionEnterFolder() ==
3372 GlobalSettings::EnumActionEnterFolder::SelectFirstNew ) ||
3373 ( ( mFolder->
getMsgBase(new_kci->id())->isNew() ||
3374 mFolder->
getMsgBase(new_kci->id())->isUnread() ) &&
3377 unread_exists =
true;
3380 if ( !oldestItem || mFolder->
getMsgBase( oldestItem->
msgId() )->date() >
3381 mFolder->
getMsgBase( new_kci->id() )->date() ) {
3385 if ( !newestItem || mFolder->
getMsgBase( newestItem->
msgId() )->date() <
3386 mFolder->
getMsgBase( new_kci->id() )->date() ) {
3393 if (mSortCol == paintInfo()->dateCol)
3394 compare_toplevel =
false;
3395 }
while(!s.isEmpty());
3397 for(
int x = 0; x < mFolder->
count(); x++) {
3398 if (!sortCache[x]) {
3402 if (!sortCache[x]->item()) {
3403 kdDebug(5006) <<
"KMHeaders::readSortOrder - msg could not be threaded. " 3404 << endl <<
"Please talk to your threading counselor asap. " << endl;
3405 khi =
new HeaderItem(
this, sortCache[x]->
id(), sortCache[x]->key());
3406 sortCache[x]->setItem(mItems[sortCache[x]->
id()] = khi);
3411 if (threaded && sortCache[x]->isImperfectlyThreaded()) {
3412 mImperfectlyThreadedList.append(sortCache[x]->item());
3416 sortCache[x]->item()->setSortCacheItem(sortCache[x]);
3419 if (getNestingPolicy()<2)
3420 for (
HeaderItem *khi=static_cast<HeaderItem*>(firstChild()); khi!=0;khi=
static_cast<HeaderItem*
>(khi->nextSibling()))
3423 END_TIMER(header_creation);
3424 SHOW_TIMER(header_creation);
3428 if( discovered_count * discovered_count > sorted_count - deleted_count ) {
3429 mSortInfo.dirty =
true;
3433 fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);
3434 fwrite(&appended,
sizeof(appended), 1, sortStream);
3439 CREATE_TIMER(selection);
3440 START_TIMER(selection);
3444 int first_unread = -1;
3445 if (unread_exists) {
3449 GlobalSettings::self()->actionEnterFolder() ==
3450 GlobalSettings::EnumActionEnterFolder::SelectFirstNew ) ||
3455 first_unread = item->
msgId();
3458 item =
static_cast<HeaderItem*
>(item->itemBelow());
3463 if(first_unread == -1 ) {
3464 setTopItemByIndex( mTopItem );
3466 if ( GlobalSettings::self()->actionEnterFolder() ==
3467 GlobalSettings::EnumActionEnterFolder::SelectNewest && newestItem != 0 ) {
3468 setCurrentItemByIndex( newestItem->
msgId() );
3470 else if ( GlobalSettings::self()->actionEnterFolder() ==
3471 GlobalSettings::EnumActionEnterFolder::SelectOldest && oldestItem != 0 ) {
3472 setCurrentItemByIndex( oldestItem->
msgId() );
3474 else if ( mCurrentItem >= 0 )
3475 setCurrentItemByIndex( mCurrentItem );
3476 else if ( mCurrentItemSerNum > 0 )
3477 setCurrentItemBySerialNum( mCurrentItemSerNum );
3479 setCurrentItemByIndex( 0 );
3483 setCurrentItemByIndex(first_unread);
3484 makeHeaderVisible();
3485 center( contentsX(), itemPos(mItems[first_unread]), 0, 9.0 );
3491 if (mCurrentItem <= 0) {
3492 setTopItemByIndex(mTopItem);
3493 setCurrentItemByIndex(0);
3496 END_TIMER(selection);
3497 SHOW_TIMER(selection);
3498 if (error || (sortStream && ferror(sortStream))) {
3501 unlink(TQFile::encodeName(sortFile));
3502 kdWarning(5006) <<
"Error: Failure modifying " << sortFile <<
" (No space left on device?)" << endl;
3503 kdWarning(5006) << __FILE__ <<
":" << __LINE__ << endl;
3519 for (
int i = 0; i < (int)mItems.size() - 1; ++i) {
3520 KMMsgBase *mMsgBase = mFolder->
getMsgBase( i );
3521 if ( mMsgBase->getMsgSerNum() == serialNum ) {
3522 bool unchanged = (currentItem() == mItems[i]);
3523 setCurrentItem( mItems[i] );
3524 setSelected( mItems[i],
true );
3525 setSelectionAnchor( currentItem() );
3527 highlightMessage( currentItem(),
false );
3528 ensureCurrentItemVisible();
3533 kdDebug(5006) <<
"KMHeaders::setCurrentItem item with serial number " << serialNum <<
" NOT FOUND" << endl;
3536 void KMHeaders::copyMessages()
3538 mCopiedMessages.clear();
3539 KMMessageList* list = selectedMsgs();
3540 for ( uint i = 0; i < list->count(); ++ i )
3541 mCopiedMessages << list->at( i )->getMsgSerNum();
3542 mMoveMessages =
false;
3547 void KMHeaders::cutMessages()
3549 mCopiedMessages.clear();
3550 KMMessageList* list = selectedMsgs();
3551 for ( uint i = 0; i < list->count(); ++ i )
3552 mCopiedMessages << list->at( i )->getMsgSerNum();
3553 mMoveMessages =
true;
3558 void KMHeaders::pasteMessages()
3560 new MessageCopyHelper( mCopiedMessages, folder(), mMoveMessages, TQT_TQOBJECT(
this) );
3561 if ( mMoveMessages ) {
3562 mCopiedMessages.clear();
3567 void KMHeaders::updateActions()
3569 TDEAction *copy = owner()->action(
"copy_messages" );
3570 TDEAction *cut = owner()->action(
"cut_messages" );
3571 TDEAction *paste = owner()->action(
"paste_messages" );
3573 if ( selectedItems().isEmpty() ) {
3574 copy->setEnabled(
false );
3575 cut->setEnabled(
false );
3577 copy->setEnabled(
true );
3579 cut->setEnabled(
false );
3581 cut->setEnabled(
true );
3584 if ( mCopiedMessages.isEmpty() || !folder() || folder()->
isReadOnly() )
3585 paste->setEnabled(
false );
3587 paste->setEnabled(
true );
3592 mCopiedMessages = msgs;
3593 mMoveMessages = move;
3599 return mMoveMessages && mCopiedMessages.contains( serNum );
3604 TQValueList<TQ_UINT32> list;
3605 for ( TQListViewItemIterator it(
this); it.current(); it++ ) {
3606 if ( it.current()->isSelected() && it.current()->isVisible() ) {
3610 list.append( msgBase->getMsgSerNum() );
3619 TQValueList<TQ_UINT32> list;
3620 TQListViewItemIterator it(
this, TQListViewItemIterator::Selected|TQListViewItemIterator::Visible);
3621 while( it.current() ) {
3622 if ( it.current()->isSelected() && it.current()->isVisible() ) {
3623 if ( it.current()->parent() && ( !it.current()->parent()->isOpen() ) ) {
3625 TQListViewItem * lastAncestorWithSiblings = it.current()->parent();
3627 while ( ( lastAncestorWithSiblings->depth() > 0 ) && !lastAncestorWithSiblings->nextSibling() )
3628 lastAncestorWithSiblings = lastAncestorWithSiblings->parent();
3630 it = TQListViewItemIterator( lastAncestorWithSiblings->nextSibling() );
3636 list.append( msgBase->getMsgSerNum() );
3645 #include "kmheaders.moc"
TQString indexLocation() const
Returns full path to index file.
SortCacheItem * parent() const
The parent node of the item in the threading hierarchy.
bool canDeleteMessages() const
Can messages in this folder be deleted?
void getLocation(unsigned long key, KMFolder **retFolder, int *retIndex) const
Returns the folder the message represented by the serial number key is in and the index in that folde...
const TQPtrList< SortCacheItem > * sortedChildren() const
The sorted children are an array of sortcache items we know are below the current one and are already...
void msgAdded(int idx)
Emitted when a message is added from the folder.
const TQString & key() const
sort key as used by the listview
const KMMsgBase * getMsgBase(int idx) const
Provides access to the basic message fields that are also stored in the index.
static const KMMsgDict * instance()
Access the globally unique MessageDict.
int countUnread()
Number of new or unread messages in this folder.
void ignoreJobsForMessage(KMMessage *)
Removes and deletes all jobs associated with the particular message.
static TQValueList< unsigned long > serNumList(TQPtrList< KMMsgBase > msgList)
Convert a list of KMMsgBase pointers to a list of serial numbers.
int writeIndex(bool createEmptyIndex=false)
Write index to index-file.
void setImperfectlyThreaded(bool val)
Set whether the item is currently imperfectly threaded (by References or Subject, not by In-Reply-To)...
virtual void setStatus(int idx, KMMsgStatus status, bool toggle=false)
Set the status of the message at index idx to status.
SortCacheItem ** unsortedChildren(int &count) const
The unsorted children are an array of sortcache items we know are below the current one...
TQString msgId() const
Get or set the 'Message-Id' header field.
bool isTrash()
Returns true if this folder is configured as a trash folder, locally or for one of the accounts...
TQPtrList< SortCacheItem > * subjectThreadingList() const
The list of mails with a certain subject that this item is on.
void statusMsg(const TQString &)
Emmited to display a message somewhere in a status line.
void closed(KMFolder *)
Emitted when the folder was closed and ticket owners have to reopen.
FolderJob * createJob(KMMessage *msg, FolderJob::JobType jt=FolderJob::tGetMessage, KMFolder *folder=0, TQString partSpecifier=TQString(), const AttachmentStrategy *as=0) const
These methods create respective FolderJob (You should derive FolderJob for each derived KMFolder)...
void numUnreadMsgsChanged(KMFolder *)
Emitted when number of unread messages has changed.
TQString replyToAuxIdMD5() const
Get the second to last id from the References header field.
HeaderItem * item() const
The corresponding KMail::HeaderItem.
Represents an item in the set of mails to be displayed but only as far as sorting, threading and reading/writing of the current sort order to a disk cache is concerned.
void correctUnreadMsgsCount()
A cludge to help make sure the count of unread messges is kept in sync.
void expunged(KMFolder *)
Emitted after an expunge.
void changed()
Emitted when the status, name, or associated accounts of this folder changed.
virtual void writeConfig()
Write the config file.
void setItem(HeaderItem *i)
Set the corresponding KMail::HeaderItem.
TQString replyToId() const
Get or set the 'In-Reply-To' header field.
bool dirty() const
Returns true if the table of contents is dirty.
bool isComplete() const
Return true if the complete message is available without referring to the backing store...
virtual TQString label() const
Returns the label of the folder for visualization.
TQString idString() const
Returns a string that can be used to identify this folder.
bool isReadOnly() const
Is the folder read-only?
bool transferInProgress() const
Return, if the message should not be deleted.
void cleared()
Emitted when the contents of a folder have been cleared (new search in a search folder, for example)
bool hasChildren() const
Returns whether the item has other items below it.
void markNewAsUnread()
Mark all new messages as unread.
bool isImperfectlyThreaded() const
Returs whether the item is so far imperfectly threaded.
int count(bool cache=false) const
Number of messages in this folder.
void msgHeaderChanged(KMFolder *, int)
Emitted when a field of the header of a specific message changed.
KMMessage * getMsg(int idx)
Read message at given index.
Helper class to copy/move a set of messages defined by their serial numbers from arbitrary folders in...
sets a cursor and makes sure it's restored on destruction Create a KCursorSaver object when you want ...
void msgChanged(KMFolder *, TQ_UINT32 sernum, int delta)
Emitted, when the status of a message is changed.
KMMsgStatus status() const
Status of the message.
void close(const char *owner, bool force=false)
Close folder.
bool isOpened() const
Test if folder is opened.
void addUnsortedChild(SortCacheItem *i)
Add an item to this itme's list of unsorted children.
TQCString id() const
Returns the message ID, useful for followups.
virtual int rename(const TQString &newName, KMFolderDir *aParent=0)
Physically rename the folder.
void addSortedChild(SortCacheItem *i)
Add an item to this itme's list of already sorted children.
virtual bool canDeleteMessages() const
Can messages in this folder be deleted?
unsigned long getMsgSerNum(KMFolder *folder, int index) const
Find the message serial number for the message located at index index in folder folder.
void setTransferInProgress(bool value, bool force=false)
Set that the message shall not be deleted because it is still required.
void setKey(const TQString &key)
Set the sort key used by the list view.
int open(const char *owner)
Open folder for access.
KMMsgInfo * unGetMsg(int idx)
Replace KMMessage with KMMsgInfo and delete KMMessage.
TQString whoField() const
Get / set the name of the field that is used for the Sender/Receiver column in the headers (From/To) ...
void msgRemoved(KMFolder *, TQ_UINT32 sernum)
Emitted before a message is removed from the folder.
virtual int open(const char *owner)=0
Open folder for access.
virtual int count(bool cache=false) const
Number of messages in this folder.