]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kfileitemlistwidget.cpp
b4e0895f2a7fcb0548e8393f63d9dd3832b28fb6
[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) 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](const QDateTime &time) {
59 if (ContentDisplaySettings::useShortRelativeDates()) {
60 return formatter.formatRelativeDateTime(time, QLocale::ShortFormat);
61 } else {
62 return local.toString(time, QLocale::ShortFormat);
63 }
64 };
65
66 if (role == "size") {
67 if (values.value("isDir").toBool()) {
68 if (!roleValue.isNull() && roleValue != -1) {
69 // The item represents a directory.
70 if (ContentDisplaySettings::directorySizeMode() == ContentDisplaySettings::EnumDirectorySizeMode::ContentCount
71 || roleValue == -2 /* size is invalid */) {
72 // Show the number of sub directories instead of the file size of the directory.
73 const int count = values.value("count").toInt();
74 text = i18ncp("@item:intable", "%1 item", "%1 items", count);
75 } else {
76 // if we have directory size available
77 const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
78 text = formatter.formatByteSize(size);
79 }
80 }
81 } else {
82 const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
83 text = formatter.formatByteSize(size);
84 }
85 } else if (role == "modificationtime" || role == "creationtime" || role == "accesstime") {
86 bool ok;
87 const long long time = roleValue.toLongLong(&ok);
88 if (ok && time != -1) {
89 const QDateTime dateTime = QDateTime::fromSecsSinceEpoch(time);
90 text = formatDate(dateTime);
91 }
92 } else if (role == "deletiontime" || role == "imageDateTime") {
93 const QDateTime dateTime = roleValue.toDateTime();
94 if (dateTime.isValid()) {
95 text = formatDate(dateTime);
96 }
97 } else if (role == "dimensions") {
98 const auto dimensions = roleValue.toSize();
99 if (dimensions.isValid()) {
100 text = i18nc("width × height", "%1 × %2", dimensions.width(), dimensions.height());
101 }
102 } else if (role == "permissions") {
103 const auto permissions = roleValue.value<QVariantList>();
104
105 switch (ContentDisplaySettings::usePermissionsFormat()) {
106 case ContentDisplaySettings::EnumUsePermissionsFormat::SymbolicFormat:
107 text = permissions.at(0).toString();
108 break;
109 case ContentDisplaySettings::EnumUsePermissionsFormat::NumericFormat:
110 text = QString::number(permissions.at(1).toInt(), 8);
111 break;
112 case ContentDisplaySettings::EnumUsePermissionsFormat::CombinedFormat:
113 text = QLatin1String("%1 (%2)").arg(permissions.at(0).toString()).arg(permissions.at(1).toInt(), 0, 8);
114 break;
115 }
116 } else {
117 text = KStandardItemListWidgetInformant::roleText(role, values);
118 }
119
120 return text;
121 }
122
123 QFont KFileItemListWidgetInformant::customizedFontForLinks(const QFont &baseFont) const
124 {
125 // The customized font should be italic if the file is a symbolic link.
126 QFont font(baseFont);
127 font.setItalic(true);
128 return font;
129 }
130
131 KFileItemListWidget::KFileItemListWidget(KItemListWidgetInformant *informant, QGraphicsItem *parent)
132 : KStandardItemListWidget(informant, parent)
133 {
134 }
135
136 KFileItemListWidget::~KFileItemListWidget()
137 {
138 }
139
140 KItemListWidgetInformant *KFileItemListWidget::createInformant()
141 {
142 return new KFileItemListWidgetInformant();
143 }
144
145 bool KFileItemListWidget::isRoleRightAligned(const QByteArray &role) const
146 {
147 return role == "size" || role == "permissions";
148 }
149
150 bool KFileItemListWidget::isHidden() const
151 {
152 return data().value("isHidden").toBool();
153 }
154
155 QFont KFileItemListWidget::customizedFont(const QFont &baseFont) const
156 {
157 // The customized font should be italic if the file is a symbolic link.
158 QFont font(baseFont);
159 font.setItalic(data().value("isLink").toBool());
160 return font;
161 }
162
163 int KFileItemListWidget::selectionLength(const QString &text) const
164 {
165 // If item is a directory, use the whole text length for
166 // selection (ignore all points)
167 if (data().value("isDir").toBool()) {
168 return numberOfUnicodeCharactersIn(text);
169 }
170
171 int indexOfExtension = text.length();
172
173 QMimeDatabase db;
174 const QString extension = db.suffixForFileName(text);
175 if (extension.isEmpty()) {
176 // For an unknown extension just exclude the extension after
177 // the last point. This does not work for multiple extensions like
178 // *.tar.gz but usually this is anyhow a known extension.
179 indexOfExtension = text.lastIndexOf(QLatin1Char('.'));
180
181 // If no point could be found, use whole text length for selection.
182 if (indexOfExtension < 1) {
183 indexOfExtension = text.length();
184 }
185
186 } else {
187 indexOfExtension -= extension.length() + 1;
188 }
189
190 return numberOfUnicodeCharactersIn(text.left(indexOfExtension));
191 }
192
193 void KFileItemListWidget::hoverSequenceStarted()
194 {
195 KFileItemListView *view = listView();
196
197 if (!view) {
198 return;
199 }
200
201 const QUrl itemUrl = data().value("url").toUrl();
202
203 view->setHoverSequenceState(itemUrl, 0);
204 }
205
206 void KFileItemListWidget::forceUpdate()
207 {
208 updateAdditionalInfoTextColor();
209 // icon layout does not include the icons in the item selection rectangle
210 // so its icon does not need updating
211 if (listView()->itemLayout() != KStandardItemListView::ItemLayout::IconsLayout) {
212 invalidateIconCache();
213 }
214 update();
215 }
216
217 void KFileItemListWidget::hoverSequenceIndexChanged(int sequenceIndex)
218 {
219 KFileItemListView *view = listView();
220
221 if (!view) {
222 return;
223 }
224
225 const QUrl itemUrl = data().value("url").toUrl();
226
227 view->setHoverSequenceState(itemUrl, sequenceIndex);
228
229 // Force-update the displayed icon
230 invalidateIconCache();
231 update();
232 }
233
234 void KFileItemListWidget::hoverSequenceEnded()
235 {
236 KFileItemListView *view = listView();
237
238 if (!view) {
239 return;
240 }
241
242 view->setHoverSequenceState(QUrl(), 0);
243 }
244
245 KFileItemListView *KFileItemListWidget::listView()
246 {
247 return dynamic_cast<KFileItemListView *>(parentItem());
248 }
249
250 #include "moc_kfileitemlistwidget.cpp"