Mailcommon

favoritecollectionwidget.cpp
1/*
2
3 SPDX-FileCopyrightText: 2012-2025 Laurent Montel <montel@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "favoritecollectionwidget.h"
9#include "kernel/mailkernel.h"
10#include "mailcommonsettings_base.h"
11
12#include <MessageCore/MessageCoreSettings>
13
14#include <Akonadi/CollectionStatisticsDelegate>
15#include <KActionCollection>
16#include <KActionMenu>
17#include <KLocalizedString>
18#include <KXMLGUIClient>
19
20#include <QActionGroup>
21#include <QApplication>
22#include <QFontDatabase>
23#include <QMimeData>
24#include <QMouseEvent>
25#include <QPainter>
26
27using namespace MailCommon;
28
29class Q_DECL_HIDDEN FavoriteCollectionWidget::FavoriteCollectionWidgetPrivate
30{
31public:
32 FavoriteCollectionWidgetPrivate() = default;
33
34 QColor textColor;
35 QAction *listMode = nullptr;
36 QAction *iconMode = nullptr;
37 MailCommonSettings *settings = nullptr;
38 Akonadi::CollectionStatisticsDelegate *delegate = nullptr;
39};
40
41FavoriteCollectionWidget::FavoriteCollectionWidget(MailCommon::MailCommonSettings *settings, KXMLGUIClient *xmlGuiClient, QWidget *parent)
42 : Akonadi::EntityListView(xmlGuiClient, parent)
43 , d(new FavoriteCollectionWidgetPrivate)
44{
45 d->settings = settings;
46 setFocusPolicy(Qt::NoFocus);
47
48 d->delegate = new Akonadi::CollectionStatisticsDelegate(this);
49 d->delegate->setProgressAnimationEnabled(true);
50
51 setItemDelegate(d->delegate);
52
53 d->delegate->setUnreadCountShown(true);
54
55 readConfig();
56
57 createMenu(xmlGuiClient->actionCollection());
58 setResizeMode(QListView::Adjust);
59}
60
61FavoriteCollectionWidget::~FavoriteCollectionWidget() = default;
62
63void FavoriteCollectionWidget::updatePalette()
64{
65 d->delegate->updatePalette();
66}
67
68void FavoriteCollectionWidget::mousePressEvent(QMouseEvent *e)
69{
70 const bool buttonPressedIsMiddle = (e->button() == Qt::MiddleButton);
71 Q_EMIT newTabRequested(buttonPressedIsMiddle);
73}
74
75void FavoriteCollectionWidget::updateMode()
76{
77 switch (viewMode()) {
78 case ListMode:
79 d->listMode->setChecked(true);
80 d->iconMode->setChecked(false);
81 break;
82 case IconMode:
83 d->listMode->setChecked(false);
84 d->iconMode->setChecked(true);
85 break;
86 }
87}
88
89void FavoriteCollectionWidget::createMenu(KActionCollection *ac)
90{
91 auto iconSizeMenu = new KActionMenu(i18n("Icon size"), this);
92 ac->addAction(QStringLiteral("favorite_icon_size"), iconSizeMenu);
93
94 static const int icon_sizes[] = {16, 22, 32 /*, 48, 64, 128 */};
95
96 auto grp = new QActionGroup(iconSizeMenu);
97 QAction *act = nullptr;
98 for (int i : icon_sizes) {
99 act = new QAction(QStringLiteral("%1x%2").arg(i).arg(i), iconSizeMenu);
100 iconSizeMenu->addAction(act);
101 act->setCheckable(true);
102 grp->addAction(act);
103 if (iconSize().width() == i) {
104 act->setChecked(true);
105 }
106 act->setData(QVariant(i));
107 connect(act, &QAction::triggered, this, &FavoriteCollectionWidget::slotChangeIconSize);
108 }
109
110 auto modeFavoriteMenu = new KActionMenu(i18n("Mode"), this);
111 ac->addAction(QStringLiteral("favorite_mode"), modeFavoriteMenu);
112
113 grp = new QActionGroup(modeFavoriteMenu);
114 d->listMode = new QAction(i18nc("@action", "List Mode"), modeFavoriteMenu);
115 modeFavoriteMenu->addAction(d->listMode);
116 d->listMode->setCheckable(true);
117 grp->addAction(d->listMode);
118 if (viewMode() == ListMode) {
119 d->listMode->setChecked(true);
120 }
121 d->listMode->setData(QVariant(MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::ListMode));
122 connect(d->listMode, &QAction::triggered, this, &FavoriteCollectionWidget::slotChangeMode);
123
124 d->iconMode = new QAction(i18nc("@action", "Icon Mode"), modeFavoriteMenu);
125 modeFavoriteMenu->addAction(d->iconMode);
126 grp->addAction(d->iconMode);
127 d->iconMode->setCheckable(true);
128 if (viewMode() == IconMode) {
129 d->iconMode->setChecked(true);
130 }
131 d->iconMode->setData(QVariant(MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::IconMode));
132 connect(d->iconMode, &QAction::triggered, this, &FavoriteCollectionWidget::slotChangeMode);
133}
134
135void FavoriteCollectionWidget::slotChangeMode(bool)
136{
137 auto act = qobject_cast<QAction *>(sender());
138 if (!act) {
139 return;
140 }
141
142 QVariant data = act->data();
143
144 bool ok;
145 const int mode = data.toInt(&ok);
146 if (!ok) {
147 return;
148 }
149
150 switch (mode) {
151 case MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::IconMode:
152 changeViewMode(IconMode);
153 break;
154 case MailCommon::MailCommonSettings::EnumFavoriteCollectionViewMode::ListMode:
155 changeViewMode(ListMode);
156 break;
157 }
158
159 d->settings->setFavoriteCollectionViewMode(mode);
160 d->settings->save();
161}
162
163void FavoriteCollectionWidget::changeViewMode(QListView::ViewMode mode)
164{
165 setViewMode(mode);
166 setDragEnabled(true);
167 setAcceptDrops(true);
168}
169
170void FavoriteCollectionWidget::slotChangeIconSize(bool)
171{
172 auto act = qobject_cast<QAction *>(sender());
173 if (!act) {
174 return;
175 }
176
177 QVariant data = act->data();
178
179 bool ok;
180 const int size = data.toInt(&ok);
181 if (!ok) {
182 return;
183 }
184
185 const QSize newIconSize(QSize(size, size));
186 if (newIconSize == iconSize()) {
187 return;
188 }
189 setIconSize(newIconSize);
190 d->settings->setIconSize(iconSize().width());
191 d->settings->save();
192}
193
194void FavoriteCollectionWidget::slotGeneralPaletteChanged()
195{
196 const QPalette palette = viewport()->palette();
197 QColor color = palette.text().color();
198 color.setAlpha(128);
199 d->textColor = color;
200}
201
202void FavoriteCollectionWidget::slotGeneralFontChanged()
203{
204 // Custom/System font support
205 if (MessageCore::MessageCoreSettings::self()->useDefaultFonts()) {
207 }
208}
209
210void FavoriteCollectionWidget::readConfig()
211{
213
214 int iIconSize = d->settings->iconSize();
215 if (iIconSize < 16 || iIconSize > 32) {
216 iIconSize = 22;
217 }
218 setIconSize(QSize(iIconSize, iIconSize));
219}
220
221void FavoriteCollectionWidget::paintEvent(QPaintEvent *event)
222{
223 if (!model() || model()->rowCount() == 0) {
224 QPainter p(viewport());
225
226 QFont font = p.font();
227 font.setItalic(true);
228 p.setFont(font);
229
230 if (!d->textColor.isValid()) {
231 slotGeneralPaletteChanged();
232 }
233 p.setPen(d->textColor);
234
235 p.drawText(QRect(0, 0, width(), height()), Qt::AlignCenter, i18n("Drop your favorite folders here…"));
236 } else {
238 }
239}
240
241static bool isCollection(const QMimeData *mimeData)
242{
243 const QList<QUrl> urls = mimeData->urls();
244 for (const QUrl &url : urls) {
245 const Akonadi::Collection collection = Akonadi::Collection::fromUrl(url);
246 if (collection.isValid()) {
247 return true;
248 }
249 }
250 return false;
251}
252
253bool FavoriteCollectionWidget::acceptEvent(QDropEvent *event) const
254{
255 const bool draggingCollection = isCollection(event->mimeData());
256 const bool droppingOnCollection = dropIndicatorPosition() == QAbstractItemView::OnItem;
257 if (event->source() == this) {
258 if (draggingCollection && !droppingOnCollection) { // Re-ordering favorites
259 return true;
260 }
261 } else {
262 if ((draggingCollection && !droppingOnCollection) // Adding a new favorite collection
263 || (!draggingCollection && droppingOnCollection)) { // Dropping emails onto a favorite collection
264 return true;
265 }
266 }
267 event->ignore();
268 return false;
269}
270
271void FavoriteCollectionWidget::dragEnterEvent(QDragEnterEvent *event)
272{
273 if (event->source() == this) {
274 QListView::dragEnterEvent(event); // Re-ordering favourites
275 } else {
276 Akonadi::EntityListView::dragEnterEvent(event); // Dropping emails onto a favorite collection
277 }
278}
279
280void FavoriteCollectionWidget::dragMoveEvent(QDragMoveEvent *event)
281{
282 // We need to ask QListView to update dropIndicatorPosition() first...
284 if (event->source() == this) {
285 if (acceptEvent(event)) {
286 event->setDropAction(Qt::MoveAction);
287 event->accept(); // Re-ordering favourites
288 }
289 } else {
290 if (acceptEvent(event)) {
291 Akonadi::EntityListView::dragMoveEvent(event); // Dropping emails onto a favorite collection
292 }
293 }
294}
295
296void FavoriteCollectionWidget::dropEvent(QDropEvent *event)
297{
298 if (event->source() == this) {
299 if (acceptEvent(event)) {
300 QListView::dropEvent(event); // Re-ordering favourites
301 }
302 } else {
303 if (acceptEvent(event)) {
305 Akonadi::EntityListView::dropEvent(event); // Dropping emails onto a favorite collection
306 } else {
307 QListView::dropEvent(event); // Add new favorite
308 }
309 }
310 }
311}
312
313void FavoriteCollectionWidget::startDrag(Qt::DropActions supportedActions)
314{
315 // skip EntityListView logic (we want to reorder favorites, not trigger moving/copying of actual folders)
316 QListView::startDrag(supportedActions);
317}
318
319bool FavoriteCollectionWidget::event(QEvent *e)
320{
322 updatePalette();
323 }
325}
326
327#include "moc_favoritecollectionwidget.cpp"
bool isValid() const
static Collection fromUrl(const QUrl &url)
QAction * addAction(const QString &name, const QObject *receiver=nullptr, const char *member=nullptr)
virtual KActionCollection * actionCollection() const
The FavoriteCollectionWidget class.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KActionMenu * createMenu(KColorSchemeManager *manager, QObject *parent=nullptr)
The filter dialog.
void setDragEnabled(bool enable)
virtual void dragEnterEvent(QDragEnterEvent *event) override
virtual void dragMoveEvent(QDragMoveEvent *event) override
virtual void dropEvent(QDropEvent *event) override
DropIndicatorPosition dropIndicatorPosition() const const
QAbstractItemModel * model() const const
virtual void mousePressEvent(QMouseEvent *event) override
virtual void paintEvent(QPaintEvent *event) override
QWidget * viewport() const const
void setCheckable(bool)
void setChecked(bool)
QVariant data() const const
void setData(const QVariant &data)
void triggered(bool checked)
void setAlpha(int alpha)
ApplicationPaletteChange
Type type() const const
QFont systemFont(SystemFont type)
virtual void dragMoveEvent(QDragMoveEvent *e) override
virtual void dropEvent(QDropEvent *event) override
virtual void startDrag(Qt::DropActions supportedActions) override
QList< QUrl > urls() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
T qobject_cast(QObject *object)
QObject * sender() const const
Qt::MouseButton button() const const
AlignCenter
MoveAction
MiddleButton
int toInt(bool *ok) const const
void setAcceptDrops(bool on)
void setFont(const QFont &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 28 2025 11:51:59 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.