Merge branch 'main' into feat/dashboard-media-widget
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 18s
Python / static (pull_request) Successful in 1m10s
Rust / fmt (pull_request) Successful in 1m1s
Rust / build (pull_request) Successful in 2m12s
Rust / clippy (pull_request) Successful in 1m17s
C++ / build (pull_request) Successful in 2m45s
Python / verify (pull_request) Successful in 3m9s
C++ / clang-tidy (pull_request) Successful in 4m7s

This commit is contained in:
2026-08-18 19:26:15 +02:00
3 changed files with 92 additions and 39 deletions
+7 -7
View File
@@ -15,6 +15,10 @@ CarouselView {
readonly property var values: Wallpapers.query(root.search.text.split(" ").slice(1).join(" ")) readonly property var values: Wallpapers.query(root.search.text.split(" ").slice(1).join(" "))
required property var visibilities required property var visibilities
currentIndex: {
const idx = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent);
return idx >= 0 ? idx : 0;
}
delegateProperties: ({ delegateProperties: ({
visibilities: root.visibilities visibilities: root.visibilities
}) })
@@ -41,13 +45,9 @@ CarouselView {
} }
} }
Component.onCompleted: {
const idx = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent);
if (idx >= 0)
jumpToIndex(idx);
}
Component.onDestruction: Wallpapers.stopPreview() Component.onDestruction: Wallpapers.stopPreview()
onPreviewIndexChanged: (realIndex, modelData) => { onCurrentItemChanged: {
Wallpapers.preview(modelData.path); if (currentItem)
Wallpapers.preview(currentItem.modelData.path);
} }
} }
+75 -28
View File
@@ -1,11 +1,13 @@
#include "carouselview.hpp" #include "carouselview.hpp"
#include <QSignalBlocker>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlProperty> #include <QQmlProperty>
#include <QMouseEvent> #include <QMouseEvent>
#include <QWheelEvent> #include <QWheelEvent>
#include <cmath> #include <cmath>
#include <qobject.h>
namespace ZShell::components { namespace ZShell::components {
@@ -81,6 +83,33 @@ void CarouselView::setDelegate(QQmlComponent* c) {
relayout(); relayout();
} }
void CarouselView::notifyCurrentIndexChanged() {
if (!m_completed) return;
emit currentIndexChanged();
}
void CarouselView::notifyCurrentItemChanged() {
if (!m_completed) return;
emit currentItemChanged();
}
void CarouselView::notifyPreviewIndexChanged(int realIndex) {
if (!m_completed || realIndex < 0) return;
emit previewIndexChanged(realIndex, m_model.at(realIndex));
}
void CarouselView::classBegin() {}
void CarouselView::componentComplete() {
m_completed = true;
emit currentIndexChanged();
if (m_currentRealIndex >= 0 && m_currentRealIndex < m_model.size())
emit previewIndexChanged(
m_currentRealIndex, m_model.at(m_currentRealIndex));
emit currentItemChanged();
}
bool CarouselView::childMouseEventFilter(QQuickItem* item, QEvent* event) { bool CarouselView::childMouseEventFilter(QQuickItem* item, QEvent* event) {
Q_UNUSED(item); Q_UNUSED(item);
@@ -163,7 +192,7 @@ void CarouselView::setModel(const QVariantList& m) {
if (newCount == 0) { if (newCount == 0) {
m_currentRealIndex = -1; m_currentRealIndex = -1;
m_currentItem = nullptr; m_currentItem = nullptr;
emit currentItemChanged(); notifyCurrentItemChanged();
releaseAllItems(); releaseAllItems();
rebuildArrangement(); rebuildArrangement();
@@ -173,19 +202,23 @@ void CarouselView::setModel(const QVariantList& m) {
if (!m_initializedLayout) { if (!m_initializedLayout) {
m_centerBlockStart = 0; m_centerBlockStart = 0;
m_currentVirtualIndex = 0;
m_contentX = contentXForIndex(0); const int startVirtual =
m_pendingCurrentIndex >= 0
? qBound(0, m_pendingCurrentIndex, newCount - 1)
: 0;
m_pendingCurrentIndex = -1;
m_currentVirtualIndex = startVirtual;
m_contentX = contentXForIndex(startVirtual);
m_currentRealIndex = realIndexOf(m_currentVirtualIndex); m_currentRealIndex = realIndexOf(m_currentVirtualIndex);
m_previewRealIndex = m_currentRealIndex; m_previewRealIndex = m_currentRealIndex;
m_initializedLayout = true; m_initializedLayout = true;
m_layoutCapacity = m_layoutCapacity =
qMax(m_layoutCapacity, layoutCapacityForWidth(m_maxWidth)); qMax(m_layoutCapacity, layoutCapacityForWidth(m_maxWidth));
setImplicitWidth(targetWidthForMaxWidth(m_maxWidth)); setImplicitWidth(targetWidthForMaxWidth(m_maxWidth));
rebuildArrangement(); rebuildArrangement();
@@ -320,6 +353,22 @@ void CarouselView::setDelegateProperties(const QVariantMap& v) {
} }
void CarouselView::setCurrentIndex(int idx) { void CarouselView::setCurrentIndex(int idx) {
if (m_model.isEmpty()) {
m_pendingCurrentIndex = idx;
if (m_currentRealIndex != idx) {
m_currentRealIndex = idx;
notifyCurrentIndexChanged();
}
return;
}
if (!m_completed) {
centerInstantlyOnReal(idx);
return;
}
goToIndex(idx); goToIndex(idx);
} }
@@ -336,7 +385,7 @@ void CarouselView::updateCurrentItem() {
if (item == m_currentItem) return; if (item == m_currentItem) return;
m_currentItem = item; m_currentItem = item;
emit currentItemChanged(); notifyCurrentItemChanged();
} }
void CarouselView::geometryChange(const QRectF& newGeo, const QRectF& oldGeo) { void CarouselView::geometryChange(const QRectF& newGeo, const QRectF& oldGeo) {
@@ -676,15 +725,12 @@ void CarouselView::updateCurrentIndexFromContentX(bool emitPreview) {
if (newReal != m_currentRealIndex) { if (newReal != m_currentRealIndex) {
m_currentRealIndex = newReal; m_currentRealIndex = newReal;
emit currentIndexChanged(); notifyCurrentIndexChanged();
} }
if (emitPreview && newReal != m_previewRealIndex) { if (emitPreview && newReal != m_previewRealIndex) {
m_previewRealIndex = newReal; m_previewRealIndex = newReal;
notifyPreviewIndexChanged(newReal);
if (newReal >= 0) {
emit previewIndexChanged(newReal, m_model.at(newReal));
}
} }
} }
@@ -1029,13 +1075,14 @@ void CarouselView::glideTo(qreal dest) {
cancelAnimations(); cancelAnimations();
m_glideAnim->setDuration(m_glideDuration); {
QSignalBlocker blocker(m_glideAnim);
m_glideAnim->setStartValue(m_contentX); m_glideAnim->setDuration(m_glideDuration);
m_glideAnim->setStartValue(m_contentX);
m_glideAnim->setEndValue(dest); m_glideAnim->setEndValue(dest);
m_glideAnim->start();
m_glideAnim->start(); }
} }
void CarouselView::snapToNearest() { void CarouselView::snapToNearest() {
@@ -1078,10 +1125,6 @@ void CarouselView::decrementCurrentIndex() {
glideTo(contentXForIndex(m_currentVirtualIndex - 1)); glideTo(contentXForIndex(m_currentVirtualIndex - 1));
} }
void CarouselView::jumpToIndex(int realIndex) {
centerInstantlyOnReal(realIndex);
}
void CarouselView::centerInstantlyOnReal(int realIndex) { void CarouselView::centerInstantlyOnReal(int realIndex) {
const int count = m_model.size(); const int count = m_model.size();
@@ -1115,7 +1158,7 @@ void CarouselView::centerInstantlyOnReal(int realIndex) {
if (changed) emit currentIndexChanged(); if (changed) emit currentIndexChanged();
emit previewIndexChanged(realIndex, m_model.at(realIndex)); notifyPreviewIndexChanged(realIndex);
relayout(); relayout();
} }
@@ -1219,12 +1262,16 @@ void CarouselView::mouseReleaseEvent(QMouseEvent* event) {
cancelAnimations(); cancelAnimations();
m_flickAnim->setDuration( {
static_cast<int>(qBound<qreal>(120, duration, 900))); QSignalBlocker blocker(m_flickAnim);
m_flickAnim->setEasingCurve(QEasingCurve::OutQuad);
m_flickAnim->setStartValue(m_contentX); m_flickAnim->setDuration(
m_flickAnim->setEndValue(dest); static_cast<int>(qBound<qreal>(120, duration, 900)));
m_flickAnim->start(); m_flickAnim->setEasingCurve(QEasingCurve::OutQuad);
m_flickAnim->setStartValue(m_contentX);
m_flickAnim->setEndValue(dest);
m_flickAnim->start();
}
event->accept(); event->accept();
} }
+10 -4
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <QQmlParserStatus>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QEasingCurve> #include <QEasingCurve>
#include <QList> #include <QList>
@@ -100,8 +101,6 @@ class CarouselView : public QQuickItem {
Q_INVOKABLE void incrementCurrentIndex(); Q_INVOKABLE void incrementCurrentIndex();
Q_INVOKABLE void decrementCurrentIndex(); Q_INVOKABLE void decrementCurrentIndex();
Q_INVOKABLE void jumpToIndex(int realIndex);
signals: signals:
void delegateChanged(); void delegateChanged();
void modelChanged(); void modelChanged();
@@ -120,10 +119,10 @@ class CarouselView : public QQuickItem {
void previewIndexChanged(int realIndex, QVariant modelData); void previewIndexChanged(int realIndex, QVariant modelData);
protected: protected:
void classBegin() override;
void componentComplete() override;
bool childMouseEventFilter(QQuickItem* item, QEvent* event) override; bool childMouseEventFilter(QQuickItem* item, QEvent* event) override;
void geometryChange(const QRectF& newGeo, const QRectF& oldGeo) override; void geometryChange(const QRectF& newGeo, const QRectF& oldGeo) override;
void mousePressEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override;
@@ -200,6 +199,10 @@ class CarouselView : public QQuickItem {
void addVelocitySample(qint64 t, qreal x); void addVelocitySample(qint64 t, qreal x);
qreal sampledVelocity() const; qreal sampledVelocity() const;
void notifyCurrentIndexChanged();
void notifyCurrentItemChanged();
void notifyPreviewIndexChanged(int realIndex);
QQmlComponent* m_delegate = nullptr; QQmlComponent* m_delegate = nullptr;
QVariantList m_model; QVariantList m_model;
QVariantMap m_delegateProperties; QVariantMap m_delegateProperties;
@@ -242,6 +245,9 @@ class CarouselView : public QQuickItem {
QVariantAnimation* m_flickAnim = nullptr; QVariantAnimation* m_flickAnim = nullptr;
bool m_completed = false;
int m_pendingCurrentIndex = -1;
bool m_initializedLayout = false; bool m_initializedLayout = false;
bool m_relayoutQueued = false; bool m_relayoutQueued = false;
}; };