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/KMime/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;
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) {
1231  w->populateStatusFilterCombo();
1232  }
1233  }
1234 }
1235 
1236 #include "moc_pane.cpp"
void customContextMenuRequested(const QPoint &pos)
bool isRightToLeft()
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...
bool focusPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop)
Focuses the previous message item in the view without actually selecting it.
bool sync() override
void triggered(bool checked)
MouseButtonPress
QEvent::Type type() const const
bool selectPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, bool centerItem, bool loop)
Selects the previous message item in the view.
QString asprintf(const char *cformat,...)
void messageActivated(const Akonadi::Item &item)
Emitted when a message is doubleclicked or activated by other input means.
void setMovable(bool movable)
void selectAll()
Selects all the items in the current folder.
void tabCloseRequested(int index)
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
void setAllThreadsExpanded(bool expand)
If expand is true then it expands all the threads, otherwise collapses them.
int indexOf(const T &value, int from) const const
void setCornerWidget(QWidget *widget, Qt::Corner corner)
QObject * sender() const const
bool selectionEmpty() const
Fast function that determines if the selection is empty.
Definition: pane.cpp:1014
QWidget * currentWidget() const const
void setIcon(const QIcon &icon)
void setDocumentMode(bool set)
void setCurrentThreadExpanded(bool expand)
If expand is true then it expands the current thread, otherwise collapses it.
The Akonadi specific implementation of the Core::Widget.
Definition: widget.h:32
void selectionChanged()
Emitted when the selection in the view changes.
void deletePersistentSet(MessageList::Core::MessageItemSetReference ref)
Deletes the persistent set pointed by the specified reference.
Definition: pane.cpp:962
MiddleButton
TopLeftCorner
void setCurrentWidget(QWidget *widget)
View * view() const
Returns the View attached to this Widget.
Definition: widgetbase.cpp:387
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
MessageList::Core::MessageItemSetReference selectionAsPersistentSet(bool includeCollapsedChildren=true) const
Return a persistent set from current selection.
Definition: pane.cpp:1036
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...
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
int indexOf(QWidget *w) const const
void setTabsClosable(bool closeable)
void selectFocusedMessageItem(bool centerItem)
Selects the currently focused message item.
Definition: pane.cpp:376
void tabBarDoubleClicked(int index)
void chop(int n)
int count() const const
QAction * addAction(const QString &text)
CustomContextMenu
bool selectLastMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem)
Selects the last message item in the view that matches the specified Core::MessageTypeFilter.
Pane(bool restoreSession, QAbstractItemModel *model, QItemSelectionModel *selectionModel, QWidget *parent=nullptr)
Create a Pane wrapping the specified model and selection.
Definition: pane.cpp:93
const QList< QKeySequence > & tabPrev()
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
void setTabText(int index, const QString &label)
void reloadGlobalConfiguration()
Reloads global configuration and eventually reloads all the views.
Definition: pane.cpp:1065
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
int currentIndex() const const
void focusView()
Sets the focus on the view of the currently active tab.
Definition: pane.cpp:1054
void append(const T &value)
void installEventFilter(QObject *filterObj)
bool isThreaded() const
Returns true if the current Aggregation is threaded, false otherwise (or if there is no current Aggre...
Definition: pane.cpp:1005
QStringList filter(QStringView str, Qt::CaseSensitivity cs) const const
Akonadi::Item::List selectionAsMessageItemList(bool includeCollapsedChildren=true) const
Returns the currently selected Items (bound to current StorageModel).
Definition: pane.cpp:917
bool selectNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour, bool centerItem, bool loop)
Selects the next message item in the view.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool exists() const
void setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
Sets the XML GUI client which the view is used in.
void setFocus()
const QItemSelection selection() const const
bool isEmpty() const const
void currentChanged(int index)
DisplayRole
void setCurrentThreadExpanded(bool expand)
If expand is true then it expands the current thread, otherwise collapses it.
Definition: pane.cpp:432
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
bool isEmpty() const const
void clicked(bool checked)
QModelIndexList selectedRows(int column) const const
bool selectFirstMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem)
Selects the first message item in the view that matches the specified Core::MessageTypeFilter.
int addTab(QWidget *page, const QString &label)
PreSelectionMode
Pre-selection is the action of automatically selecting a message just after the folder has finished l...
QPoint pos() const const
void selectFocusedMessageItem(bool centerItem)
Selects the currently focused message item.
virtual bool eventFilter(QObject *watched, QEvent *event)
KMime::Message::Ptr currentMessage() const
Returns the current message for the list as KMime::Message::Ptr.
Definition: pane.cpp:897
T & first()
void statusMessage(const QString &message)
Notify the outside when updating the status bar with a message could be useful.
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
QAction * exec()
void setAllGroupsExpanded(bool expand)
If expand is true then it expands all the groups (only the toplevel group item: inner threads are NOT...
void setAllThreadsExpanded(bool expand)
If expand is true then it expands all the threads, otherwise collapses them.
Definition: pane.cpp:445
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
QWidget * widget(int index) const const
Akonadi::Item currentItem() const
Returns the current message for the list as Akonadi::Item.
Definition: pane.cpp:886
MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const
Return a persistent set from current thread.
Definition: pane.cpp:1045
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 setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void messageActivated(const Akonadi::Item &item)
Emitted when a message is doubleclicked or activated by other input means.
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
QString currentFilterSearchString() const
Returns the search term in the current quicksearch field.
Definition: pane.cpp:996
QString i18n(const char *text, const TYPE &arg...)
QVector< KMime::Message::Ptr > selectionAsMessageList(bool includeCollapsedChildren=true) const
Returns the currently selected KMime::Message::Ptr (bound to current StorageModel).
Definition: pane.cpp:908
QItemSelectionModel * createNewTab()
Add a new tab to the Pane and select it.
Definition: pane.cpp:789
const QList< QKeySequence > & tabNext()
MessageTypeFilter
This enum is used in the view message selection functions (for instance View::nextMessageItem()).
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
virtual void clear()
const QAbstractItemModel * model() const const
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
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
The Akonadi specific implementation of the Core::StorageModel.
Definition: storagemodel.h:35
void statusMessage(const QString &message)
Notify the outside when updating the status bar with a message could be useful.
int tabAt(const QPoint &position) const const
QString fromLatin1(const char *str, int size)
QVector< qlonglong > selectionAsMessageItemListId(bool includeCollapsedChildren=true) const
Returns the currently selected Items id(bound to current StorageModel).
Definition: pane.cpp:935
bool focusNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop)
Focuses the next message item in the view without actually selecting it.
QIcon fromTheme(const QString &name)
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
This is the main MessageList panel for Akonadi applications.
Definition: pane.h:45
void show()
QString toolTip() const const
QVector< Akonadi::MessageStatus > currentFilterStatus() const
Returns the Akonadi::MessageStatus in the current quicksearch field.
Definition: pane.cpp:978
QTabBar * tabBar() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
QObject * parent() const const
Akonadi::Item::List itemListFromPersistentSet(MessageList::Core::MessageItemSetReference ref)
Return Akonadi::Item from messageItemReference.
Definition: pane.cpp:953
void setXmlGuiClient(KXMLGUIClient *xmlGuiClient)
Sets the XML GUI client which the pane is used in.
Definition: pane.cpp:195
QChar * data()
QItemSelectionModel * currentItemSelectionModel()
Returns the QItemSelectionModel for the currently displayed tab.
Definition: pane.cpp:1070
void messageStatusChangeRequest(const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear)
Emitted when a message wants its status to be changed.
T readEntry(const QString &key, const T &aDefault) const
const QAbstractItemModel * model() const const
virtual bool event(QEvent *ev) override
void selectAll()
Selects all the items in the current folder.
Definition: pane.cpp:419
void focusQuickSearch(const QString &selectedText)
Sets the focus on the quick search line of the currently active tab.
ExistingSelectionBehaviour
This enum is used in the view message selection functions (for instance View::selectNextMessage()) ...
Q_EMITQ_EMIT
void selectionChanged()
Emitted when the selection in the view changes.
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
void setTabIcon(int index, const QIcon &icon)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Dec 5 2021 23:04:54 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.