]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemlistview.cpp
Merge remote-tracking branch 'fork/work/zakharafoniam/useful-groups'
[dolphin.git] / src / kitemviews / kfileitemlistview.cpp
index d249bef91b9e0314c585f08885306b272a43a9e3..d58a1a8baf3ac982d82135f1ed1ba55a2ae41404 100644 (file)
@@ -1,55 +1,47 @@
-/***************************************************************************
- *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
- ***************************************************************************/
+/*
+ * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
 
 #include "kfileitemlistview.h"
 
-#include "kfileitemmodelrolesupdater.h"
 #include "kfileitemlistwidget.h"
 #include "kfileitemmodel.h"
+#include "kfileitemmodelrolesupdater.h"
+#include "private/kitemviewsutils.h"
 #include "private/kpixmapmodifier.h"
 
-#include <QIcon>
 #include <KIconLoader>
 
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QIcon>
+#include <QMimeDatabase>
 #include <QPainter>
 #include <QTimer>
 
 // #define KFILEITEMLISTVIEW_DEBUG
 
-namespace {
-    // If the visible index range changes, KFileItemModelRolesUpdater is not
-    // informed immediatetly, but with a short delay. This ensures that scrolling
-    // always feels smooth and is not interrupted by icon loading (which can be
-    // quite expensive if a disk access is required to determine the final icon).
-    const int ShortInterval = 50;
-
-    // If the icon size changes, a longer delay is used. This prevents that
-    // the expensive re-generation of all previews is triggered repeatedly when
-    // chaning the zoom level.
-    const int LongInterval = 300;
-}
-
-KFileItemListView::KFileItemListView(QGraphicsWidget* parent) :
-    KStandardItemListView(parent),
-    m_modelRolesUpdater(0),
-    m_updateVisibleIndexRangeTimer(0),
-    m_updateIconSizeTimer(0)
+namespace
+{
+// If the visible index range changes, KFileItemModelRolesUpdater is not
+// informed immediately, but with a short delay. This ensures that scrolling
+// always feels smooth and is not interrupted by icon loading (which can be
+// quite expensive if a disk access is required to determine the final icon).
+const int ShortInterval = 50;
+
+// If the icon size changes, a longer delay is used. This prevents that
+// the expensive re-generation of all previews is triggered repeatedly when
+// changing the zoom level.
+const int LongInterval = 300;
+}
+
+KFileItemListView::KFileItemListView(QGraphicsWidget *parent)
+    : KStandardItemListView(parent)
+    , m_modelRolesUpdater(nullptr)
+    , m_updateVisibleIndexRangeTimer(nullptr)
+    , m_updateIconSizeTimer(nullptr)
 {
     setAcceptDrops(true);
 
@@ -103,7 +95,7 @@ bool KFileItemListView::enlargeSmallPreviews() const
     return m_modelRolesUpdater ? m_modelRolesUpdater->enlargeSmallPreviews() : false;
 }
 
-void KFileItemListView::setEnabledPlugins(const QStringListlist)
+void KFileItemListView::setEnabledPlugins(const QStringList &list)
 {
     if (m_modelRolesUpdater) {
         m_modelRolesUpdater->setEnabledPlugins(list);
@@ -115,7 +107,19 @@ QStringList KFileItemListView::enabledPlugins() const
     return m_modelRolesUpdater ? m_modelRolesUpdater->enabledPlugins() : QStringList();
 }
 
-QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const
+void KFileItemListView::setLocalFileSizePreviewLimit(const qlonglong size)
+{
+    if (m_modelRolesUpdater) {
+        m_modelRolesUpdater->setLocalFileSizePreviewLimit(size);
+    }
+}
+
+qlonglong KFileItemListView::localFileSizePreviewLimit() const
+{
+    return m_modelRolesUpdater ? m_modelRolesUpdater->localFileSizePreviewLimit() : 0;
+}
+
+QPixmap KFileItemListView::createDragPixmap(const KItemSet &indexes) const
 {
     if (!model()) {
         return QPixmap();
@@ -154,21 +158,31 @@ QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const
         yCount = xCount;
     }
 
+    const qreal dpr = KItemViewsUtils::devicePixelRatio(this);
     // Draw the selected items into the grid cells.
-    QPixmap dragPixmap(xCount * size + xCount, yCount * size + yCount);
+    QPixmap dragPixmap(QSize(xCount * size + xCount, yCount * size + yCount) * dpr);
+    dragPixmap.setDevicePixelRatio(dpr);
     dragPixmap.fill(Qt::transparent);
 
     QPainter painter(&dragPixmap);
     int x = 0;
     int y = 0;
 
-    foreach (int index, indexes) {
+    for (int index : indexes) {
         QPixmap pixmap = model()->data(index).value("iconPixmap").value<QPixmap>();
         if (pixmap.isNull()) {
             QIcon icon = QIcon::fromTheme(model()->data(index).value("iconName").toString());
-            pixmap = icon.pixmap(size, size);
+            if (icon.isNull()) {
+                icon = QIcon::fromTheme(QStringLiteral("unknown"));
+            }
+            if (!icon.isNull()) {
+                pixmap = icon.pixmap(size, size);
+            } else {
+                pixmap = QPixmap(size, size);
+                pixmap.fill(Qt::transparent);
+            }
         } else {
-            KPixmapModifier::scale(pixmap, QSize(size, size));
+            KPixmapModifier::scale(pixmap, QSize(size, size) * dpr);
         }
 
         painter.drawPixmap(x, y, pixmap);
@@ -187,30 +201,42 @@ QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const
     return dragPixmap;
 }
 
-KItemListWidgetCreatorBase* KFileItemListView::defaultWidgetCreator() const
+void KFileItemListView::setHoverSequenceState(const QUrl &itemUrl, int seqIdx)
+{
+    if (m_modelRolesUpdater) {
+        m_modelRolesUpdater->setHoverSequenceState(itemUrl, seqIdx);
+    }
+}
+
+KItemListWidgetCreatorBase *KFileItemListView::defaultWidgetCreator() const
 {
     return new KItemListWidgetCreator<KFileItemListWidget>();
 }
 
-void KFileItemListView::initializeItemListWidget(KItemListWidgetitem)
+void KFileItemListView::initializeItemListWidget(KItemListWidget *item)
 {
     KStandardItemListView::initializeItemListWidget(item);
 
     // Make sure that the item has an icon.
     QHash<QByteArray, QVariant> data = item->data();
     if (!data.contains("iconName") && data["iconPixmap"].value<QPixmap>().isNull()) {
-        Q_ASSERT(qobject_cast<KFileItemModel*>(model()));
-        KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(model());
+        Q_ASSERT(qobject_cast<KFileItemModel *>(model()));
+        KFileItemModel *fileItemModel = static_cast<KFileItemModel *>(model());
 
         const KFileItem fileItem = fileItemModel->fileItem(item->index());
-        data.insert("iconName", fileItem.iconName());
+        QString iconName = fileItem.iconName();
+        if (!QIcon::hasThemeIcon(iconName)) {
+            QMimeDatabase mimeDb;
+            iconName = mimeDb.mimeTypeForName(fileItem.mimetype()).genericIconName();
+        }
+        data.insert("iconName", iconName);
         item->setData(data, {"iconName"});
     }
 }
 
 void KFileItemListView::onPreviewsShownChanged(bool shown)
 {
-    Q_UNUSED(shown);
+    Q_UNUSED(shown)
 }
 
 void KFileItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previous)
@@ -219,17 +245,18 @@ void KFileItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previ
     triggerVisibleIndexRangeUpdate();
 }
 
-void KFileItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* previous)
+void KFileItemListView::onModelChanged(KItemModelBase *current, KItemModelBase *previous)
 {
-    Q_ASSERT(qobject_cast<KFileItemModel*>(current));
+    Q_ASSERT(qobject_cast<KFileItemModel *>(current));
     KStandardItemListView::onModelChanged(current, previous);
 
     delete m_modelRolesUpdater;
-    m_modelRolesUpdater = 0;
+    m_modelRolesUpdater = nullptr;
 
     if (current) {
-        m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast<KFileItemModel*>(current), this);
+        m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast<KFileItemModel *>(current), this);
         m_modelRolesUpdater->setIconSize(availableIconSize());
+        m_modelRolesUpdater->setDevicePixelRatio(KItemViewsUtils::devicePixelRatio(this));
 
         applyRolesToModel();
     }
@@ -241,10 +268,10 @@ void KFileItemListView::onScrollOrientationChanged(Qt::Orientation current, Qt::
     triggerVisibleIndexRangeUpdate();
 }
 
-void KFileItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previous)
+void KFileItemListView::onItemSizeChanged(const QSizeF &current, const QSizeF &previous)
 {
-    Q_UNUSED(current);
-    Q_UNUSED(previous);
+    Q_UNUSED(current)
+    Q_UNUSED(previous)
     triggerVisibleIndexRangeUpdate();
 }
 
@@ -254,13 +281,13 @@ void KFileItemListView::onScrollOffsetChanged(qreal current, qreal previous)
     triggerVisibleIndexRangeUpdate();
 }
 
-void KFileItemListView::onVisibleRolesChanged(const QList<QByteArray>& current, const QList<QByteArray>& previous)
+void KFileItemListView::onVisibleRolesChanged(const QList<QByteArray> &current, const QList<QByteArray> &previous)
 {
     KStandardItemListView::onVisibleRolesChanged(current, previous);
     applyRolesToModel();
 }
 
-void KFileItemListView::onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous)
+void KFileItemListView::onStyleOptionChanged(const KItemListStyleOption &current, const KItemListStyleOption &previous)
 {
     KStandardItemListView::onStyleOptionChanged(current, previous);
     triggerIconSizeUpdate();
@@ -289,25 +316,49 @@ void KFileItemListView::onTransactionEnd()
     // Only unpause the model-roles-updater if no timer is active. If one
     // timer is still active the model-roles-updater will be unpaused later as
     // soon as the timer has been exceeded.
-    const bool timerActive = m_updateVisibleIndexRangeTimer->isActive() ||
-                             m_updateIconSizeTimer->isActive();
+    const bool timerActive = m_updateVisibleIndexRangeTimer->isActive() || m_updateIconSizeTimer->isActive();
     if (!timerActive) {
         m_modelRolesUpdater->setPaused(false);
     }
 }
 
-void KFileItemListView::resizeEvent(QGraphicsSceneResizeEventevent)
+void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent *event)
 {
     KStandardItemListView::resizeEvent(event);
     triggerVisibleIndexRangeUpdate();
 }
 
-void KFileItemListView::slotItemsRemoved(const KItemRangeList& itemRanges)
+void KFileItemListView::focusInEvent(QFocusEvent *event)
+{
+    Q_UNUSED(event)
+    updateSelectedWidgets();
+}
+
+void KFileItemListView::focusOutEvent(QFocusEvent *event)
+{
+    Q_UNUSED(event)
+    updateSelectedWidgets();
+}
+
+void KFileItemListView::updateSelectedWidgets()
+{
+    const auto visibleWidgets = visibleItemListWidgets();
+    for (KItemListWidget *widget : visibleWidgets) {
+        if (widget->isSelected()) {
+            auto w = qobject_cast<KFileItemListWidget *>(widget);
+            if (w) {
+                w->forceUpdate();
+            }
+        }
+    }
+}
+
+void KFileItemListView::slotItemsRemoved(const KItemRangeList &itemRanges)
 {
     KStandardItemListView::slotItemsRemoved(itemRanges);
 }
 
-void KFileItemListView::slotSortRoleChanged(const QByteArray& current, const QByteArray& previous)
+void KFileItemListView::slotSortRoleChanged(const QByteArray &current, const QByteArray &previous)
 {
     const QByteArray sortRole = model()->sortRole();
     if (!visibleRoles().contains(sortRole)) {
@@ -365,6 +416,7 @@ void KFileItemListView::updateIconSize()
     }
 
     m_modelRolesUpdater->setIconSize(availableIconSize());
+    m_modelRolesUpdater->setDevicePixelRatio(KItemViewsUtils::devicePixelRatio(this));
 
     // Update the visible index range (which has most likely changed after the
     // icon size change) before unpausing m_modelRolesUpdater.
@@ -381,25 +433,28 @@ void KFileItemListView::applyRolesToModel()
         return;
     }
 
-    Q_ASSERT(qobject_cast<KFileItemModel*>(model()));
-    KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(model());
+    Q_ASSERT(qobject_cast<KFileItemModel *>(model()));
+    KFileItemModel *fileItemModel = static_cast<KFileItemModel *>(model());
 
     // KFileItemModel does not distinct between "visible" and "invisible" roles.
     // Add all roles that are mandatory for having a working KFileItemListView:
-    QSet<QByteArray> roles = visibleRoles().toSet();
+    const auto visibleRoles = this->visibleRoles();
+    auto roles = QSet<QByteArray>(visibleRoles.constBegin(), visibleRoles.constEnd());
     roles.insert("iconPixmap");
     roles.insert("iconName");
     roles.insert("text");
     roles.insert("isDir");
     roles.insert("isLink");
+    roles.insert("isHidden");
     if (supportsItemExpanding()) {
         roles.insert("isExpanded");
         roles.insert("isExpandable");
         roles.insert("expandedParentsCount");
     }
 
-    // Assure that the role that is used for sorting will be determined
+    // Assure that the roles used for sorting and grouping will be determined
     roles.insert(fileItemModel->sortRole());
+    roles.insert(fileItemModel->groupRole());
 
     fileItemModel->setRoles(roles);
     m_modelRolesUpdater->setRoles(roles);
@@ -407,7 +462,7 @@ void KFileItemListView::applyRolesToModel()
 
 QSize KFileItemListView::availableIconSize() const
 {
-    const KItemListStyleOptionoption = styleOption();
+    const KItemListStyleOption &option = styleOption();
     const int iconSize = option.iconSize;
     if (itemLayout() == IconsLayout) {
         const int maxIconWidth = itemSize().width() - 2 * option.padding;
@@ -417,3 +472,4 @@ QSize KFileItemListView::availableIconSize() const
     return QSize(iconSize, iconSize);
 }
 
+#include "moc_kfileitemlistview.cpp"