#include <QPropertyAnimation>
#include <QStyleOptionRubberBand>
#include <QTimer>
+#include <QVariantAnimation>
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
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
if (newOffset != scrollOffset()) {
Q_EMIT scrollTo(newOffset);
+ return;
}
}
+
+ Q_EMIT scrollingStopped();
}
void KItemListView::beginTransaction()
{
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();
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;
{
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)
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();
// 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);
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;