]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kitemlistview.cpp
Load service menus for settings from new file location
[dolphin.git] / src / kitemviews / kitemlistview.cpp
index f6e5e666bb8e2e00ecdf710d3c7aa492a4ff9bb6..a4074c6cb4cff45ca4c7542e76903f3e4958778a 100644 (file)
@@ -27,6 +27,7 @@
 #include <QPropertyAnimation>
 #include <QStyleOptionRubberBand>
 #include <QTimer>
+#include <QVariantAnimation>
 
 
 namespace {
@@ -36,6 +37,11 @@ namespace {
 
     // Delay in ms for triggering the next autoscroll
     const int RepeatingAutoScrollDelay = 1000 / 60;
+
+    // Copied from the Kirigami.Units.shortDuration
+    const int RubberFadeSpeed = 150;
+
+    const char* RubberPropertyName = "_kitemviews_rubberBandPosition";
 }
 
 #ifndef QT_NO_ACCESSIBILITY
@@ -366,29 +372,12 @@ void KItemListView::setGeometry(const QRectF& rect)
                                          m_itemSize.height());
             m_layouter->setItemSize(dynamicItemSize);
         }
-
-        // Triggering a synchronous layout is fine from a performance point of view,
-        // as with dynamic item sizes no moving animation must be done.
-        m_layouter->setSize(newSize);
-        doLayout(NoAnimation);
-    } else {
-        const bool animate = !changesItemGridLayout(newSize,
-                                                    m_layouter->itemSize(),
-                                                    m_layouter->itemMargin());
-        m_layouter->setSize(newSize);
-
-        if (animate) {
-            // Trigger an asynchronous relayout with m_layoutTimer to prevent
-            // performance bottlenecks. If the timer is exceeded, an animated layout
-            // will be triggered.
-            if (!m_layoutTimer->isActive()) {
-                m_layoutTimer->start();
-            }
-        } else {
-            m_layoutTimer->stop();
-            doLayout(NoAnimation);
-        }
     }
+
+    m_layouter->setSize(newSize);
+    // We don't animate the moving of the items here because
+    // it would look like the items are slow to find their position.
+    doLayout(NoAnimation);
 }
 
 qreal KItemListView::verticalPageStep() const
@@ -400,7 +389,7 @@ qreal KItemListView::verticalPageStep() const
     return size().height() - headerHeight;
 }
 
-int KItemListView::itemAt(const QPointF& pos) const
+std::optional<int> KItemListView::itemAt(const QPointF& pos) const
 {
     QHashIterator<int, KItemListWidget*> it(m_visibleItems);
     while (it.hasNext()) {
@@ -413,7 +402,7 @@ int KItemListView::itemAt(const QPointF& pos) const
         }
     }
 
-    return -1;
+    return std::nullopt;
 }
 
 bool KItemListView::isAboveSelectionToggle(int index, const QPointF& pos) const
@@ -469,7 +458,7 @@ int KItemListView::lastVisibleIndex() const
     return m_layouter->lastVisibleIndex();
 }
 
-void KItemListView::calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint) const
+void KItemListView::calculateItemSizeHints(QVector<std::pair<qreal, bool>>& logicalHeightHints, qreal& logicalWidthHint) const
 {
     widgetCreator()->calculateItemSizeHints(logicalHeightHints, logicalWidthHint, this);
 }
@@ -506,6 +495,11 @@ QRectF KItemListView::itemContextRect(int index) const
     return contextRect;
 }
 
+bool KItemListView::isElided(int index) const
+{
+    return m_sizeHintResolver->isElided(index);
+}
+
 void KItemListView::scrollToItem(int index)
 {
     QRectF viewGeometry = geometry();
@@ -537,8 +531,11 @@ void KItemListView::scrollToItem(int index)
 
         if (newOffset != scrollOffset()) {
             Q_EMIT scrollTo(newOffset);
+            return;
         }
     }
+
+    Q_EMIT scrollingStopped();
 }
 
 void KItemListView::beginTransaction()
