Krita Source Code Documentation
Loading...
Searching...
No Matches
KisRecentDocumentsModelWrapper.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Felipe Lema <felipelema@mortemale.org>
3 * SPDX-FileCopyrightText: 2022 Alvin Wong <alvin@alvinhc.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
9
10#include <QApplication>
11#include <QDir>
12#include <QUrl>
13
14#include "kis_icon_utils.h"
17
18
26class KisRecentDocumentsModelItem : public QStandardItem
27{
28 QUrl m_url;
29 mutable bool m_iconFetched {false};
30 mutable QIcon m_fileIcon;
31 QString m_tooltip;
32
33public:
34 explicit KisRecentDocumentsModelItem(const QUrl &url);
36
37 QVariant data(int role = Qt::UserRole + 1) const override;
38 void setData(const QVariant &value, int role = Qt::UserRole + 1) override;
39};
40
41static QString urlToTooltip(const QUrl &url)
42{
43#ifdef Q_OS_WIN
44 // Convert forward slashes to backslashes
45 if (url.isLocalFile()) {
46 return QDir::toNativeSeparators(url.toLocalFile());
47 }
48#elif defined(Q_OS_ANDROID)
49 return url.toLocalFile();
50#endif
51 return url.toDisplayString(QUrl::PreferLocalFile);
52}
53
55 : QStandardItem(url.fileName())
56 , m_url(url)
57 , m_tooltip(urlToTooltip(url))
58{
59}
60
62
63QVariant KisRecentDocumentsModelItem::data(int role) const
64{
65 switch (role) {
66 case Qt::DecorationRole:
67 if (!m_iconFetched) {
68 m_iconFetched = true;
69 // This lazy-loads the icon if not already cached. Once the real
70 // icon has been loaded, `KisRecentDocumentsModelItem` will be
71 // notified of the icon change and sets it to this item.
73 if (!icon.isNull()) {
74 m_fileIcon = icon;
75 }
76 }
77 if (m_fileIcon.isNull()) {
78 return KisIconUtils::loadIcon("media-floppy");
79 } else {
80 return m_fileIcon;
81 }
82 case Qt::ToolTipRole:
83 return m_tooltip;
84 case Qt::UserRole + 1:
85 return m_url;
86 }
87 return QStandardItem::data(role);
88}
89
90void KisRecentDocumentsModelItem::setData(const QVariant &value, int role)
91{
92 switch (role) {
93 case Qt::DecorationRole:
94 if (value.type() == (QVariant::Type)QMetaType::QIcon) {
95 // `KisRecentDocumentsModelItem` calls `setIcon` to update the
96 // file icon once it has been lazy-loaded or changed.
97 m_iconFetched = true;
98 m_fileIcon = value.value<QIcon>();
99 emitDataChanged();
100 }
101 return;
102 case Qt::ToolTipRole:
103 qWarning() << "KisRecentDocumentsModelItem::setTooltip ignored";
104 return;
105 case Qt::UserRole + 1:
106 qWarning() << "KisRecentDocumentsModelItem::setData ignored";
107 return;
108 }
109 QStandardItem::setData(value, role);
110}
111
112
114{
116 SIGNAL(fileIconChanged(const QUrl &, const QIcon &)),
117 SLOT(slotFileIconChanged(const QUrl &, const QIcon &)));
119 SIGNAL(fileAdded(const QUrl &)),
120 SLOT(fileAdded(const QUrl &)));
122 SIGNAL(fileRemoved(const QUrl &)),
123 SLOT(fileRemoved(const QUrl &)));
125 SIGNAL(listRenewed()),
126 SLOT(listRenewed()));
127
128 // Load the initial recent files list
129 listRenewed();
130}
131
133
135{
136 if (QThread::currentThread() != qApp->thread()) {
137 qWarning() << "KisRecentDocumentsModelWrapper::instance() called from non-GUI thread!";
138 return nullptr;
139 }
140 static KisRecentDocumentsModelWrapper s_instance;
141 return &s_instance;
142}
143
145{
146 // Replace all items in the model. The existing items are deleted by
147 // `QStandardItemModel`.
148 m_filesAndThumbnailsModel.setRowCount(urls.count());
149 for (int i = 0; i < urls.count(); i++) {
150 QStandardItem *item = new KisRecentDocumentsModelItem(urls[i]);
151 m_filesAndThumbnailsModel.setItem(i, item);
152 }
153
154 Q_EMIT sigModelIsUpToDate();
155}
156
157void KisRecentDocumentsModelWrapper::slotFileIconChanged(const QUrl &url, const QIcon &icon)
158{
159 const int count = m_filesAndThumbnailsModel.rowCount();
160 for (int i = 0; i < count; i++) {
161 QStandardItem *item = m_filesAndThumbnailsModel.item(i);
162 if (item && item->data() == url) {
163 item->setIcon(icon);
164 return;
165 }
166 }
167}
168
170{
172 Q_EMIT sigModelIsUpToDate();
173}
174
176{
177 const int count = m_filesAndThumbnailsModel.rowCount();
178 for (int i = 0; i < count; i++) {
179 QStandardItem *item = m_filesAndThumbnailsModel.item(i);
180 if (item && item->data() == url) {
181 m_filesAndThumbnailsModel.removeRow(i);
182 Q_EMIT sigModelIsUpToDate();
183 return;
184 }
185 }
186}
187
192
194{
196}
float value(const T *src, size_t ch)
static QString urlToTooltip(const QUrl &url)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
QVariant data(int role=Qt::UserRole+1) const override
void setData(const QVariant &value, int role=Qt::UserRole+1) override
void slotFileIconChanged(const QUrl &url, const QIcon &icon)
static KisRecentDocumentsModelWrapper * instance()
QIcon getOrQueueFileIcon(const QUrl &url)
static KisRecentFileIconCache * instance()
static KisRecentFilesManager * instance()
QIcon loadIcon(const QString &name)