X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/3991e9d24eb2aba2ea7228f925cfa0a60e55463f..8fda69892284144a8aea3845d2aad844021c99d2:/src/kitemviews/kfileitemlistview.cpp diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 1f0fcbd6f..adcc2d793 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -1,51 +1,46 @@ -/*************************************************************************** - * Copyright (C) 2011 by Peter Penz * - * * - * 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 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "kfileitemlistview.h" -#include "kfileitemmodelrolesupdater.h" #include "kfileitemlistwidget.h" #include "kfileitemmodel.h" -#include -#include +#include "kfileitemmodelrolesupdater.h" #include "private/kpixmapmodifier.h" -#include -#include -#include +#include +#include +#include #include -#include #include +#include +#include // #define KFILEITEMLISTVIEW_DEBUG 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(0), - m_updateVisibleIndexRangeTimer(0), - m_updateIconSizeTimer(0) + m_modelRolesUpdater(nullptr), + m_updateVisibleIndexRangeTimer(nullptr), + m_updateIconSizeTimer(nullptr), + m_scanDirectories(true) { setAcceptDrops(true); @@ -54,14 +49,14 @@ KFileItemListView::KFileItemListView(QGraphicsWidget* parent) : m_updateVisibleIndexRangeTimer = new QTimer(this); m_updateVisibleIndexRangeTimer->setSingleShot(true); m_updateVisibleIndexRangeTimer->setInterval(ShortInterval); - connect(m_updateVisibleIndexRangeTimer, SIGNAL(timeout()), this, SLOT(updateVisibleIndexRange())); + connect(m_updateVisibleIndexRangeTimer, &QTimer::timeout, this, &KFileItemListView::updateVisibleIndexRange); m_updateIconSizeTimer = new QTimer(this); m_updateIconSizeTimer->setSingleShot(true); - m_updateIconSizeTimer->setInterval(ShortInterval); - connect(m_updateIconSizeTimer, SIGNAL(timeout()), this, SLOT(updateIconSize())); + m_updateIconSizeTimer->setInterval(LongInterval); + connect(m_updateIconSizeTimer, &QTimer::timeout, this, &KFileItemListView::updateIconSize); - setVisibleRoles(QList() << "text"); + setVisibleRoles({"text"}); } KFileItemListView::~KFileItemListView() @@ -111,7 +106,32 @@ QStringList KFileItemListView::enabledPlugins() const return m_modelRolesUpdater ? m_modelRolesUpdater->enabledPlugins() : QStringList(); } -QPixmap KFileItemListView::createDragPixmap(const QSet& 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; +} + +void KFileItemListView::setScanDirectories(bool enabled) +{ + m_scanDirectories = enabled; + if (m_modelRolesUpdater) { + m_modelRolesUpdater->setScanDirectories(m_scanDirectories); + } +} + +bool KFileItemListView::scanDirectories() +{ + return m_scanDirectories; +} + +QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const { if (!model()) { return QPixmap(); @@ -150,23 +170,31 @@ QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const yCount = xCount; } + const qreal dpr = scene()->views()[0]->devicePixelRatio(); // 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; - QSetIterator it(indexes); - while (it.hasNext()) { - const int index = it.next(); + for (int index : indexes) { QPixmap pixmap = model()->data(index).value("iconPixmap").value(); if (pixmap.isNull()) { - KIcon icon(model()->data(index).value("iconName").toString()); - pixmap = icon.pixmap(size, size); + QIcon icon = QIcon::fromTheme(model()->data(index).value("iconName").toString()); + if (icon.isNull()) { + icon = QIcon::fromTheme("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); @@ -185,6 +213,13 @@ QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const return dragPixmap; } +void KFileItemListView::setHoverSequenceState(const QUrl& itemUrl, int seqIdx) +{ + if (m_modelRolesUpdater) { + m_modelRolesUpdater->setHoverSequenceState(itemUrl, seqIdx); + } +} + KItemListWidgetCreatorBase* KFileItemListView::defaultWidgetCreator() const { return new KItemListWidgetCreator(); @@ -201,14 +236,19 @@ void KFileItemListView::initializeItemListWidget(KItemListWidget* item) KFileItemModel* fileItemModel = static_cast(model()); const KFileItem fileItem = fileItemModel->fileItem(item->index()); - data.insert("iconName", fileItem.iconName()); - item->setData(data, QSet() << "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) @@ -223,11 +263,12 @@ void KFileItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* KStandardItemListView::onModelChanged(current, previous); delete m_modelRolesUpdater; - m_modelRolesUpdater = 0; + m_modelRolesUpdater = nullptr; if (current) { m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast(current), this); m_modelRolesUpdater->setIconSize(availableIconSize()); + m_modelRolesUpdater->setScanDirectories(scanDirectories()); applyRolesToModel(); } @@ -241,8 +282,8 @@ void KFileItemListView::onScrollOrientationChanged(Qt::Orientation current, Qt:: void KFileItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previous) { - Q_UNUSED(current); - Q_UNUSED(previous); + Q_UNUSED(current) + Q_UNUSED(previous) triggerVisibleIndexRangeUpdate(); } @@ -303,7 +344,6 @@ void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent* event) void KFileItemListView::slotItemsRemoved(const KItemRangeList& itemRanges) { KStandardItemListView::slotItemsRemoved(itemRanges); - updateTimersInterval(); } void KFileItemListView::slotSortRoleChanged(const QByteArray& current, const QByteArray& previous) @@ -322,7 +362,12 @@ void KFileItemListView::triggerVisibleIndexRangeUpdate() return; } m_modelRolesUpdater->setPaused(true); - m_updateVisibleIndexRangeTimer->start(); + + // If the icon size has been changed recently, wait until + // m_updateIconSizeTimer expires. + if (!m_updateIconSizeTimer->isActive()) { + m_updateVisibleIndexRangeTimer->start(); + } } void KFileItemListView::updateVisibleIndexRange() @@ -335,17 +380,7 @@ void KFileItemListView::updateVisibleIndexRange() const int count = lastVisibleIndex() - index + 1; m_modelRolesUpdater->setMaximumVisibleItems(maximumVisibleItems()); m_modelRolesUpdater->setVisibleIndexRange(index, count); - - if (m_updateIconSizeTimer->isActive()) { - // If the icon-size update is pending do an immediate update - // of the icon-size before unpausing m_modelRolesUpdater. This prevents - // an unnecessary expensive recreation of all previews afterwards. - m_updateIconSizeTimer->stop(); - m_modelRolesUpdater->setIconSize(availableIconSize()); - } - m_modelRolesUpdater->setPaused(isTransactionActive()); - updateTimersInterval(); } void KFileItemListView::triggerIconSizeUpdate() @@ -355,6 +390,11 @@ void KFileItemListView::triggerIconSizeUpdate() } m_modelRolesUpdater->setPaused(true); m_updateIconSizeTimer->start(); + + // The visible index range will be updated when m_updateIconSizeTimer expires. + // Stop m_updateVisibleIndexRangeTimer to prevent an expensive re-generation + // of all previews (note that the user might change the icon size again soon). + m_updateVisibleIndexRangeTimer->stop(); } void KFileItemListView::updateIconSize() @@ -365,35 +405,13 @@ void KFileItemListView::updateIconSize() m_modelRolesUpdater->setIconSize(availableIconSize()); - if (m_updateVisibleIndexRangeTimer->isActive()) { - // If the visibility-index-range update is pending do an immediate update - // of the range before unpausing m_modelRolesUpdater. This prevents - // an unnecessary expensive recreation of all previews afterwards. - m_updateVisibleIndexRangeTimer->stop(); - const int index = firstVisibleIndex(); - const int count = lastVisibleIndex() - index + 1; - m_modelRolesUpdater->setVisibleIndexRange(index, count); - } + // Update the visible index range (which has most likely changed after the + // icon size change) before unpausing m_modelRolesUpdater. + const int index = firstVisibleIndex(); + const int count = lastVisibleIndex() - index + 1; + m_modelRolesUpdater->setVisibleIndexRange(index, count); m_modelRolesUpdater->setPaused(isTransactionActive()); - updateTimersInterval(); -} - -void KFileItemListView::updateTimersInterval() -{ - if (!model()) { - return; - } - - // The ShortInterval is used for cases like switching the directory: If the - // model is empty and filled later the creation of the previews should be done - // as soon as possible. The LongInterval is used when the model already contains - // items and assures that operations like zooming don't result in too many temporary - // recreations of the previews. - - const int interval = (model()->count() <= 0) ? ShortInterval : LongInterval; - m_updateVisibleIndexRangeTimer->setInterval(interval); - m_updateIconSizeTimer->setInterval(interval); } void KFileItemListView::applyRolesToModel() @@ -407,12 +425,14 @@ void KFileItemListView::applyRolesToModel() // KFileItemModel does not distinct between "visible" and "invisible" roles. // Add all roles that are mandatory for having a working KFileItemListView: - QSet roles = visibleRoles().toSet(); + const auto visibleRoles = this->visibleRoles(); + auto roles = QSet(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"); @@ -438,4 +458,3 @@ QSize KFileItemListView::availableIconSize() const return QSize(iconSize, iconSize); } -#include "kfileitemlistview.moc"