X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/793311dac163592a8b63fc4859fdc054d7a22022..1b6ee5d6cd918b81c59a5163c9d6371f35f9885c:/src/kitemviews/kfileitemlistview.cpp diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index 8f7c9c899..5efb820b0 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -19,31 +19,36 @@ #include "kfileitemlistview.h" -#include "kfileitemlistgroupheader.h" #include "kfileitemmodelrolesupdater.h" #include "kfileitemlistwidget.h" #include "kfileitemmodel.h" -#include "kpixmapmodifier_p.h" -#include -#include +#include "private/kpixmapmodifier.h" -#include -#include +#include +#include #include -#include #include +#include +#include // #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) : - KItemListView(parent), - m_itemLayout(IconsLayout), + KStandardItemListView(parent), m_modelRolesUpdater(0), m_updateVisibleIndexRangeTimer(0), m_updateIconSizeTimer(0) @@ -51,64 +56,53 @@ KFileItemListView::KFileItemListView(QGraphicsWidget* parent) : setAcceptDrops(true); setScrollOrientation(Qt::Vertical); - setWidgetCreator(new KItemListWidgetCreator()); - setGroupHeaderCreator(new KItemListGroupHeaderCreator()); 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() << "name"); + setVisibleRoles({"text"}); } KFileItemListView::~KFileItemListView() { - // The group headers are children of the widgets created by - // widgetCreator(). So it is mandatory to delete the group headers - // first. - delete groupHeaderCreator(); - delete widgetCreator(); - - delete m_modelRolesUpdater; - m_modelRolesUpdater = 0; } void KFileItemListView::setPreviewsShown(bool show) { - if (m_modelRolesUpdater) { - m_modelRolesUpdater->setPreviewShown(show); + if (!m_modelRolesUpdater) { + return; + } + + if (m_modelRolesUpdater->previewsShown() != show) { + beginTransaction(); + m_modelRolesUpdater->setPreviewsShown(show); + onPreviewsShownChanged(show); + endTransaction(); } } bool KFileItemListView::previewsShown() const { - return m_modelRolesUpdater->isPreviewShown(); + return m_modelRolesUpdater ? m_modelRolesUpdater->previewsShown() : false; } -void KFileItemListView::setItemLayout(Layout layout) +void KFileItemListView::setEnlargeSmallPreviews(bool enlarge) { - if (m_itemLayout != layout) { - const bool updateRoles = (m_itemLayout == DetailsLayout || layout == DetailsLayout); - m_itemLayout = layout; - if (updateRoles) { - // The details-layout requires some invisible roles that - // must be added to the model if the new layout is "details". - // If the old layout was "details" the roles will get removed. - applyRolesToModel(); - } - updateLayoutOfVisibleItems(); + if (m_modelRolesUpdater) { + m_modelRolesUpdater->setEnlargeSmallPreviews(enlarge); } } -KFileItemListView::Layout KFileItemListView::itemLayout() const +bool KFileItemListView::enlargeSmallPreviews() const { - return m_itemLayout; + return m_modelRolesUpdater ? m_modelRolesUpdater->enlargeSmallPreviews() : false; } void KFileItemListView::setEnabledPlugins(const QStringList& list) @@ -123,7 +117,7 @@ QStringList KFileItemListView::enabledPlugins() const return m_modelRolesUpdater ? m_modelRolesUpdater->enabledPlugins() : QStringList(); } -QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const +QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const { if (!model()) { return QPixmap(); @@ -131,6 +125,9 @@ QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const const int itemCount = indexes.count(); Q_ASSERT(itemCount > 0); + if (itemCount == 1) { + return KItemListView::createDragPixmap(indexes); + } // If more than one item is dragged, align the items inside a // rectangular grid. The maximum grid size is limited to 5 x 5 items. @@ -159,23 +156,23 @@ 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(); + foreach (int index, indexes) { QPixmap pixmap = model()->data(index).value("iconPixmap").value(); if (pixmap.isNull()) { - KIcon icon(model()->data(index).value("iconName").toString()); + QIcon icon = QIcon::fromTheme(model()->data(index).value("iconName").toString()); pixmap = icon.pixmap(size, size); } else { - KPixmapModifier::scale(pixmap, QSize(size, size)); + KPixmapModifier::scale(pixmap, QSize(size, size) * dpr); } painter.drawPixmap(x, y, pixmap); @@ -194,52 +191,58 @@ QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const return dragPixmap; } +KItemListWidgetCreatorBase* KFileItemListView::defaultWidgetCreator() const +{ + return new KItemListWidgetCreator(); +} + void KFileItemListView::initializeItemListWidget(KItemListWidget* item) { - KFileItemListWidget* fileItemListWidget = static_cast(item); + KStandardItemListView::initializeItemListWidget(item); - switch (m_itemLayout) { - case IconsLayout: fileItemListWidget->setLayout(KFileItemListWidget::IconsLayout); break; - case CompactLayout: fileItemListWidget->setLayout(KFileItemListWidget::CompactLayout); break; - case DetailsLayout: fileItemListWidget->setLayout(KFileItemListWidget::DetailsLayout); break; - default: Q_ASSERT(false); break; - } + // Make sure that the item has an icon. + QHash data = item->data(); + if (!data.contains("iconName") && data["iconPixmap"].value().isNull()) { + Q_ASSERT(qobject_cast(model())); + KFileItemModel* fileItemModel = static_cast(model()); - fileItemListWidget->setSupportsItemExpanding(supportsItemExpanding()); + const KFileItem fileItem = fileItemModel->fileItem(item->index()); + data.insert("iconName", fileItem.iconName()); + item->setData(data, {"iconName"}); + } } -bool KFileItemListView::itemSizeHintUpdateRequired(const QSet& changedRoles) const +void KFileItemListView::onPreviewsShownChanged(bool shown) { - // Even if the icons have a different size they are always aligned within - // the area defined by KItemStyleOption.iconSize and hence result in no - // change of the item-size. - const bool containsIconName = changedRoles.contains("iconName"); - const bool containsIconPixmap = changedRoles.contains("iconPixmap"); - const int count = changedRoles.count(); + Q_UNUSED(shown); +} - const bool iconChanged = (containsIconName && containsIconPixmap && count == 2) || - (containsIconName && count == 1) || - (containsIconPixmap && count == 1); - return !iconChanged; +void KFileItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previous) +{ + KStandardItemListView::onItemLayoutChanged(current, previous); + triggerVisibleIndexRangeUpdate(); } void KFileItemListView::onModelChanged(KItemModelBase* current, KItemModelBase* previous) { - Q_UNUSED(previous); Q_ASSERT(qobject_cast(current)); + KStandardItemListView::onModelChanged(current, previous); delete m_modelRolesUpdater; - m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast(current), this); - m_modelRolesUpdater->setIconSize(availableIconSize()); + m_modelRolesUpdater = 0; - applyRolesToModel(); + if (current) { + m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast(current), this); + m_modelRolesUpdater->setIconSize(availableIconSize()); + + applyRolesToModel(); + } } void KFileItemListView::onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous) { - Q_UNUSED(current); - Q_UNUSED(previous); - updateLayoutOfVisibleItems(); + KStandardItemListView::onScrollOrientationChanged(current, previous); + triggerVisibleIndexRangeUpdate(); } void KFileItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& previous) @@ -251,39 +254,42 @@ void KFileItemListView::onItemSizeChanged(const QSizeF& current, const QSizeF& p void KFileItemListView::onScrollOffsetChanged(qreal current, qreal previous) { - Q_UNUSED(current); - Q_UNUSED(previous); + KStandardItemListView::onScrollOffsetChanged(current, previous); triggerVisibleIndexRangeUpdate(); } void KFileItemListView::onVisibleRolesChanged(const QList& current, const QList& previous) { - Q_UNUSED(current); - Q_UNUSED(previous); + KStandardItemListView::onVisibleRolesChanged(current, previous); applyRolesToModel(); } void KFileItemListView::onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous) { - Q_UNUSED(current); - Q_UNUSED(previous); + KStandardItemListView::onStyleOptionChanged(current, previous); triggerIconSizeUpdate(); } void KFileItemListView::onSupportsItemExpandingChanged(bool supportsExpanding) { - Q_UNUSED(supportsExpanding); applyRolesToModel(); - updateLayoutOfVisibleItems(); + KStandardItemListView::onSupportsItemExpandingChanged(supportsExpanding); + triggerVisibleIndexRangeUpdate(); } void KFileItemListView::onTransactionBegin() { - m_modelRolesUpdater->setPaused(true); + if (m_modelRolesUpdater) { + m_modelRolesUpdater->setPaused(true); + } } void KFileItemListView::onTransactionEnd() { + if (!m_modelRolesUpdater) { + return; + } + // 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. @@ -296,14 +302,13 @@ void KFileItemListView::onTransactionEnd() void KFileItemListView::resizeEvent(QGraphicsSceneResizeEvent* event) { - KItemListView::resizeEvent(event); + KStandardItemListView::resizeEvent(event); triggerVisibleIndexRangeUpdate(); } void KFileItemListView::slotItemsRemoved(const KItemRangeList& itemRanges) { - KItemListView::slotItemsRemoved(itemRanges); - updateTimersInterval(); + KStandardItemListView::slotItemsRemoved(itemRanges); } void KFileItemListView::slotSortRoleChanged(const QByteArray& current, const QByteArray& previous) @@ -313,7 +318,7 @@ void KFileItemListView::slotSortRoleChanged(const QByteArray& current, const QBy applyRolesToModel(); } - KItemListView::slotSortRoleChanged(current, previous); + KStandardItemListView::slotSortRoleChanged(current, previous); } void KFileItemListView::triggerVisibleIndexRangeUpdate() @@ -322,7 +327,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() @@ -333,18 +343,9 @@ void KFileItemListView::updateVisibleIndexRange() const int index = firstVisibleIndex(); 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() @@ -354,6 +355,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() @@ -364,47 +370,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::updateLayoutOfVisibleItems() -{ - if (!model()) { - return; - } - - foreach (KItemListWidget* widget, visibleItemListWidgets()) { - initializeItemListWidget(widget); - } - triggerVisibleIndexRangeUpdate(); -} - -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() @@ -421,8 +393,9 @@ void KFileItemListView::applyRolesToModel() QSet roles = visibleRoles().toSet(); roles.insert("iconPixmap"); roles.insert("iconName"); - roles.insert("name"); + roles.insert("text"); roles.insert("isDir"); + roles.insert("isLink"); if (supportsItemExpanding()) { roles.insert("isExpanded"); roles.insert("isExpandable"); @@ -440,7 +413,7 @@ QSize KFileItemListView::availableIconSize() const { const KItemListStyleOption& option = styleOption(); const int iconSize = option.iconSize; - if (m_itemLayout == IconsLayout) { + if (itemLayout() == IconsLayout) { const int maxIconWidth = itemSize().width() - 2 * option.padding; return QSize(maxIconWidth, iconSize); } @@ -448,4 +421,3 @@ QSize KFileItemListView::availableIconSize() const return QSize(iconSize, iconSize); } -#include "kfileitemlistview.moc"