@@ -660,6 +657,30 @@ void KItemListView::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
 {
     QGraphicsWidget::paint(painter, option, widget);
 
+    for (auto animation : qAsConst(m_rubberBandAnimations)) {
+        QRectF rubberBandRect = animation->property(RubberPropertyName).toRectF();
+
+        const QPointF topLeft = rubberBandRect.topLeft();
+        if (scrollOrientation() == Qt::Vertical) {
+            rubberBandRect.moveTo(topLeft.x(), topLeft.y() - scrollOffset());
+        } else {
+            rubberBandRect.moveTo(topLeft.x() - scrollOffset(), topLeft.y());
+        }
+
+        QStyleOptionRubberBand opt;
+        initStyleOption(&opt);
+        opt.shape = QRubberBand::Rectangle;
+        opt.opaque = false;
+        opt.rect = rubberBandRect.toRect();
+
+        painter->save();
+
+        painter->setOpacity(animation->currentValue().toReal());
+        style()->drawControl(QStyle::CE_RubberBand, &opt, painter);
+
+        painter->restore();
+    }
+
     if (m_rubberBand->isActive()) {
         QRectF rubberBandRect = QRectF(m_rubberBand->startPosition(),
                                        m_rubberBand->endPosition()).normalized();
@@ -1455,6 +1476,30 @@ void KItemListView::slotRubberBandActivationChanged(bool active)
         connect(m_rubberBand, &KItemListRubberBand::endPositionChanged, this, &KItemListView::slotRubberBandPosChanged);
         m_skipAutoScrollForRubberBand = true;
     } else {
+        QRectF rubberBandRect = QRectF(m_rubberBand->startPosition(),
+                                       m_rubberBand->endPosition()).normalized();
+
+        auto animation = new QVariantAnimation(this);
+        animation->setStartValue(1.0);
+        animation->setEndValue(0.0);
+        animation->setDuration(RubberFadeSpeed);
+        animation->setProperty(RubberPropertyName, rubberBandRect);
+
+        QEasingCurve curve;
+        curve.setType(QEasingCurve::BezierSpline);
+        curve.addCubicBezierSegment(QPointF(0.4, 0.0), QPointF(1.0, 1.0), QPointF(1.0, 1.0));
+        animation->setEasingCurve(curve);
+
+        connect(animation, &QVariantAnimation::valueChanged, this, [=](const QVariant&) {
+            update();
+        });
+        connect(animation, &QVariantAnimation::finished, this, [=]() {
+            m_rubberBandAnimations.removeAll(animation);
+            delete animation;
+        });
+        animation->start();
+        m_rubberBandAnimations << animation;
+
         disconnect(m_rubberBand, &KItemListRubberBand::startPositionChanged, this, &KItemListView::slotRubberBandPosChanged);
         disconnect(m_rubberBand, &KItemListRubberBand::endPositionChanged, this, &KItemListView::slotRubberBandPosChanged);
         m_skipAutoScrollForRubberBand = false;
@@ -1565,16 +1610,16 @@ void KItemListView::slotRoleEditingCanceled(int index, const QByteArray& role, c
 {
     disconnectRoleEditingSignals(index);
 
-    Q_EMIT roleEditingCanceled(index, role, value);
     m_editingRole = false;
+    Q_EMIT roleEditingCanceled(index, role, value);
 }
 
 void KItemListView::slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value)
 {
     disconnectRoleEditingSignals(index);
 
-    Q_EMIT roleEditingFinished(index, role, value);
     m_editingRole = false;
+    Q_EMIT roleEditingFinished(index, role, value);
 }
 
 void KItemListView::setController(KItemListController* controller)
@@ -1713,13 +1758,11 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
     const bool animate = (hint == Animation);
     for (int i = firstVisibleIndex; i <= lastVisibleIndex; ++i) {
         bool applyNewPos = true;
-        bool wasHidden = false;
 
         const QRectF itemBounds = m_layouter->itemRect(i);
         const QPointF newPos = itemBounds.topLeft();
         KItemListWidget* widget = m_visibleItems.value(i);
         if (!widget) {
-            wasHidden = true;
             if (!reusableItems.isEmpty()) {
                 // Reuse a KItemListWidget instance from an invisible item
                 const int oldIndex = reusableItems.takeLast();
@@ -1786,9 +1829,6 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
                     // prevents a "move animation mess" when inserting several ranges in parallel.
                     applyNewPos = !moveWidget(widget, newPos);
                 }
-            } else if (!itemsRemoved && !itemsInserted && !wasHidden) {
-                // The size of the view might have been changed. Animate the moving of the position.
-                applyNewPos = !moveWidget(widget, newPos);
             }
         } else {
             m_animation->stop(widget);
@@ -2202,11 +2242,11 @@ QHash<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeLi
     const int headerMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderMargin);
     for (const QByteArray& visibleRole : qAsConst(m_visibleRoles)) {
         const QString headerText = m_model->roleDescription(visibleRole);
-        const qreal headerWidth = fontMetrics.width(headerText) + gripMargin + headerMargin * 2;
+        const qreal headerWidth = fontMetrics.horizontalAdvance(headerText) + gripMargin + headerMargin * 2;
         widths.insert(visibleRole, headerWidth);
     }
 
-    // Calculate the preferred column withs for each item and ignore values
+    // Calculate the preferred column widths for each item and ignore values
     // smaller than the width for showing the headline unclipped.
     const KItemListWidgetCreatorBase* creator = widgetCreator();
     int calculatedItemCount = 0;
@@ -2517,7 +2557,7 @@ void KItemListView::updateGroupHeaderHeight()
         groupHeaderHeight += 2 * m_styleOption.horizontalMargin;
         groupHeaderMargin = m_styleOption.horizontalMargin;
     } else if (m_itemSize.isEmpty()){
-        groupHeaderHeight += 2 * m_styleOption.padding;
+        groupHeaderHeight += 4 * m_styleOption.padding;
         groupHeaderMargin = m_styleOption.iconSize / 2;
     } else {
         groupHeaderHeight += 2 * m_styleOption.padding + m_styleOption.verticalMargin;