]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kfileitemlistwidget.cpp
KItemListSmoothScroller: stop animation on property or targetobject change
[dolphin.git] / src / kitemviews / kfileitemlistwidget.cpp
1 /*
2 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "kfileitemlistwidget.h"
8 #include "kfileitemlistview.h"
9 #include "kfileitemmodel.h"
10 #include "kitemlistview.h"
11
12 #include "dolphin_contentdisplaysettings.h"
13
14 #include <KFormat>
15 #include <KLocalizedString>
16
17 #include <QGraphicsScene>
18 #include <QGraphicsView>
19 #include <QMimeDatabase>
20
21 KFileItemListWidgetInformant::KFileItemListWidgetInformant()
22 : KStandardItemListWidgetInformant()
23 {
24 }
25
26 KFileItemListWidgetInformant::~KFileItemListWidgetInformant()
27 {
28 }
29
30 QString KFileItemListWidgetInformant::itemText(int index, const KItemListView *view) const
31 {
32 Q_ASSERT(qobject_cast<KFileItemModel *>(view->model()));
33 KFileItemModel *fileItemModel = static_cast<KFileItemModel *>(view->model());
34
35 const KFileItem item = fileItemModel->fileItem(index);
36 return item.text();
37 }
38
39 bool KFileItemListWidgetInformant::itemIsLink(int index, const KItemListView *view) const
40 {
41 Q_ASSERT(qobject_cast<KFileItemModel *>(view->model()));
42 KFileItemModel *fileItemModel = static_cast<KFileItemModel *>(view->model());
43
44 const KFileItem item = fileItemModel->fileItem(index);
45 return item.isLink();
46 }
47
48 QString KFileItemListWidgetInformant::roleText(const QByteArray &role, const QHash<QByteArray, QVariant> &values, ForUsageAs forUsageAs) const
49 {
50 QString text;
51 const QVariant roleValue = values.value(role);
52 QLocale local;
53 KFormat formatter(local);
54
55 // Implementation note: In case if more roles require a custom handling
56 // use a hash + switch for a linear runtime.
57
58 auto formatDate = [formatter, local, forUsageAs](const QDateTime &time) {
59 if (ContentDisplaySettings::useShortRelativeDates()) {
60 return formatter.formatRelativeDateTime(time,
61 forUsageAs == KStandardItemListWidgetInformant::ForUsageAs::DisplayedText ? QLocale::ShortFormat
62 : QLocale::LongFormat);
63 } else {
64 return local.toString(time, forUsageAs == KStandardItemListWidgetInformant::ForUsageAs::DisplayedText ? QLocale::ShortFormat : QLocale::LongFormat);
65 }
66 };
67
68 if (role == "size") {
69 if (values.value("isDir").toBool()) {
70 if (!roleValue.isNull() && roleValue != -1) {
71 // The item represents a directory.
72 if (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount
73 || roleValue == -2 /* size is invalid */) {
74 // Show the number of sub directories instead of the file size of the directory.
75 const int count = values.value("count").toInt();
76 text = i18ncp("@item:intable", "%1 item", "%1 items", count);
77 } else {
78 // if we have directory size available
79 const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
80 text = formatter.formatByteSize(size);
81 }
82 }
83 } else {
84 const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
85 text = formatter.formatByteSize(size);
86 }
87 } else if (role == "modificationtime" || role == "creationtime" || role == "accesstime") {
88 bool ok;
89 const long long time = roleValue.toLongLong(&ok);
90 if (ok && time != -1) {
91 const QDateTime dateTime = QDateTime::fromSecsSinceEpoch(time);
92 text = formatDate(dateTime);
93 }
94 } else if (role == "deletiontime" || role == "imageDateTime") {
95 const QDateTime dateTime = roleValue.toDateTime();
96 if (dateTime.isValid()) {
97 text = formatDate(dateTime);
98 }
99 } else if (role == "dimensions") {
100 const auto dimensions = roleValue.toSize();
101 if (dimensions.isValid()) {
102 text = i18nc("width × height", "%1 × %2", dimensions.width(), dimensions.height());
103 }
104 } else if (role == "permissions") {
105 const auto permissions = roleValue.value<QVariantList>();
106
107 switch (ContentDisplaySettings::usePermissionsFormat()) {
108 case ContentDisplaySettings::EnumUsePermissionsFormat::SymbolicFormat:
109 text = permissions.at(0).toString();
110 break;
111 case ContentDisplaySettings::EnumUsePermissionsFormat::NumericFormat:
112 text = QString::number(permissions.at(1).toInt(), 8);
113 break;
114 case ContentDisplaySettings::EnumUsePermissionsFormat::CombinedFormat:
115 text = QLatin1String("%1 (%2)").arg(permissions.at(0).toString()).arg(permissions.at(1).toInt(), 0, 8);
116 break;
117 }
118 } else {
119 text = KStandardItemListWidgetInformant::roleText(role, values, forUsageAs);
120 }
121
122 return text;
123 }
124
125 QFont KFileItemListWidgetInformant::customizedFontForLinks(const QFont &baseFont) const
126 {
127 // The customized font should be italic if the file is a symbolic link.
128 QFont font(baseFont);
129 font.setItalic(true);
130 return font;
131 }
132
133 KFileItemListWidget::KFileItemListWidget(KItemListWidgetInformant *informant, QGraphicsItem *parent)
134 : KStandardItemListWidget(informant, parent)
135 {
136 }
137
138 KFileItemListWidget::~KFileItemListWidget()
139 {
140 }
141
142 KItemListWidgetInformant *KFileItemListWidget::createInformant()
143 {
144 return new KFileItemListWidgetInformant();
145 }
146
147 bool KFileItemListWidget::isRoleRightAligned(const QByteArray &role) const
148 {
149 return role == "size" || role == "permissions";
150 }
151
152 bool KFileItemListWidget::isHidden() const
153 {
154 return data().value("isHidden").toBool();
155 }
156
157 QFont KFileItemListWidget::customizedFont(const QFont &baseFont) const
158 {
159 // The customized font should be italic if the file is a symbolic link.
160 QFont font(baseFont);
161 font.setItalic(data().value("isLink").toBool());
162 return font;
163 }
164
165 int KFileItemListWidget::selectionLength(const QString &text) const
166 {
167 // If item is a directory, use the whole text length for
168 // selection (ignore all points)
169 if (data().value("isDir").toBool()) {
170 return numberOfUnicodeCharactersIn(text);
171 }
172
173 int indexOfExtension = text.length();
174
175 QMimeDatabase db;
176 const QString extension = db.suffixForFileName(text);
177 if (extension.isEmpty()) {
178 // For an unknown extension just exclude the extension after
179 // the last point. This does not work for multiple extensions like
180 // *.tar.gz but usually this is anyhow a known extension.
181 indexOfExtension = text.lastIndexOf(QLatin1Char('.'));
182
183 // If no point could be found, use whole text length for selection.
184 if (indexOfExtension < 1) {
185 indexOfExtension = text.length();
186 }
187
188 } else {
189 indexOfExtension -= extension.length() + 1;
190 }
191
192 return numberOfUnicodeCharactersIn(text.left(indexOfExtension));
193 }
194
195 void KFileItemListWidget::hoverSequenceStarted()
196 {
197 KFileItemListView *view = listView();
198
199 if (!view) {
200 return;
201 }
202
203 const QUrl itemUrl = data().value("url").toUrl();
204
205 view->setHoverSequenceState(itemUrl, 0);
206 }
207
208 void KFileItemListWidget::forceUpdate()
209 {
210 updateAdditionalInfoTextColor();
211 // icon layout does not include the icons in the item selection rectangle
212 // so its icon does not need updating
213 if (listView()->itemLayout() != KStandardItemListView::ItemLayout::IconsLayout) {
214 invalidateIconCache();
215 }
216 update();
217 }
218
219 void KFileItemListWidget::hoverSequenceIndexChanged(int sequenceIndex)
220 {
221 KFileItemListView *view = listView();
222
223 if (!view) {
224 return;
225 }
226
227 const QUrl itemUrl = data().value("url").toUrl();
228
229 view->setHoverSequenceState(itemUrl, sequenceIndex);
230
231 // Force-update the displayed icon
232 invalidateIconCache();
233 update();
234 }
235
236 void KFileItemListWidget::hoverSequenceEnded()
237 {
238 KFileItemListView *view = listView();
239
240 if (!view) {
241 return;
242 }
243
244 view->setHoverSequenceState(QUrl(), 0);
245 }
246
247 KFileItemListView *KFileItemListWidget::listView()
248 {
249 return dynamic_cast<KFileItemListView *>(parentItem());
250 }
251
252 #include "moc_kfileitemlistwidget.cpp"