Messagelib

pane.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Kevin Ottens <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "pane.h"
8 
9 #include <KActionCollection>
10 #include <KActionMenu>
11 #include <KLocalizedString>
12 #include <KToggleAction>
13 #include <KXMLGUIClient>
14 #include <QAction>
15 #include <QIcon>
16 #include <QMenu>
17 
18 #include <QAbstractItemModel>
19 #include <QAbstractProxyModel>
20 #include <QApplication>
21 #include <QHeaderView>
22 #include <QItemSelectionModel>
23 #include <QMouseEvent>
24 #include <QRegularExpression>
25 #include <QTabBar>
26 #include <QToolButton>
27 
28 #include "core/manager.h"
29 #include "core/model.h"
30 #include "core/widgets/quicksearchline.h"
31 #include "messagelistsettings.h"
32 #include "messagelistutil_p.h"
33 #include "storagemodel.h"
34 #include "widget.h"
35 #include <Akonadi/MessageStatus>
36 
37 namespace MessageList
38 {
39 class Pane::PanePrivate
40 {
41 public:
42  PanePrivate(Pane *owner)
43  : q(owner)
44  {
45  }
46 
47  void setCurrentFolder(const QModelIndex &etmIndex);
48  void onNewTabClicked();
49  void onCloseTabClicked();
50  void activateTab();
51  void closeTab(QWidget *);
52  void onCurrentTabChanged();
53  void onTabContextMenuRequest(const QPoint &pos);
54  void activateNextTab();
55  void activatePreviousTab();
56  void moveTabLeft();
57  void moveTabRight();
58  void moveTabBackward();
59  void moveTabForward();
60  void changeQuicksearchVisibility(bool);
61  void addActivateTabAction(int i);
62  void slotTabCloseRequested(int index);
63  Q_REQUIRED_RESULT QItemSelection mapSelectionFromSource(const QItemSelection &selection) const;
64  void updateTabControls();
65 
66  Pane *const q;
67 
68  KXMLGUIClient *mXmlGuiClient = nullptr;
69  KActionMenu *mActionMenu = nullptr;
70 
71  QAbstractItemModel *mModel = nullptr;
72  QItemSelectionModel *mSelectionModel = nullptr;
73  Core::PreSelectionMode mPreSelectionMode = Core::PreSelectLastSelected;
74 
75  QHash<Widget *, QItemSelectionModel *> mWidgetSelectionHash;
77 
78  QToolButton *mNewTabButton = nullptr;
79  QToolButton *mCloseTabButton = nullptr;
80  QAction *mCloseTabAction = nullptr;
81  QAction *mActivateNextTabAction = nullptr;
82  QAction *mActivatePreviousTabAction = nullptr;
83  QAction *mMoveTabLeftAction = nullptr;
84  QAction *mMoveTabRightAction = nullptr;
85  bool mPreferEmptyTab = false;
86  int mMaxTabCreated = 0;
87 };
88 } // namespace MessageList
89 
90 using namespace Akonadi;
91 using namespace MessageList;
92 
93 Pane::Pane(bool restoreSession, QAbstractItemModel *model, QItemSelectionModel *selectionModel, QWidget *parent)
94  : QTabWidget(parent)
95  , d(new PanePrivate(this))
96 {
97  setDocumentMode(true);
98  d->mModel = model;
99  d->mSelectionModel = selectionModel;
100 
101  // Build the proxy stack
102  const auto *proxyModel = qobject_cast<const QAbstractProxyModel *>(d->mSelectionModel->model());
103 
104  while (proxyModel) {
105  if (proxyModel == d->mModel) {
106  break;
107  }
108 
109  d->mProxyStack << proxyModel;
110  const auto nextProxyModel = qobject_cast<const QAbstractProxyModel *>(proxyModel->sourceModel());
111 
112  if (!nextProxyModel) {
113  // It's the final model in the chain, so it is necessarily the sourceModel.
114  Q_ASSERT(proxyModel->sourceModel() == d->mModel);
115  break;
116  }
117  proxyModel = nextProxyModel;
118  } // Proxy stack done
119 
120  d->mNewTabButton = new QToolButton(this);
121  d->mNewTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
122  d->mNewTabButton->adjustSize();
123  d->mNewTabButton->setToolTip(i18nc("@info:tooltip", "Open a new tab"));
124 #ifndef QT_NO_ACCESSIBILITY
125  d->mNewTabButton->setAccessibleName(i18n("New tab"));
126 #endif
127  setCornerWidget(d->mNewTabButton, Qt::TopLeftCorner);
128  connect(d->mNewTabButton, &QToolButton::clicked, this, [this]() {
129  d->onNewTabClicked();
130  });
131 
132  d->mCloseTabButton = new QToolButton(this);
133  d->mCloseTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
134  d->mCloseTabButton->adjustSize();
135  d->mCloseTabButton->setToolTip(i18nc("@info:tooltip", "Close the current tab"));
136 #ifndef QT_NO_ACCESSIBILITY
137  d->mCloseTabButton->setAccessibleName(i18n("Close tab"));
138 #endif
139  setCornerWidget(d->mCloseTabButton, Qt::TopRightCorner);
140  connect(d->mCloseTabButton, &QToolButton::clicked, this, [this]() {
141  d->onCloseTabClicked();
142  });
143 
144  setTabsClosable(true);
145  connect(this, &Pane::tabCloseRequested, this, [this](int index) {
146  d->slotTabCloseRequested(index);
147  });
148 
149  readConfig(restoreSession);
150  setMovable(true);
151 
152  connect(this, &Pane::currentChanged, this, [this]() {
153  d->onCurrentTabChanged();
154  });
155 
157  connect(this, &Pane::customContextMenuRequested, this, [this](const QPoint &point) {
158  d->onTabContextMenuRequest(point);
159  });
160 
161  connect(MessageListSettings::self(), &MessageListSettings::configChanged, this, [this]() {
162  d->updateTabControls();
163  });
164 
166 
167  tabBar()->installEventFilter(this);
168 }
169 
170 Pane::~Pane()
171 {
172  saveCurrentSelection();
173  writeConfig(true);
174 }
175 
176 void Pane::PanePrivate::addActivateTabAction(int i)
177 {
178  const QString actionname = QString::asprintf("activate_tab_%02d", i);
179  auto action = new QAction(i18n("Activate Tab %1", i), q);
180  mXmlGuiClient->actionCollection()->addAction(actionname, action);
181  mXmlGuiClient->actionCollection()->setDefaultShortcut(action, QKeySequence(QStringLiteral("Alt+%1").arg(i)));
182  connect(action, &QAction::triggered, q, [this]() {
183  activateTab();
184  });
185 }
186 
187 void Pane::PanePrivate::slotTabCloseRequested(int index)
188 {
189  QWidget *w = q->widget(index);
190  if (w) {
191  closeTab(w);
192  }
193 }
194 
196 {
197  d->mXmlGuiClient = xmlGuiClient;
198 
199  auto const showHideQuicksearch = new KToggleAction(i18n("Show Quick Search Bar"), this);
200  d->mXmlGuiClient->actionCollection()->setDefaultShortcut(showHideQuicksearch, Qt::CTRL | Qt::Key_H);
201  showHideQuicksearch->setChecked(MessageListSettings::showQuickSearch());
202 
203  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("show_quick_search"), showHideQuicksearch);
204  connect(showHideQuicksearch, &KToggleAction::triggered, this, [this](bool state) {
205  d->changeQuicksearchVisibility(state);
206  });
207 
208  for (int i = 0; i < count(); ++i) {
209  auto w = qobject_cast<Widget *>(widget(i));
210  if (w) {
211  w->setXmlGuiClient(d->mXmlGuiClient);
212  }
213  }
214 
215  // Setup "View->Message List" actions.
216  if (xmlGuiClient) {
217  if (d->mActionMenu) {
218  d->mXmlGuiClient->actionCollection()->removeAction(d->mActionMenu);
219  }
220  d->mActionMenu = new KActionMenu(QIcon(), i18n("Message List"), this);
221  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("view_message_list"), d->mActionMenu);
222  MessageList::Util::fillViewMenu(d->mActionMenu->menu(), this);
223 
224  d->mActionMenu->addSeparator();
225 
226  auto action = new QAction(i18n("Create New Tab"), this);
227  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("create_new_tab"), action);
228  d->mXmlGuiClient->actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_O));
229  connect(action, &QAction::triggered, this, [this]() {
230  d->onNewTabClicked();
231  });
232  d->mActionMenu->addAction(action);
233  d->mActionMenu->addSeparator();
234 
235  d->mMaxTabCreated = count();
236  for (int i = 1; i < 10 && i <= count(); ++i) {
237  d->addActivateTabAction(i);
238  }
239 
240  QList<QKeySequence> nextShortcut;
241  QList<QKeySequence> prevShortcut;
242 
243  QString nextIcon;
244  QString prevIcon;
246  nextShortcut.append(KStandardShortcut::tabPrev());
247  prevShortcut.append(KStandardShortcut::tabNext());
248  nextIcon = QStringLiteral("go-previous-view");
249  prevIcon = QStringLiteral("go-next-view");
250  } else {
251  nextShortcut.append(KStandardShortcut::tabNext());
252  prevShortcut.append(KStandardShortcut::tabPrev());
253  nextIcon = QStringLiteral("go-next-view");
254  prevIcon = QStringLiteral("go-previous-view");
255  }
256 
257  d->mActivateNextTabAction = new QAction(i18n("Activate Next Tab"), this);
258  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("activate_next_tab"), d->mActivateNextTabAction);
259  d->mActivateNextTabAction->setEnabled(false);
260  d->mActivateNextTabAction->setIcon(QIcon::fromTheme(nextIcon));
261  d->mXmlGuiClient->actionCollection()->setDefaultShortcuts(d->mActivateNextTabAction, nextShortcut);
262  connect(d->mActivateNextTabAction, &QAction::triggered, [this]() {
263  d->activateNextTab();
264  });
265  d->mActionMenu->addAction(d->mActivateNextTabAction);
266 
267  d->mActivatePreviousTabAction = new QAction(i18n("Activate Previous Tab"), this);
268  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("activate_previous_tab"), d->mActivatePreviousTabAction);
269  d->mXmlGuiClient->actionCollection()->setDefaultShortcuts(d->mActivatePreviousTabAction, prevShortcut);
270  d->mActivatePreviousTabAction->setIcon(QIcon::fromTheme(prevIcon));
271  d->mActivatePreviousTabAction->setEnabled(false);
272  connect(d->mActivatePreviousTabAction, &QAction::triggered, this, [this]() {
273  d->activatePreviousTab();
274  });
275  d->mActionMenu->addAction(d->mActivatePreviousTabAction);
276 
277  d->mActionMenu->addSeparator();
278 
279  d->mMoveTabLeftAction = new QAction(i18n("Move Tab Left"), this);
280  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("move_tab_left"), d->mMoveTabLeftAction);
281  d->mMoveTabLeftAction->setEnabled(false);
282  connect(d->mMoveTabLeftAction, &QAction::triggered, this, [this]() {
283  d->moveTabLeft();
284  });
285  d->mActionMenu->addAction(d->mMoveTabLeftAction);
286 
287  d->mMoveTabRightAction = new QAction(i18n("Move Tab Right"), this);
288  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("move_tab_right"), d->mMoveTabRightAction);
289  d->mMoveTabRightAction->setEnabled(false);
290  connect(d->mMoveTabRightAction, &QAction::triggered, this, [this]() {
291  d->moveTabRight();
292  });
293  d->mActionMenu->addAction(d->mMoveTabRightAction);
294 
295  d->mActionMenu->addSeparator();
296 
297  d->mCloseTabAction = new QAction(i18n("Close Tab"), this);
298  d->mXmlGuiClient->actionCollection()->addAction(QStringLiteral("close_current_tab"), d->mCloseTabAction);
299  d->mXmlGuiClient->actionCollection()->setDefaultShortcuts(d->mCloseTabAction,
302  connect(d->mCloseTabAction, &QAction::triggered, this, [this]() {
303  d->onCloseTabClicked();
304  });
305  d->mActionMenu->addAction(d->mCloseTabAction);
306  d->mCloseTabAction->setEnabled(false);
307  }
308 }
309 
311  MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour,
312  bool centerItem,
313  bool loop)
314 {
315  auto w = static_cast<Widget *>(currentWidget());
316 
317  if (w) {
318  if (w->view()->model()->isLoading()) {
319  return true;
320  }
321 
322  return w->selectNextMessageItem(messageTypeFilter, existingSelectionBehaviour, centerItem, loop);
323  } else {
324  return false;
325  }
326 }
327 
329  MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour,
330  bool centerItem,
331  bool loop)
332 {
333  auto w = static_cast<Widget *>(currentWidget());
334 
335  if (w) {
336  if (w->view()->model()->isLoading()) {
337  return true;
338  }
339 
340  return w->selectPreviousMessageItem(messageTypeFilter, existingSelectionBehaviour, centerItem, loop);
341  } else {
342  return false;
343  }
344 }
345 
346 bool Pane::focusNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop)
347 {
348  auto w = static_cast<Widget *>(currentWidget());
349 
350  if (w) {
351  if (w->view()->model()->isLoading()) {
352  return true;
353  }
354 
355  return w->focusNextMessageItem(messageTypeFilter, centerItem, loop);
356  } else {
357  return false;
358  }
359 }
360 
361 bool Pane::focusPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop)
362 {
363  auto w = static_cast<Widget *>(currentWidget());
364 
365  if (w) {
366  if (w->view()->model()->isLoading()) {
367  return true;
368  }
369 
370  return w->focusPreviousMessageItem(messageTypeFilter, centerItem, loop);
371  } else {
372  return false;
373  }
374 }
375 
376 void Pane::selectFocusedMessageItem(bool centerItem)
377 {
378  auto w = static_cast<Widget *>(currentWidget());
379 
380  if (w) {
381  if (w->view()->model()->isLoading()) {
382  return;
383  }
384 
385  w->selectFocusedMessageItem(centerItem);
386  }
387 }
388 
390 {
391  auto w = static_cast<Widget *>(currentWidget());
392 
393  if (w) {
394  if (w->view()->model()->isLoading()) {
395  return true;
396  }
397 
398  return w->selectFirstMessageItem(messageTypeFilter, centerItem);
399  } else {
400  return false;
401  }
402 }
403 
404 bool Pane::selectLastMessageItem(Core::MessageTypeFilter messageTypeFilter, bool centerItem)
405 {
406  auto w = static_cast<Widget *>(currentWidget());
407 
408  if (w) {
409  if (w->view()->model()->isLoading()) {
410  return true;
411  }
412 
413  return w->selectLastMessageItem(messageTypeFilter, centerItem);
414  } else {
415  return false;
416  }
417 }
418 
420 {
421  auto w = static_cast<Widget *>(currentWidget());
422 
423  if (w) {
424  if (w->view()->model()->isLoading()) {
425  return;
426  }
427 
428  w->selectAll();
429  }
430 }
431 
433 {
434  auto w = static_cast<Widget *>(currentWidget());
435 
436  if (w) {
437  if (w->view()->model()->isLoading()) {
438  return;
439  }
440 
441  w->setCurrentThreadExpanded(expand);
442  }
443 }
444 
446 {
447  auto w = static_cast<Widget *>(currentWidget());
448 
449  if (w) {
450  if (w->view()->model()->isLoading()) {
451  return;
452  }
453 
454  w->setAllThreadsExpanded(expand);
455  }
456 }
457 
458 void Pane::setAllGroupsExpanded(bool expand)
459 {
460  auto w = static_cast<Widget *>(currentWidget());
461 
462  if (w) {
463  if (w->view()->model()->isLoading()) {
464  return;
465  }
466 
467  w->setAllGroupsExpanded(expand);
468  }
469 }
470 
471 void Pane::focusQuickSearch(const QString &selectedText)
472 {
473  auto w = static_cast<Widget *>(currentWidget());
474 
475  if (w) {
476  w->focusQuickSearch(selectedText);
477  }
478 }
479 
480 void Pane::setQuickSearchClickMessage(const QString &msg)
481 {
482  auto w = static_cast<Widget *>(currentWidget());
483 
484  if (w) {
485  w->setQuickSearchClickMessage(msg);
486  }
487 }
488 
489 void Pane::PanePrivate::setCurrentFolder(const QModelIndex &etmIndex)
490 {
491  if (mPreferEmptyTab) {
492  q->createNewTab();
493  }
494 
495  auto w = static_cast<Widget *>(q->currentWidget());
496  QItemSelectionModel *s = mWidgetSelectionHash[w];
497 
498  w->saveCurrentSelection();
499 
500  // Deselect old before we select new - so that the messagelist can clear first.
501  s->clear();
502  if (s->selection().isEmpty()) {
503  w->view()->model()->setPreSelectionMode(mPreSelectionMode);
504  }
505  Q_ASSERT(s->model() == etmIndex.model());
506  s->select(etmIndex, QItemSelectionModel::Select);
507 
508  QString label;
509  QIcon icon;
510  QString toolTip;
511  for (const QModelIndex &index : s->selectedRows()) {
512  label += index.data(Qt::DisplayRole).toString() + QLatin1String(", ");
513  }
514  label.chop(2);
515 
516  if (label.isEmpty()) {
517  label = i18nc("@title:tab Empty messagelist", "Empty");
518  icon = QIcon();
519  } else if (s->selectedRows().size() == 1) {
520  icon = s->selectedRows().first().data(Qt::DecorationRole).value<QIcon>();
521  QModelIndex idx = s->selectedRows().first().parent();
522  toolTip = label;
523  while (idx != QModelIndex()) {
524  toolTip = idx.data().toString() + QLatin1Char('/') + toolTip;
525  idx = idx.parent();
526  }
527  } else {
528  icon = QIcon::fromTheme(QStringLiteral("folder"));
529  }
530 
531  const int index = q->indexOf(w);
532  q->setTabText(index, label);
533  q->setTabIcon(index, icon);
534  q->setTabToolTip(index, toolTip);
535  if (mPreferEmptyTab) {
536  mSelectionModel->select(mapSelectionFromSource(s->selection()), QItemSelectionModel::ClearAndSelect);
537  }
538  mPreferEmptyTab = false;
539 }
540 
541 void Pane::PanePrivate::activateTab()
542 {
543  q->tabBar()->setCurrentIndex(q->sender()->objectName().rightRef(2).toInt() - 1);
544 }
545 
546 void Pane::PanePrivate::moveTabRight()
547 {
548  const int numberOfTab = q->tabBar()->count();
549  if (numberOfTab == 1) {
550  return;
551  }
553  moveTabForward();
554  } else {
555  moveTabBackward();
556  }
557 }
558 
559 void Pane::PanePrivate::moveTabLeft()
560 {
561  const int numberOfTab = q->tabBar()->count();
562  if (numberOfTab == 1) {
563  return;
564  }
566  moveTabBackward();
567  } else {
568  moveTabForward();
569  }
570 }
571 
572 void Pane::PanePrivate::moveTabForward()
573 {
574  const int currentIndex = q->tabBar()->currentIndex();
575  if (currentIndex == q->tabBar()->count() - 1) {
576  return;
577  }
578  q->tabBar()->moveTab(currentIndex, currentIndex + 1);
579 }
580 
581 void Pane::PanePrivate::moveTabBackward()
582 {
583  const int currentIndex = q->tabBar()->currentIndex();
584  if (currentIndex == 0) {
585  return;
586  }
587  q->tabBar()->moveTab(currentIndex, currentIndex - 1);
588 }
589 
590 void Pane::PanePrivate::activateNextTab()
591 {
592  const int numberOfTab = q->tabBar()->count();
593  if (numberOfTab == 1) {
594  return;
595  }
596 
597  int indexTab = (q->tabBar()->currentIndex() + 1);
598 
599  if (indexTab == numberOfTab) {
600  indexTab = 0;
601  }
602 
603  q->tabBar()->setCurrentIndex(indexTab);
604 }
605 
606 void Pane::PanePrivate::activatePreviousTab()
607 {
608  const int numberOfTab = q->tabBar()->count();
609  if (numberOfTab == 1) {
610  return;
611  }
612 
613  int indexTab = (q->tabBar()->currentIndex() - 1);
614 
615  if (indexTab == -1) {
616  indexTab = numberOfTab - 1;
617  }
618 
619  q->tabBar()->setCurrentIndex(indexTab);
620 }
621 
622 void Pane::PanePrivate::onNewTabClicked()
623 {
624  q->createNewTab();
625 }
626 
627 void Pane::PanePrivate::onCloseTabClicked()
628 {
629  closeTab(q->currentWidget());
630 }
631 
632 void Pane::PanePrivate::closeTab(QWidget *w)
633 {
634  if (!w || (q->count() < 2)) {
635  return;
636  }
637 
638  auto wWidget = qobject_cast<Widget *>(w);
639  if (wWidget) {
640  wWidget->saveCurrentSelection();
641  }
642 
643  delete w;
644  updateTabControls();
645 }
646 
647 void Pane::PanePrivate::changeQuicksearchVisibility(bool show)
648 {
649  for (int i = 0; i < q->count(); ++i) {
650  auto w = qobject_cast<Widget *>(q->widget(i));
651  if (w) {
652  w->changeQuicksearchVisibility(show);
653  }
654  }
655 }
656 
657 bool Pane::eventFilter(QObject *object, QEvent *event)
658 {
659  if (event->type() == QEvent::MouseButtonPress) {
660  auto const mouseEvent = static_cast<QMouseEvent *>(event);
661  if (mouseEvent->button() == Qt::MiddleButton) {
662  return true;
663  }
664  }
665  return QTabWidget::eventFilter(object, event);
666 }
667 
668 void Pane::PanePrivate::onCurrentTabChanged()
669 {
670  Q_EMIT q->currentTabChanged();
671 
672  auto w = static_cast<Widget *>(q->currentWidget());
673 
674  QItemSelectionModel *s = mWidgetSelectionHash[w];
675 
676  mSelectionModel->select(mapSelectionFromSource(s->selection()), QItemSelectionModel::ClearAndSelect);
677 }
678 
679 void Pane::PanePrivate::onTabContextMenuRequest(const QPoint &pos)
680 {
681  QTabBar *bar = q->tabBar();
682  if (q->count() <= 1) {
683  return;
684  }
685 
686  const int indexBar = bar->tabAt(bar->mapFrom(q, pos));
687  if (indexBar == -1) {
688  return;
689  }
690 
691  auto w = qobject_cast<Widget *>(q->widget(indexBar));
692  if (!w) {
693  return;
694  }
695 
696  QMenu menu(q);
697 
698  QAction *closeTabAction = menu.addAction(i18nc("@action:inmenu", "Close Tab"));
699  closeTabAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
700 
701  QAction *allOtherAction = menu.addAction(i18nc("@action:inmenu", "Close All Other Tabs"));
702  allOtherAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-close-other")));
703 
704  QAction *lockTabAction = menu.addAction(w->isLocked() ? i18nc("@action:inmenu", "Unlock Tab") : i18nc("@action:inmenu", "Lock Tab"));
705  lockTabAction->setIcon(w->isLocked() ? QIcon::fromTheme(QStringLiteral("lock")) : QIcon::fromTheme(QStringLiteral("unlock")));
706 
707  QAction *action = menu.exec(q->mapToGlobal(pos));
708 
709  if (action == allOtherAction) { // Close all other tabs
710  QVector<Widget *> widgets;
711  const int index = q->indexOf(w);
712 
713  for (int i = 0; i < q->count(); ++i) {
714  if (i == index) {
715  continue; // Skip the current one
716  }
717 
718  auto other = qobject_cast<Widget *>(q->widget(i));
719  if (other) {
720  widgets << other;
721  }
722  }
723 
724  for (Widget *other : std::as_const(widgets)) {
725  other->saveCurrentSelection();
726  delete other;
727  }
728 
729  updateTabControls();
730  } else if (action == closeTabAction) {
731  closeTab(q->widget(indexBar));
732  } else if (action == lockTabAction) {
733  auto tab = qobject_cast<Widget *>(q->widget(indexBar));
734  const bool isLocked = !tab->isLocked();
735  tab->setLockTab(isLocked);
736  q->setTabIcon(indexBar, isLocked ? QIcon::fromTheme(QStringLiteral("lock")) : QIcon::fromTheme(QStringLiteral("unlock")));
737  }
738 }
739 
740 MessageList::StorageModel *Pane::createStorageModel(QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent)
741 {
742  return new MessageList::StorageModel(model, selectionModel, parent);
743 }
744 
745 Akonadi::Collection Pane::currentFolder() const
746 {
747  auto w = static_cast<Widget *>(currentWidget());
748  if (w) {
749  return w->currentCollection();
750  }
751  return {};
752 }
753 
755  const QModelIndex &etmIndex,
756  bool,
757  Core::PreSelectionMode preSelectionMode,
758  const QString &overrideLabel)
759 {
760  auto w = static_cast<Widget *>(currentWidget());
761  if (!w->isLocked()) {
762  d->setCurrentFolder(etmIndex);
763  d->mPreSelectionMode = preSelectionMode;
764  if (w) {
765  w->setCurrentFolder(collection);
766  QItemSelectionModel *s = d->mWidgetSelectionHash[w];
767  MessageList::StorageModel *m = createStorageModel(d->mModel, s, w);
768  w->setStorageModel(m, preSelectionMode);
769  if (!overrideLabel.isEmpty()) {
770  const int index = indexOf(w);
771  setTabText(index, overrideLabel);
772  }
773  }
774  }
775 }
776 
777 void Pane::updateTabIconText(const Akonadi::Collection &collection, const QString &label, const QIcon &icon)
778 {
779  for (int i = 0; i < count(); ++i) {
780  auto w = qobject_cast<Widget *>(widget(i));
781  if (w && (w->currentCollection() == collection)) {
782  const int index = indexOf(w);
783  setTabText(index, label);
784  setTabIcon(index, icon);
785  }
786  }
787 }
788 
790 {
791  auto w = new Widget(this);
792  w->setXmlGuiClient(d->mXmlGuiClient);
793 
794  addTab(w, i18nc("@title:tab Empty messagelist", "Empty"));
795 
796  if (d->mXmlGuiClient && count() < 10) {
797  if (d->mMaxTabCreated < count()) {
798  d->mMaxTabCreated = count();
799  d->addActivateTabAction(d->mMaxTabCreated);
800  }
801  }
802 
803  auto s = new QItemSelectionModel(d->mModel, w);
804  MessageList::StorageModel *m = createStorageModel(d->mModel, s, w);
805  w->setStorageModel(m);
806 
807  d->mWidgetSelectionHash[w] = s;
808 
813 
815 
816  connect(w, &Core::Widget::forceLostFocus, this, &Pane::forceLostFocus);
817  connect(w, &Core::Widget::unlockTabRequested, this, [this, w]() {
818  for (int i = 0; i < count(); ++i) {
819  if (w == qobject_cast<Widget *>(widget(i))) {
820  setTabIcon(i, QIcon::fromTheme(QStringLiteral("unlock")));
821  }
822  }
823  });
824 
825  d->updateTabControls();
826  setCurrentWidget(w);
827  return s;
828 }
829 
830 QItemSelection Pane::PanePrivate::mapSelectionFromSource(const QItemSelection &selection) const
831 {
832  QItemSelection result = selection;
833 
835 
836  for (Iterator it = mProxyStack.end() - 1; it != mProxyStack.begin(); --it) {
837  result = (*it)->mapSelectionFromSource(result);
838  }
839  result = mProxyStack.first()->mapSelectionFromSource(result);
840 
841  return result;
842 }
843 
844 void Pane::PanePrivate::updateTabControls()
845 {
846  const bool enableAction = (q->count() > 1);
847  if (enableAction) {
848  q->setCornerWidget(mCloseTabButton, Qt::TopRightCorner);
849  mCloseTabButton->setVisible(true);
850  } else {
851  q->setCornerWidget(nullptr, Qt::TopRightCorner);
852  }
853  if (mCloseTabAction) {
854  mCloseTabAction->setEnabled(enableAction);
855  }
856  if (mActivatePreviousTabAction) {
857  mActivatePreviousTabAction->setEnabled(enableAction);
858  }
859  if (mActivateNextTabAction) {
860  mActivateNextTabAction->setEnabled(enableAction);
861  }
862  if (mMoveTabRightAction) {
863  mMoveTabRightAction->setEnabled(enableAction);
864  }
865  if (mMoveTabLeftAction) {
866  mMoveTabLeftAction->setEnabled(enableAction);
867  }
868 
869  q->tabBar()->setVisible(enableAction);
870  if (enableAction) {
871  q->setCornerWidget(mNewTabButton, Qt::TopLeftCorner);
872  mNewTabButton->setVisible(true);
873  } else {
874  q->setCornerWidget(nullptr, Qt::TopLeftCorner);
875  }
876 
877  q->setTabsClosable(true);
878  const int numberOfTab(q->count());
879  if (numberOfTab == 1) {
880  q->tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(false);
881  } else if (numberOfTab > 1) {
882  q->tabBar()->tabButton(0, QTabBar::RightSide)->setEnabled(true);
883  }
884 }
885 
887 {
888  auto w = static_cast<Widget *>(currentWidget());
889 
890  if (!w) {
891  return {};
892  }
893 
894  return w->currentItem();
895 }
896 
898 {
899  auto w = static_cast<Widget *>(currentWidget());
900 
901  if (!w) {
902  return {};
903  }
904 
905  return w->currentMessage();
906 }
907 
908 QVector<KMime::Message::Ptr> Pane::selectionAsMessageList(bool includeCollapsedChildren) const
909 {
910  auto w = static_cast<Widget *>(currentWidget());
911  if (!w) {
912  return {};
913  }
914  return w->selectionAsMessageList(includeCollapsedChildren);
915 }
916 
917 Akonadi::Item::List Pane::selectionAsMessageItemList(bool includeCollapsedChildren) const
918 {
919  auto w = static_cast<Widget *>(currentWidget());
920  if (!w) {
921  return {};
922  }
923  return w->selectionAsMessageItemList(includeCollapsedChildren);
924 }
925 
926 QVector<Akonadi::Item::Id> Pane::selectionAsListMessageId(bool includeCollapsedChildren) const
927 {
928  auto w = static_cast<Widget *>(currentWidget());
929  if (!w) {
930  return {};
931  }
932  return w->selectionAsListMessageId(includeCollapsedChildren);
933 }
934 
935 QVector<qlonglong> Pane::selectionAsMessageItemListId(bool includeCollapsedChildren) const
936 {
937  auto w = static_cast<Widget *>(currentWidget());
938  if (!w) {
939  return {};
940  }
941  return w->selectionAsMessageItemListId(includeCollapsedChildren);
942 }
943 
945 {
946  auto w = static_cast<Widget *>(currentWidget());
947  if (!w) {
948  return {};
949  }
950  return w->currentThreadAsMessageList();
951 }
952 
953 Akonadi::Item::List Pane::itemListFromPersistentSet(MessageList::Core::MessageItemSetReference ref)
954 {
955  auto w = static_cast<Widget *>(currentWidget());
956  if (w) {
957  return w->itemListFromPersistentSet(ref);
958  }
959  return {};
960 }
961 
962 void Pane::deletePersistentSet(MessageList::Core::MessageItemSetReference ref)
963 {
964  auto w = static_cast<Widget *>(currentWidget());
965  if (w) {
966  w->deletePersistentSet(ref);
967  }
968 }
969 
970 void Pane::markMessageItemsAsAboutToBeRemoved(MessageList::Core::MessageItemSetReference ref, bool bMark)
971 {
972  auto w = static_cast<Widget *>(currentWidget());
973  if (w) {
974  w->markMessageItemsAsAboutToBeRemoved(ref, bMark);
975  }
976 }
977 
979 {
980  auto w = static_cast<Widget *>(currentWidget());
981  if (!w) {
982  return {};
983  }
984  return w->currentFilterStatus();
985 }
986 
987 Core::QuickSearchLine::SearchOptions Pane::currentOptions() const
988 {
989  auto w = static_cast<Widget *>(currentWidget());
990  if (!w) {
991  return Core::QuickSearchLine::SearchEveryWhere;
992  }
993  return w->currentOptions();
994 }
995 
997 {
998  auto w = static_cast<Widget *>(currentWidget());
999  if (w) {
1000  return w->currentFilterSearchString();
1001  }
1002  return {};
1003 }
1004 
1005 bool Pane::isThreaded() const
1006 {
1007  auto w = static_cast<Widget *>(currentWidget());
1008  if (w) {
1009  return w->isThreaded();
1010  }
1011  return false;
1012 }
1013 
1015 {
1016  auto w = static_cast<Widget *>(currentWidget());
1017  if (w) {
1018  return w->selectionEmpty();
1019  }
1020  return false;
1021 }
1022 
1024  Akonadi::Item::List &selectedVisibleItems,
1025  bool *allSelectedBelongToSameThread,
1026  bool includeCollapsedChildren) const
1027 {
1028  auto w = static_cast<Widget *>(currentWidget());
1029  if (!w) {
1030  return false;
1031  }
1032 
1033  return w->getSelectionStats(selectedItems, selectedVisibleItems, allSelectedBelongToSameThread, includeCollapsedChildren);
1034 }
1035 
1036 MessageList::Core::MessageItemSetReference Pane::selectionAsPersistentSet(bool includeCollapsedChildren) const
1037 {
1038  auto w = static_cast<Widget *>(currentWidget());
1039  if (w) {
1040  return w->selectionAsPersistentSet(includeCollapsedChildren);
1041  }
1042  return -1;
1043 }
1044 
1045 MessageList::Core::MessageItemSetReference Pane::currentThreadAsPersistentSet() const
1046 {
1047  auto w = static_cast<Widget *>(currentWidget());
1048  if (w) {
1049  return w->currentThreadAsPersistentSet();
1050  }
1051  return -1;
1052 }
1053 
1055 {
1056  auto w = static_cast<Widget *>(currentWidget());
1057  if (w) {
1058  QWidget *view = w->view();
1059  if (view) {
1060  view->setFocus();
1061  }
1062  }
1063 }
1064 
1066 {
1067  d->updateTabControls();
1068 }
1069 
1071 {
1072  auto w = static_cast<Widget *>(currentWidget());
1073  if (w) {
1074  return w->view()->selectionModel();
1075  }
1076  return nullptr;
1077 }
1078 
1079 void Pane::resetModelStorage()
1080 {
1081  auto w = static_cast<Widget *>(currentWidget());
1082  if (w) {
1083  auto m = static_cast<MessageList::StorageModel *>(w->storageModel());
1084  if (m) {
1085  m->resetModelStorage();
1086  }
1087  }
1088 }
1089 
1090 void Pane::setPreferEmptyTab(bool emptyTab)
1091 {
1092  d->mPreferEmptyTab = emptyTab;
1093 }
1094 
1095 void Pane::saveCurrentSelection()
1096 {
1097  for (int i = 0; i < count(); ++i) {
1098  auto w = qobject_cast<Widget *>(widget(i));
1099  if (w) {
1100  w->saveCurrentSelection();
1101  }
1102  }
1103 }
1104 
1105 void Pane::updateTagComboBox()
1106 {
1107  for (int i = 0; i < count(); ++i) {
1108  auto w = qobject_cast<Widget *>(widget(i));
1109  if (w) {
1110  w->populateStatusFilterCombo();
1111  }
1112  }
1113 }
1114 
1115 void Pane::writeConfig(bool restoreSession)
1116 {
1117  KConfigGroup conf(MessageList::MessageListSettings::self()->config(), "MessageListPane");
1118 
1119  // Delete list before
1120  const QStringList list = MessageList::MessageListSettings::self()->config()->groupList().filter(QRegularExpression(QStringLiteral("MessageListTab\\d+")));
1121  for (const QString &group : list) {
1122  MessageList::MessageListSettings::self()->config()->deleteGroup(group);
1123  }
1124 
1125  if (restoreSession) {
1126  conf.writeEntry(QStringLiteral("currentIndex"), currentIndex());
1127  conf.writeEntry(QStringLiteral("tabNumber"), count());
1128 
1129  for (int i = 0; i < count(); ++i) {
1130  auto w = qobject_cast<Widget *>(widget(i));
1131  if (w) {
1132  KConfigGroup grp(MessageList::MessageListSettings::self()->config(), QStringLiteral("MessageListTab%1").arg(i));
1133  grp.writeEntry(QStringLiteral("collectionId"), w->currentCollection().id());
1134  grp.writeEntry(QStringLiteral("HeaderState"), w->view()->header()->saveState());
1135  }
1136  }
1137  }
1138  conf.sync();
1139 }
1140 
1141 void Pane::readConfig(bool restoreSession)
1142 {
1143  if (MessageList::MessageListSettings::self()->config()->hasGroup(QStringLiteral("MessageListPane"))) {
1144  KConfigGroup conf(MessageList::MessageListSettings::self()->config(), "MessageListPane");
1145  const int numberOfTab = conf.readEntry(QStringLiteral("tabNumber"), 0);
1146  if (numberOfTab == 0) {
1147  createNewTab();
1148  } else {
1149  for (int i = 0; i < numberOfTab; ++i) {
1150  createNewTab();
1151  restoreHeaderSettings(i);
1152  if (restoreSession) {
1153 #if 0 // TODO fix me
1154  Akonadi::Collection::Id id = grp.readEntry(QStringLiteral("collectionId"), -1);
1155  ETMViewStateSaver *saver = new ETMViewStateSaver;
1156  saver->setSelectionModel(selectionModel);
1157 
1158  if (id != -1) {
1159  ETMViewStateSaver *saver = new ETMViewStateSaver;
1160  saver->setSelectionModel(selectionModel);
1161  saver->restoreState(grp);
1162  saver->selectCollections(Akonadi::Collection::List() << Akonadi::Collection(id));
1163  saver->restoreCurrentItem(QString::fromLatin1("c%1").arg(id));
1164  }
1165 #endif
1166  }
1167  }
1168  setCurrentIndex(conf.readEntry(QStringLiteral("currentIndex"), 0));
1169  }
1170  } else {
1171  createNewTab();
1172  restoreHeaderSettings(0);
1173  }
1174 }
1175 
1176 void Pane::restoreHeaderSettings(int index)
1177 {
1178  KConfigGroup grp(MessageList::MessageListSettings::self()->config(), QStringLiteral("MessageListTab%1").arg(index));
1179  if (grp.exists()) {
1180  auto w = qobject_cast<Widget *>(widget(index));
1181  if (w) {
1182  w->view()->header()->restoreState(grp.readEntry(QStringLiteral("HeaderState"), QByteArray()));
1183  }
1184  }
1185 }
1186 
1187 bool Pane::searchEditHasFocus() const
1188 {
1189  auto w = static_cast<Widget *>(currentWidget());
1190  if (w) {
1191  return w->searchEditHasFocus();
1192  }
1193  return false;
1194 }
1195 
1196 void Pane::sortOrderMenuAboutToShow()
1197 {
1198  auto menu = qobject_cast<QMenu *>(sender());
1199  if (!menu) {
1200  return;
1201  }
1202  const Widget *const w = static_cast<Widget *>(currentWidget());
1203  w->view()->sortOrderMenuAboutToShow(menu);
1204 }
1205 
1206 void Pane::aggregationMenuAboutToShow()
1207 {
1208  auto menu = qobject_cast<QMenu *>(sender());
1209  if (!menu) {
1210  return;
1211  }
1212  const Widget *const w = static_cast<Widget *>(currentWidget());
1213  w->view()->aggregationMenuAboutToShow(menu);
1214 }
1215 
1216 void Pane::themeMenuAboutToShow()
1217 {
1218  auto menu = qobject_cast<QMenu *>(sender());
1219  if (!menu) {
1220  return;
1221  }
1222  const Widget *const w = static_cast<Widget *>(currentWidget());
1223  w->view()->themeMenuAboutToShow(menu);
1224 }
1225 
1226 void Pane::populateStatusFilterCombo()
1227 {
1228  for (int i = 0; i < count(); ++i) {
1229  auto w = qobject_cast<Widget *>(widget(i));
1230  if (w) {
1232  }
1233  }
1234 }
1235 
1236 #include "moc_pane.cpp"
void append(const T &value)
T & first()
const QList< QKeySequence > & tabPrev()
void markMessageItemsAsAboutToBeRemoved(MessageList::Core::MessageItemSetReference ref, bool bMark)
If bMark is true this function marks the messages as "about to be removed" so they appear dimmer and ...
Definition: pane.cpp:970
bool selectionEmpty() const
Fast function that determines if the selection is empty.
Definition: pane.cpp:1014
int indexOf(QWidget *w) const const
void tabBarDoubleClicked(int index)
bool selectLastMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem)
Selects the last message item in the view that matches the specified Core::MessageTypeFilter.
Definition: pane.cpp:404
DisplayRole
MouseButtonPress
void focusQuickSearch(const QString &selectedText=QString())
Sets the focus on the quick search line of the currently active tab.
Definition: pane.cpp:471
QPoint mapFrom(const QWidget *parent, const QPoint &pos) const const
QVector< qlonglong > selectionAsMessageItemListId(bool includeCollapsedChildren=true) const
Returns the currently selected Items id(bound to current StorageModel).
Definition: pane.cpp:935
void reloadGlobalConfiguration()
Reloads global configuration and eventually reloads all the views.
Definition: pane.cpp:1065
const QItemSelection selection() const const
const QAbstractItemModel * model() const const
KMime::Message::Ptr currentMessage() const
Returns the current message for the list as KMime::Message::Ptr.
Definition: pane.cpp:897
void messageSelected(const Akonadi::Item &item)
Emitted when a message is selected (that is, single clicked and thus made current in the view) Note t...
void customContextMenuRequested(const QPoint &pos)
MessageList::Core::MessageItemSetReference selectionAsPersistentSet(bool includeCollapsedChildren=true) const
Return a persistent set from current selection.
Definition: pane.cpp:1036
void setCurrentThreadExpanded(bool expand)
If expand is true then it expands the current thread, otherwise collapses it.
Definition: pane.cpp:432
void setTabText(int index, const QString &label)
void messageSelected(const Akonadi::Item &item)
Emitted when a message is selected (that is, single clicked and thus made current in the view) Note t...
void clicked(bool checked)
QIcon fromTheme(const QString &name)
void chop(int n)
int indexOf(const T &value, int from) const const
void selectFocusedMessageItem(bool centerItem)
Selects the currently focused message item.
Definition: pane.cpp:376
QObject * sender() const const
bool isThreaded() const
Returns true if the current Aggregation is threaded, false otherwise (or if there is no current Aggre...
Definition: pane.cpp:1005
CustomContextMenu
void setTabsClosable(bool closeable)
TopLeftCorner
void setMovable(bool movable)
int tabAt(const QPoint &position) const const
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
MiddleButton
void selectionChanged()
Emitted when the selection in the view changes.
void setCornerWidget(QWidget *widget, Qt::Corner corner)
View * view() const
Returns the View attached to this Widget.
Definition: widgetbase.cpp:386
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
The Akonadi specific implementation of the Core::Widget.
Definition: widget.h:32
virtual bool eventFilter(QObject *watched, QEvent *event)
MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const
Return a persistent set from current thread.
Definition: pane.cpp:1045
void setIcon(const QIcon &icon)
Akonadi::Item::List itemListFromPersistentSet(MessageList::Core::MessageItemSetReference ref)
Return Akonadi::Item from messageItemReference.
Definition: pane.cpp:953
QStringList filter(QStringView str, Qt::CaseSensitivity cs) const const
QString i18n(const char *text, const TYPE &arg...)
void setCurrentFolder(const Akonadi::Collection &fld, const QModelIndex &etmIndex, bool preferEmptyTab=false, MessageList::Core::PreSelectionMode preSelectionMode=MessageList::Core::PreSelectLastSelected, const QString &overrideLabel=QString())
Sets the current folder to be displayed by this Pane.
Definition: pane.cpp:754
bool selectFirstMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem)
Selects the first message item in the view that matches the specified Core::MessageTypeFilter.
Definition: pane.cpp:389
const QList< QKeySequence > & tabNext()
QWidget * widget(int index) const const
void installEventFilter(QObject *filterObj)
bool isEmpty() const const
void focusView()
Sets the focus on the view of the currently active tab.
Definition: pane.cpp:1054
void currentChanged(int index)
The Akonadi specific implementation of the Core::StorageModel.
Definition: storagemodel.h:35
void messageStatusChangeRequest(const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear)
Emitted when a message wants its status to be changed.
bool isEmpty() const const
PreSelectionMode
Pre-selection is the action of automatically selecting a message just after the folder has finished l...
void setCurrentWidget(QWidget *widget)
Akonadi::Item::List currentThreadAsMessageList() const
Returns the Akonadi::Item bound to the current StorageModel that are part of the current thread.
Definition: pane.cpp:944
KSharedConfigPtr config()
bool selectPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, bool centerItem, bool loop)
Selects the previous message item in the view.
Definition: pane.cpp:328
QWidget * currentWidget() const const
void setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
Sets the XML GUI client which the pane is used in.
Definition: pane.cpp:195
QItemSelectionModel * currentItemSelectionModel()
Returns the QItemSelectionModel for the currently displayed tab.
Definition: pane.cpp:1070
bool isRightToLeft()
void setAllGroupsExpanded(bool expand)
If expand is true then it expands all the groups (only the toplevel group item: inner threads are NOT...
Definition: pane.cpp:458
QString currentFilterSearchString() const
Returns the search term in the current quicksearch field.
Definition: pane.cpp:996
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void populateStatusFilterCombo()
This is called to setup the status filter's QComboBox.
Definition: widgetbase.cpp:212
QString label(StandardShortcut id)
void selectAll()
Selects all the items in the current folder.
Definition: pane.cpp:419
void setAllThreadsExpanded(bool expand)
If expand is true then it expands all the threads, otherwise collapses them.
Definition: pane.cpp:445
void statusMessage(const QString &message)
Notify the outside when updating the status bar with a message could be useful.
QTabBar * tabBar() const const
bool selectNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, bool centerItem, bool loop)
Selects the next message item in the view.
Definition: pane.cpp:310
void triggered(bool checked)
void messageActivated(const Akonadi::Item &item)
Emitted when a message is doubleclicked or activated by other input means.
void statusMessage(const QString &message)
Notify the outside when updating the status bar with a message could be useful.
QModelIndexList selectedRows(int column) const const
QString fromLatin1(const char *str, int size)
void messageActivated(const Akonadi::Item &item)
Emitted when a message is doubleclicked or activated by other input means.
QItemSelectionModel * createNewTab()
Add a new tab to the Pane and select it.
Definition: pane.cpp:789
int addTab(QWidget *page, const QString &label)
bool focusNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop)
Focuses the next message item in the view without actually selecting it.
Definition: pane.cpp:346
void selectionChanged()
Emitted when the selection in the view changes.
ExistingSelectionBehaviour
This enum is used in the view message selection functions (for instance View::selectNextMessage())
This is the main MessageList panel for Akonadi applications.
Definition: pane.h:45
QVector< KMime::Message::Ptr > selectionAsMessageList(bool includeCollapsedChildren=true) const
Returns the currently selected KMime::Message::Ptr (bound to current StorageModel).
Definition: pane.cpp:908
bool getSelectionStats(Akonadi::Item::List &selectedItems, Akonadi::Item::List &selectedVisibleItems, bool *allSelectedBelongToSameThread, bool includeCollapsedChildren=true) const
Fills the lists of the selected message serial numbers and of the selected+visible ones.
Definition: pane.cpp:1023
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void setDocumentMode(bool set)
bool focusPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop)
Focuses the previous message item in the view without actually selecting it.
Definition: pane.cpp:361
void messageStatusChangeRequest(const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear)
Emitted when a message wants its status to be changed.
void setTabIcon(int index, const QIcon &icon)
QChar * data()
MessageTypeFilter
This enum is used in the view message selection functions (for instance View::nextMessageItem()).
QVector< Akonadi::MessageStatus > currentFilterStatus() const
Returns the Akonadi::MessageStatus in the current quicksearch field.
Definition: pane.cpp:978
QString asprintf(const char *cformat,...)
virtual void clear()
void setFocus()
Akonadi::Item::List selectionAsMessageItemList(bool includeCollapsedChildren=true) const
Returns the currently selected Items (bound to current StorageModel).
Definition: pane.cpp:917
QObject * parent() const const
const QAbstractItemModel * model() const const
void deletePersistentSet(MessageList::Core::MessageItemSetReference ref)
Deletes the persistent set pointed by the specified reference.
Definition: pane.cpp:962
Akonadi::Item currentItem() const
Returns the current message for the list as Akonadi::Item.
Definition: pane.cpp:886
void tabCloseRequested(int index)
virtual bool event(QEvent *ev) override
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue May 17 2022 04:00:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.