File indexing completed on 2024-04-28 05:45:03

0001 /*
0002  * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kfileitemlistwidget.h"
0008 #include "kfileitemlistview.h"
0009 #include "kfileitemmodel.h"
0010 #include "kitemlistview.h"
0011 
0012 #include "dolphin_contentdisplaysettings.h"
0013 
0014 #include <KFormat>
0015 #include <KLocalizedString>
0016 
0017 #include <QGraphicsScene>
0018 #include <QGraphicsView>
0019 #include <QMimeDatabase>
0020 
0021 KFileItemListWidgetInformant::KFileItemListWidgetInformant()
0022     : KStandardItemListWidgetInformant()
0023 {
0024 }
0025 
0026 KFileItemListWidgetInformant::~KFileItemListWidgetInformant()
0027 {
0028 }
0029 
0030 QString KFileItemListWidgetInformant::itemText(int index, const KItemListView *view) const
0031 {
0032     Q_ASSERT(qobject_cast<KFileItemModel *>(view->model()));
0033     KFileItemModel *fileItemModel = static_cast<KFileItemModel *>(view->model());
0034 
0035     const KFileItem item = fileItemModel->fileItem(index);
0036     return item.text();
0037 }
0038 
0039 bool KFileItemListWidgetInformant::itemIsLink(int index, const KItemListView *view) const
0040 {
0041     Q_ASSERT(qobject_cast<KFileItemModel *>(view->model()));
0042     KFileItemModel *fileItemModel = static_cast<KFileItemModel *>(view->model());
0043 
0044     const KFileItem item = fileItemModel->fileItem(index);
0045     return item.isLink();
0046 }
0047 
0048 QString KFileItemListWidgetInformant::roleText(const QByteArray &role, const QHash<QByteArray, QVariant> &values) const
0049 {
0050     QString text;
0051     const QVariant roleValue = values.value(role);
0052     QLocale local;
0053     KFormat formatter(local);
0054 
0055     // Implementation note: In case if more roles require a custom handling
0056     // use a hash + switch for a linear runtime.
0057 
0058     auto formatDate = [formatter, local](const QDateTime &time) {
0059         if (ContentDisplaySettings::useShortRelativeDates()) {
0060             return formatter.formatRelativeDateTime(time, QLocale::ShortFormat);
0061         } else {
0062             return local.toString(time, QLocale::ShortFormat);
0063         }
0064     };
0065 
0066     if (role == "size") {
0067         if (values.value("isDir").toBool()) {
0068             if (!roleValue.isNull() && roleValue != -1) {
0069                 // The item represents a directory.
0070                 if (ContentDisplaySettings::directorySizeCount() || roleValue == -2 /* size is invalid */) {
0071                     //  Show the number of sub directories instead of the file size of the directory.
0072                     const int count = values.value("count").toInt();
0073                     text = i18ncp("@item:intable", "%1 item", "%1 items", count);
0074                 } else {
0075                     // if we have directory size available
0076                     const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
0077                     text = formatter.formatByteSize(size);
0078                 }
0079             }
0080         } else {
0081             const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
0082             text = formatter.formatByteSize(size);
0083         }
0084     } else if (role == "modificationtime" || role == "creationtime" || role == "accesstime") {
0085         bool ok;
0086         const long long time = roleValue.toLongLong(&ok);
0087         if (ok && time != -1) {
0088             const QDateTime dateTime = QDateTime::fromSecsSinceEpoch(time);
0089             text = formatDate(dateTime);
0090         }
0091     } else if (role == "deletiontime" || role == "imageDateTime") {
0092         const QDateTime dateTime = roleValue.toDateTime();
0093         if (dateTime.isValid()) {
0094             text = formatDate(dateTime);
0095         }
0096     } else if (role == "dimensions") {
0097         const auto dimensions = roleValue.toSize();
0098         if (dimensions.isValid()) {
0099             text = i18nc("width × height", "%1 × %2", dimensions.width(), dimensions.height());
0100         }
0101     } else if (role == "permissions") {
0102         const auto permissions = roleValue.value<QVariantList>();
0103 
0104         switch (ContentDisplaySettings::usePermissionsFormat()) {
0105         case ContentDisplaySettings::EnumUsePermissionsFormat::SymbolicFormat:
0106             text = permissions.at(0).toString();
0107             break;
0108         case ContentDisplaySettings::EnumUsePermissionsFormat::NumericFormat:
0109             text = QString::number(permissions.at(1).toInt(), 8);
0110             break;
0111         case ContentDisplaySettings::EnumUsePermissionsFormat::CombinedFormat:
0112             text = QLatin1String("%1 (%2)").arg(permissions.at(0).toString()).arg(permissions.at(1).toInt(), 0, 8);
0113             break;
0114         }
0115     } else {
0116         text = KStandardItemListWidgetInformant::roleText(role, values);
0117     }
0118 
0119     return text;
0120 }
0121 
0122 QFont KFileItemListWidgetInformant::customizedFontForLinks(const QFont &baseFont) const
0123 {
0124     // The customized font should be italic if the file is a symbolic link.
0125     QFont font(baseFont);
0126     font.setItalic(true);
0127     return font;
0128 }
0129 
0130 KFileItemListWidget::KFileItemListWidget(KItemListWidgetInformant *informant, QGraphicsItem *parent)
0131     : KStandardItemListWidget(informant, parent)
0132 {
0133 }
0134 
0135 KFileItemListWidget::~KFileItemListWidget()
0136 {
0137 }
0138 
0139 KItemListWidgetInformant *KFileItemListWidget::createInformant()
0140 {
0141     return new KFileItemListWidgetInformant();
0142 }
0143 
0144 bool KFileItemListWidget::isRoleRightAligned(const QByteArray &role) const
0145 {
0146     return role == "size" || role == "permissions";
0147 }
0148 
0149 bool KFileItemListWidget::isHidden() const
0150 {
0151     return data().value("isHidden").toBool();
0152 }
0153 
0154 QFont KFileItemListWidget::customizedFont(const QFont &baseFont) const
0155 {
0156     // The customized font should be italic if the file is a symbolic link.
0157     QFont font(baseFont);
0158     font.setItalic(data().value("isLink").toBool());
0159     return font;
0160 }
0161 
0162 int KFileItemListWidget::selectionLength(const QString &text) const
0163 {
0164     // Select the text without MIME-type extension
0165     int selectionLength = text.length();
0166 
0167     // If item is a directory, use the whole text length for
0168     // selection (ignore all points)
0169     if (data().value("isDir").toBool()) {
0170         return selectionLength;
0171     }
0172 
0173     QMimeDatabase db;
0174     const QString extension = db.suffixForFileName(text);
0175     if (extension.isEmpty()) {
0176         // For an unknown extension just exclude the extension after
0177         // the last point. This does not work for multiple extensions like
0178         // *.tar.gz but usually this is anyhow a known extension.
0179         selectionLength = text.lastIndexOf(QLatin1Char('.'));
0180 
0181         // If no point could be found, use whole text length for selection.
0182         if (selectionLength < 1) {
0183             selectionLength = text.length();
0184         }
0185 
0186     } else {
0187         selectionLength -= extension.length() + 1;
0188     }
0189 
0190     return selectionLength;
0191 }
0192 
0193 void KFileItemListWidget::hoverSequenceStarted()
0194 {
0195     KFileItemListView *view = listView();
0196 
0197     if (!view) {
0198         return;
0199     }
0200 
0201     const QUrl itemUrl = data().value("url").toUrl();
0202 
0203     view->setHoverSequenceState(itemUrl, 0);
0204 }
0205 
0206 void KFileItemListWidget::forceUpdate()
0207 {
0208     updateAdditionalInfoTextColor();
0209     // icon layout does not include the icons in the item selection rectangle
0210     // so its icon does not need updating
0211     if (listView()->itemLayout() != KStandardItemListView::ItemLayout::IconsLayout) {
0212         invalidateIconCache();
0213     }
0214     update();
0215 }
0216 
0217 void KFileItemListWidget::hoverSequenceIndexChanged(int sequenceIndex)
0218 {
0219     KFileItemListView *view = listView();
0220 
0221     if (!view) {
0222         return;
0223     }
0224 
0225     const QUrl itemUrl = data().value("url").toUrl();
0226 
0227     view->setHoverSequenceState(itemUrl, sequenceIndex);
0228 
0229     // Force-update the displayed icon
0230     invalidateIconCache();
0231     update();
0232 }
0233 
0234 void KFileItemListWidget::hoverSequenceEnded()
0235 {
0236     KFileItemListView *view = listView();
0237 
0238     if (!view) {
0239         return;
0240     }
0241 
0242     view->setHoverSequenceState(QUrl(), 0);
0243 }
0244 
0245 KFileItemListView *KFileItemListWidget::listView()
0246 {
0247     return dynamic_cast<KFileItemListView *>(parentItem());
0248 }
0249 
0250 #include "moc_kfileitemlistwidget.cpp"