Messagelib

pane.h
1/*
2 SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#pragma once
8
9#include "messagelist/enums.h"
10#include "messagelist/view.h"
11#include <QHash>
12#include <QList>
13#include <QTabWidget>
14
15#include "messagelist_export.h"
16#include <Akonadi/Collection>
17#include <Akonadi/Item>
18#include <KMime/KMimeMessage>
19
20class KXMLGUIClient;
23class QItemSelection;
24
25namespace KPIM
26{
27class MessageStatus;
28}
29
30namespace MessageList
31{
32class Widget;
33class StorageModel;
34
35/**
36 * This is the main MessageList panel for Akonadi applications.
37 * It contains multiple MessageList::Widget tabs
38 * so it can actually display multiple folder sets at once.
39 *
40 * When a KXmlGuiWindow is passed to setXmlGuiClient, the XMLGUI
41 * defined context menu @c akonadi_messagelist_contextmenu is
42 * used if available.
43 *
44 */
45class MESSAGELIST_EXPORT Pane : public QTabWidget
46{
47 Q_OBJECT
48
49public:
50 /**
51 * Create a Pane wrapping the specified model and selection.
52 */
53 explicit Pane(bool restoreSession, QAbstractItemModel *model, QItemSelectionModel *selectionModel, QWidget *parent = nullptr);
54 ~Pane() override;
55
56 virtual MessageList::StorageModel *createStorageModel(QAbstractItemModel *model, QItemSelectionModel *selectionModel, QObject *parent);
57
58 virtual void writeConfig(bool restoreSession);
59
60 /**
61 * Sets the XML GUI client which the pane is used in.
62 *
63 * This is needed if you want to use the built-in context menu.
64 * Passing 0 is ok and will disable the builtin context menu.
65 *
66 * @param xmlGuiClient The KXMLGUIClient the view is used in.
67 */
68 void setXmlGuiClient(KXMLGUIClient *xmlGuiClient);
69
70 /**
71 * Returns the current message for the list as Akonadi::Item.
72 * May return an invalid Item if there is no current message or no current folder.
73 */
74 [[nodiscard]] Akonadi::Item currentItem() const;
75
76 /**
77 * Returns the current message for the list as KMime::Message::Ptr.
78 * May return 0 if there is no current message or no current folder.
79 */
80 KMime::Message::Ptr currentMessage() const;
81
82 /**
83 * Returns the currently selected KMime::Message::Ptr (bound to current StorageModel).
84 * The list may be empty if there are no selected messages or no StorageModel.
85 *
86 * If includeCollapsedChildren is true then the children of the selected but
87 * collapsed items are also added to the list.
88 *
89 * The returned list is guaranteed to be valid only until you return control
90 * to the main even loop. Don't store it for any longer. If you need to reference
91 * this set of messages at a later stage then take a look at createPersistentSet().
92 */
93 [[nodiscard]] QList<KMime::Message::Ptr> selectionAsMessageList(bool includeCollapsedChildren = true) const;
94
95 /**
96 * Returns the currently selected Items (bound to current StorageModel).
97 * The list may be empty if there are no selected messages or no StorageModel.
98 *
99 * If includeCollapsedChildren is true then the children of the selected but
100 * collapsed items are also added to the list.
101 *
102 * The returned list is guaranteed to be valid only until you return control
103 * to the main even loop. Don't store it for any longer. If you need to reference
104 * this set of messages at a later stage then take a look at createPersistentSet().
105 */
106 [[nodiscard]] Akonadi::Item::List selectionAsMessageItemList(bool includeCollapsedChildren = true) const;
107
108 /**
109 * Returns the currently selected Items id(bound to current StorageModel).
110 * The list may be empty if there are no selected messages or no StorageModel.
111 *
112 * If includeCollapsedChildren is true then the children of the selected but
113 * collapsed items are also added to the list.
114 *
115 * The returned list is guaranteed to be valid only until you return control
116 * to the main even loop. Don't store it for any longer. If you need to reference
117 * this set of messages at a later stage then take a look at createPersistentSet().
118 */
119 [[nodiscard]] QList<qlonglong> selectionAsMessageItemListId(bool includeCollapsedChildren = true) const;
120
121 [[nodiscard]] QList<Akonadi::Item::Id> selectionAsListMessageId(bool includeCollapsedChildren = true) const;
122
123 /**
124 * Returns the Akonadi::Item bound to the current StorageModel that
125 * are part of the current thread. The current thread is the thread
126 * that contains currentMessageItem().
127 * The list may be empty if there is no currentMessageItem() or no StorageModel.
128 *
129 * The returned list is guaranteed to be valid only until you return control
130 * to the main even loop. Don't store it for any longer. If you need to reference
131 * this set of messages at a later stage then take a look at createPersistentSet().
132 */
133 [[nodiscard]] Akonadi::Item::List currentThreadAsMessageList() const;
134
135 /**
136 * Selects the next message item in the view.
137 *
138 * messageTypeFilter can be used to restrict the selection to only certain message types.
139 *
140 * existingSelectionBehaviour specifies how the existing selection
141 * is manipulated. It may be cleared, expanded or grown/shrunk.
142 *
143 * If centerItem is true then the specified item will be positioned
144 * at the center of the view, if possible.
145 * If loop is true then the "next" algorithm will restart from the beginning
146 * of the list if the end is reached, otherwise it will just stop returning false.
147 */
148 [[nodiscard]] bool selectNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter,
149 MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour,
150 bool centerItem,
151 bool loop);
152
153 /**
154 * Selects the previous message item in the view.
155 * If centerItem is true then the specified item will be positioned
156 * at the center of the view, if possible.
157 *
158 * messageTypeFilter can be used to restrict the selection to only certain message types.
159 *
160 * existingSelectionBehaviour specifies how the existing selection
161 * is manipulated. It may be cleared, expanded or grown/shrunk.
162 *
163 * If loop is true then the "previous" algorithm will restart from the end
164 * of the list if the beginning is reached, otherwise it will just stop returning false.
165 */
166 [[nodiscard]] bool selectPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter,
167 MessageList::Core::ExistingSelectionBehaviour existingSelectionBehaviour,
168 bool centerItem,
169 bool loop);
170
171 /**
172 * Focuses the next message item in the view without actually selecting it.
173 *
174 * messageTypeFilter can be used to restrict the selection to only certain message types.
175 *
176 * If centerItem is true then the specified item will be positioned
177 * at the center of the view, if possible.
178 * If loop is true then the "next" algorithm will restart from the beginning
179 * of the list if the end is reached, otherwise it will just stop returning false.
180 */
181 [[nodiscard]] bool focusNextMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop);
182
183 /**
184 * Focuses the previous message item in the view without actually selecting it.
185 *
186 * messageTypeFilter can be used to restrict the selection to only certain message types.
187 *
188 * If centerItem is true then the specified item will be positioned
189 * at the center of the view, if possible.
190 * If loop is true then the "previous" algorithm will restart from the end
191 * of the list if the beginning is reached, otherwise it will just stop returning false.
192 */
193 [[nodiscard]] bool focusPreviousMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem, bool loop);
194
195 /**
196 * Selects the currently focused message item. May do nothing if the
197 * focused message item is already selected (which is very likely).
198 * If centerItem is true then the specified item will be positioned
199 * at the center of the view, if possible.
200 */
201 void selectFocusedMessageItem(bool centerItem);
202
203 /**
204 * Selects the first message item in the view that matches the specified Core::MessageTypeFilter.
205 * If centerItem is true then the specified item will be positioned
206 * at the center of the view, if possible.
207 *
208 * If the current view is already loaded then the request will
209 * be satisfied immediately (well... if an unread message exists at all).
210 * If the current view is still loading then the selection of the first
211 * message will be scheduled to be executed when loading terminates.
212 *
213 * So this function doesn't actually guarantee that an unread or new message
214 * was selected when the call returns. Take care :)
215 *
216 * The function returns true if a message was selected and false otherwise.
217 */
218 [[nodiscard]] bool selectFirstMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem);
219
220 /**
221 * Selects the last message item in the view that matches the specified Core::MessageTypeFilter.
222 * If centerItem is true then the specified item will be positioned
223 * at the center of the view, if possible.
224 *
225 * The function returns true if a message was selected and false otherwise.
226 */
227 [[nodiscard]] bool selectLastMessageItem(MessageList::Core::MessageTypeFilter messageTypeFilter, bool centerItem);
228
229 /**
230 * If expand is true then it expands the current thread, otherwise
231 * collapses it.
232 */
233 void setCurrentThreadExpanded(bool expand);
234
235 /**
236 * If expand is true then it expands all the threads, otherwise
237 * collapses them.
238 */
239 void setAllThreadsExpanded(bool expand);
240
241 /**
242 * If expand is true then it expands all the groups (only the toplevel
243 * group item: inner threads are NOT expanded). If expand is false
244 * then it collapses all the groups. If no grouping is in effect
245 * then this function does nothing.
246 */
247 void setAllGroupsExpanded(bool expand);
248
249 /**
250 * Sets the focus on the quick search line of the currently active tab.
251 */
252 void focusQuickSearch(const QString &selectedText = QString());
253
254 /**
255 * Returns the Akonadi::MessageStatus in the current quicksearch field.
256 */
257 [[nodiscard]] QList<Akonadi::MessageStatus> currentFilterStatus() const;
258
259 /**
260 * Returns the search term in the current quicksearch field.
261 */
262 [[nodiscard]] QString currentFilterSearchString() const;
263
264 /**
265 * Returns true if the current Aggregation is threaded, false otherwise
266 * (or if there is no current Aggregation).
267 */
268 [[nodiscard]] bool isThreaded() const;
269
270 /**
271 * Fast function that determines if the selection is empty
272 */
273 [[nodiscard]] bool selectionEmpty() const;
274 /**
275 * Fills the lists of the selected message serial numbers and of the selected+visible ones.
276 * Returns true if the returned stats are valid (there is a current folder after all)
277 * and false otherwise. This is called by KMMainWidget in a single place so we optimize by
278 * making it a single sweep on the selection.
279 *
280 * If includeCollapsedChildren is true then the children of the selected but
281 * collapsed items are also included in the stats
282 */
283 [[nodiscard]] bool getSelectionStats(Akonadi::Item::List &selectedItems,
284 Akonadi::Item::List &selectedVisibleItems,
285 bool *allSelectedBelongToSameThread,
286 bool includeCollapsedChildren = true) const;
287 /**
288 * Deletes the persistent set pointed by the specified reference.
289 * If the set does not exist anymore, nothing happens.
290 */
291 void deletePersistentSet(MessageList::Core::MessageItemSetReference ref);
292
293 /**
294 * If bMark is true this function marks the messages as "about to be removed"
295 * so they appear dimmer and aren't selectable in the view.
296 * If bMark is false then this function clears the "about to be removed" state
297 * for the specified MessageItems.
298 */
299 void markMessageItemsAsAboutToBeRemoved(MessageList::Core::MessageItemSetReference ref, bool bMark);
300
301 /**
302 * Return Akonadi::Item from messageItemReference
303 */
304 [[nodiscard]] Akonadi::Item::List itemListFromPersistentSet(MessageList::Core::MessageItemSetReference ref);
305
306 /**
307 * Return a persistent set from current selection
308 */
309 [[nodiscard]] MessageList::Core::MessageItemSetReference selectionAsPersistentSet(bool includeCollapsedChildren = true) const;
310
311 /**
312 * Return a persistent set from current thread
313 */
314 [[nodiscard]] MessageList::Core::MessageItemSetReference currentThreadAsPersistentSet() const;
315 /**
316 * Sets the focus on the view of the currently active tab.
317 */
318 void focusView();
319
320 /**
321 * Reloads global configuration and eventually reloads all the views.
322 */
323 void reloadGlobalConfiguration();
324
325 /**
326 * Returns the QItemSelectionModel for the currently displayed tab.
327 */
328 QItemSelectionModel *currentItemSelectionModel();
329
330 /**
331 * Sets the current folder to be displayed by this Pane.
332 * If the specified folder is already open in one of the tabs
333 * then that tab is made current (and no reloading happens).
334 * If the specified folder is not open yet then behaviour
335 * depends on the preferEmptyTab value as follows.
336 *
337 * @param etmIndex the index for the collection in the EntityTreeModel (source model)
338 *
339 * If preferEmptyTab is set to false then the (new) folder is loaded
340 * in the current tab. If preferEmptyTab is set to true then the (new) folder is
341 * loaded in the first empty tab (or a new one if there are no empty ones).
342 *
343 * Pre-selection is the action of automatically selecting a message just after the folder
344 * has finished loading. See Model::setStorageModel() for more information.
345 *
346 * If overrideLabel is not empty then it's used as the tab text for the
347 * specified folder. This is useful to signal a particular folder state
348 * like "loading..."
349 */
350 void setCurrentFolder(const Akonadi::Collection &fld,
351 const QModelIndex &etmIndex,
352 bool preferEmptyTab = false,
353 MessageList::Core::PreSelectionMode preSelectionMode = MessageList::Core::PreSelectLastSelected,
354 const QString &overrideLabel = QString());
355
356 void resetModelStorage();
357
358 void setPreferEmptyTab(bool emptyTab);
359
360 void updateTabIconText(const Akonadi::Collection &collection, const QString &label, const QIcon &icon);
361
362 void saveCurrentSelection();
363
364 void updateTagComboBox();
365
366 bool searchEditHasFocus() const;
367
368 void setQuickSearchClickMessage(const QString &msg);
369
370 void populateStatusFilterCombo();
371
372 Core::QuickSearchLine::SearchOptions currentOptions() const;
373
374 [[nodiscard]] Akonadi::Collection currentFolder() const;
375
376public Q_SLOTS:
377 /**
378 * Selects all the items in the current folder.
379 */
380 void selectAll();
381
382 /**
383 * Add a new tab to the Pane and select it.
384 */
385 QItemSelectionModel *createNewTab();
386
387 void sortOrderMenuAboutToShow();
388
389 void aggregationMenuAboutToShow();
390
391 void themeMenuAboutToShow();
392
393Q_SIGNALS:
394 /**
395 * Emitted when a message is selected (that is, single clicked and thus made current in the view)
396 * Note that this message CAN be 0 (when the current item is cleared, for example).
397 *
398 * This signal is emitted when a SINGLE message is selected in the view, probably
399 * by clicking on it or by simple keyboard navigation. When multiple items
400 * are selected at once (by shift+clicking, for example) then you will get
401 * this signal only for the last clicked message (or at all, if the last shift+clicked
402 * thing is a group header...). You should handle selection changed in this case.
403 */
405
406 /**
407 * Emitted when a message is doubleclicked or activated by other input means
408 */
410
411 /**
412 * Emitted when the selection in the view changes.
413 */
415
416 /**
417 * Emitted when a message wants its status to be changed
418 */
420
421 /**
422 * Notify the outside when updating the status bar with a message
423 * could be useful
424 */
425 void statusMessage(const QString &message);
426
427 /**
428 * Emitted when the current tab has changed. Clients using the
429 * selection model from currentItemSelectionModel() should
430 * ask for it again, as it may be different now.
431 */
433
434 void forceLostFocus();
435
436private:
437 MESSAGELIST_NO_EXPORT void restoreHeaderSettings(int index, bool restoreSession);
438 MESSAGELIST_NO_EXPORT void readConfig(bool restoreSession);
439
440 bool eventFilter(QObject *obj, QEvent *event) override;
441
442 class PanePrivate;
443 std::unique_ptr<PanePrivate> const d;
444};
445} // namespace MessageList
This is the main MessageList panel for Akonadi applications.
Definition pane.h:46
void messageActivated(const Akonadi::Item &item)
Emitted when a message is doubleclicked or activated by other input means.
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 selectionChanged()
Emitted when the selection in the view changes.
void currentTabChanged()
Emitted when the current tab has changed.
void statusMessage(const QString &message)
Notify the outside when updating the status bar with a message could be useful.
void messageStatusChangeRequest(const Akonadi::Item &item, const Akonadi::MessageStatus &set, const Akonadi::MessageStatus &clear)
Emitted when a message wants its status to be changed.
The Akonadi specific implementation of the Core::StorageModel.
ExistingSelectionBehaviour
This enum is used in the view message selection functions (for instance View::selectNextMessage())
PreSelectionMode
Pre-selection is the action of automatically selecting a message just after the folder has finished l...
MessageTypeFilter
This enum is used in the view message selection functions (for instance View::nextMessageItem()).
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:37:31 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.