tidy&format(all): all files formatted and relevant warnings resolved
C++ / build (pull_request) Failing after 15s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 28s
Python / lint-format (pull_request) Successful in 45s
Python / test (pull_request) Successful in 38s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m45s
C++ / build (pull_request) Failing after 15s
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 28s
Python / lint-format (pull_request) Successful in 45s
Python / test (pull_request) Successful in 38s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m45s
This commit is contained in:
@@ -3,11 +3,10 @@
|
||||
namespace ZShell::components {
|
||||
|
||||
ButtonRow::ButtonRow(QQuickItem* parent)
|
||||
: QQuickItem(parent)
|
||||
, m_dirty(false)
|
||||
, m_spacing(0.0) {
|
||||
: QQuickItem(parent), m_dirty(false), m_spacing(0.0) {
|
||||
setFlag(QQuickItem::ItemHasContents, true);
|
||||
QObject::connect(this, &ButtonRow::widthChanged, this, &ButtonRow::invalidate);
|
||||
QObject::connect(
|
||||
this, &ButtonRow::widthChanged, this, &ButtonRow::invalidate);
|
||||
}
|
||||
|
||||
qreal ButtonRow::spacing() const {
|
||||
@@ -15,8 +14,7 @@ qreal ButtonRow::spacing() const {
|
||||
}
|
||||
|
||||
void ButtonRow::setSpacing(qreal spacing) {
|
||||
if (qFuzzyCompare(m_spacing + 1.0, spacing + 1.0))
|
||||
return;
|
||||
if (qFuzzyCompare(m_spacing + 1.0, spacing + 1.0)) return;
|
||||
|
||||
m_spacing = spacing;
|
||||
emit spacingChanged();
|
||||
@@ -24,18 +22,33 @@ void ButtonRow::setSpacing(qreal spacing) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void ButtonRow::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData& data) {
|
||||
void ButtonRow::itemChange(
|
||||
QQuickItem::ItemChange change, const QQuickItem::ItemChangeData& data) {
|
||||
if (change == QQuickItem::ItemChildAddedChange) {
|
||||
auto* const child = data.item;
|
||||
QObject::connect(child, &QQuickItem::implicitWidthChanged, this, &ButtonRow::invalidate);
|
||||
QObject::connect(child, &QQuickItem::implicitHeightChanged, this, &ButtonRow::invalidate);
|
||||
QObject::connect(child, &QQuickItem::visibleChanged, this, &ButtonRow::invalidate);
|
||||
QObject::connect(
|
||||
child,
|
||||
&QQuickItem::implicitWidthChanged,
|
||||
this,
|
||||
&ButtonRow::invalidate);
|
||||
QObject::connect(
|
||||
child,
|
||||
&QQuickItem::implicitHeightChanged,
|
||||
this,
|
||||
&ButtonRow::invalidate);
|
||||
QObject::connect(
|
||||
child, &QQuickItem::visibleChanged, this, &ButtonRow::invalidate);
|
||||
|
||||
const auto* childMeta = child->metaObject();
|
||||
const auto morphSignalIdx = childMeta->indexOfSignal("shapeMorphExpansionChanged()");
|
||||
const auto morphSignalIdx =
|
||||
childMeta->indexOfSignal("shapeMorphExpansionChanged()");
|
||||
if (morphSignalIdx != -1)
|
||||
QObject::connect(child, childMeta->method(morphSignalIdx), this,
|
||||
metaObject()->method(metaObject()->indexOfSlot("invalidate()")));
|
||||
QObject::connect(
|
||||
child,
|
||||
childMeta->method(morphSignalIdx),
|
||||
this,
|
||||
metaObject()->method(
|
||||
metaObject()->indexOfSlot("invalidate()")));
|
||||
|
||||
invalidate();
|
||||
} else if (change == QQuickItem::ItemChildRemovedChange) {
|
||||
@@ -77,8 +90,7 @@ void ButtonRow::relayout() {
|
||||
maxHeight = qMax(maxHeight, child->implicitHeight());
|
||||
|
||||
const auto prop = child->property("fillWidth");
|
||||
if (!prop.isValid())
|
||||
continue;
|
||||
if (!prop.isValid()) continue;
|
||||
|
||||
if (prop.toBool()) {
|
||||
fillWidthCount++;
|
||||
@@ -88,15 +100,17 @@ void ButtonRow::relayout() {
|
||||
}
|
||||
}
|
||||
|
||||
if (fillWidthCount == 0)
|
||||
fillWidthCount = 1; // Avoid divide by 0
|
||||
if (fillWidthCount == 0) fillWidthCount = 1; // Avoid divide by 0
|
||||
|
||||
const auto widthPerItem = (width() - totalSpacing - reservedWidth) / static_cast<qreal>(fillWidthCount);
|
||||
const auto widthPerItem = (width() - totalSpacing - reservedWidth) /
|
||||
static_cast<qreal>(fillWidthCount);
|
||||
|
||||
QList<qreal> baseWidths;
|
||||
baseWidths.reserve(nChildren);
|
||||
for (auto* const child : validChildren)
|
||||
baseWidths.append(child->property("fillWidth").toBool() ? widthPerItem : child->implicitWidth());
|
||||
baseWidths.append(
|
||||
child->property("fillWidth").toBool() ? widthPerItem
|
||||
: child->implicitWidth());
|
||||
|
||||
qreal accX = 0;
|
||||
for (int i = 0; i < nChildren; ++i) {
|
||||
@@ -108,12 +122,12 @@ void ButtonRow::relayout() {
|
||||
// clang-format on
|
||||
|
||||
// Items at edges push by full amount, items in middle push by half
|
||||
if (i > 1)
|
||||
prevExtraWidth /= 2;
|
||||
if (i < nChildren - 2)
|
||||
nextExtraWidth /= 2;
|
||||
if (i > 1) prevExtraWidth /= 2;
|
||||
if (i < nChildren - 2) nextExtraWidth /= 2;
|
||||
|
||||
child->setWidth(baseWidths[i] + getMorphExpansion(child) - prevExtraWidth - nextExtraWidth);
|
||||
child->setWidth(
|
||||
baseWidths[i] + getMorphExpansion(child) - prevExtraWidth -
|
||||
nextExtraWidth);
|
||||
child->setHeight(maxHeight);
|
||||
|
||||
child->setX(accX);
|
||||
|
||||
@@ -5,33 +5,34 @@
|
||||
namespace ZShell::components {
|
||||
|
||||
class ButtonRow : public QQuickItem {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
|
||||
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
|
||||
|
||||
public:
|
||||
explicit ButtonRow(QQuickItem* parent = nullptr);
|
||||
public:
|
||||
explicit ButtonRow(QQuickItem* parent = nullptr);
|
||||
|
||||
[[nodiscard]] qreal spacing() const;
|
||||
void setSpacing(qreal spacing);
|
||||
[[nodiscard]] qreal spacing() const;
|
||||
void setSpacing(qreal spacing);
|
||||
|
||||
signals:
|
||||
void spacingChanged();
|
||||
signals:
|
||||
void spacingChanged();
|
||||
|
||||
protected:
|
||||
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData& data) override;
|
||||
void updatePolish() override;
|
||||
protected:
|
||||
void itemChange(
|
||||
QQuickItem::ItemChange change,
|
||||
const QQuickItem::ItemChangeData& data) override;
|
||||
void updatePolish() override;
|
||||
|
||||
private slots:
|
||||
void invalidate();
|
||||
private slots:
|
||||
void invalidate();
|
||||
|
||||
private:
|
||||
void relayout();
|
||||
static qreal getMorphExpansion(const QQuickItem* item);
|
||||
void relayout();
|
||||
static qreal getMorphExpansion(const QQuickItem* item);
|
||||
|
||||
bool m_dirty;
|
||||
qreal m_spacing;
|
||||
bool m_dirty;
|
||||
qreal m_spacing;
|
||||
};
|
||||
|
||||
} // namespace ZShell::components
|
||||
|
||||
@@ -21,8 +21,7 @@ qreal LazyListViewAttached::preferredHeight() const {
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setPreferredHeight(qreal height) {
|
||||
if (qFuzzyCompare(m_preferredHeight + 1.0, height + 1.0))
|
||||
return;
|
||||
if (qFuzzyCompare(m_preferredHeight + 1.0, height + 1.0)) return;
|
||||
m_preferredHeight = height;
|
||||
emit preferredHeightChanged();
|
||||
}
|
||||
@@ -32,8 +31,7 @@ qreal LazyListViewAttached::visibleHeight() const {
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setVisibleHeight(qreal height) {
|
||||
if (qFuzzyCompare(m_visibleHeight + 1.0, height + 1.0))
|
||||
return;
|
||||
if (qFuzzyCompare(m_visibleHeight + 1.0, height + 1.0)) return;
|
||||
m_visibleHeight = height;
|
||||
emit visibleHeightChanged();
|
||||
}
|
||||
@@ -43,8 +41,7 @@ bool LazyListViewAttached::ready() const {
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setReady(bool ready) {
|
||||
if (m_ready == ready)
|
||||
return;
|
||||
if (m_ready == ready) return;
|
||||
m_ready = ready;
|
||||
emit readyChanged();
|
||||
}
|
||||
@@ -54,8 +51,7 @@ bool LazyListViewAttached::adding() const {
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setAdding(bool adding) {
|
||||
if (m_adding == adding)
|
||||
return;
|
||||
if (m_adding == adding) return;
|
||||
m_adding = adding;
|
||||
emit addingChanged();
|
||||
}
|
||||
@@ -65,8 +61,7 @@ bool LazyListViewAttached::removing() const {
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setRemoving(bool removing) {
|
||||
if (m_removing == removing)
|
||||
return;
|
||||
if (m_removing == removing) return;
|
||||
m_removing = removing;
|
||||
emit removingChanged();
|
||||
}
|
||||
@@ -76,8 +71,7 @@ bool LazyListViewAttached::trackViewport() const {
|
||||
}
|
||||
|
||||
void LazyListViewAttached::setTrackViewport(bool track) {
|
||||
if (m_trackViewport == track)
|
||||
return;
|
||||
if (m_trackViewport == track) return;
|
||||
m_trackViewport = track;
|
||||
emit trackViewportChanged();
|
||||
}
|
||||
@@ -102,16 +96,13 @@ QAbstractItemModel* LazyListView::model() const {
|
||||
}
|
||||
|
||||
void LazyListView::setModel(QAbstractItemModel* model) {
|
||||
if (m_model == model)
|
||||
return;
|
||||
if (m_model == model) return;
|
||||
|
||||
if (m_model)
|
||||
disconnectModel();
|
||||
if (m_model) disconnectModel();
|
||||
|
||||
m_model = model;
|
||||
|
||||
if (m_model)
|
||||
connectModel();
|
||||
if (m_model) connectModel();
|
||||
|
||||
resetContent();
|
||||
emit modelChanged();
|
||||
@@ -122,8 +113,7 @@ QQmlComponent* LazyListView::delegate() const {
|
||||
}
|
||||
|
||||
void LazyListView::setDelegate(QQmlComponent* delegate) {
|
||||
if (m_delegate == delegate)
|
||||
return;
|
||||
if (m_delegate == delegate) return;
|
||||
|
||||
m_delegate = delegate;
|
||||
resetContent();
|
||||
@@ -135,8 +125,7 @@ qreal LazyListView::spacing() const {
|
||||
}
|
||||
|
||||
void LazyListView::setSpacing(qreal spacing) {
|
||||
if (qFuzzyCompare(m_spacing, spacing))
|
||||
return;
|
||||
if (qFuzzyCompare(m_spacing, spacing)) return;
|
||||
m_spacing = spacing;
|
||||
emit spacingChanged();
|
||||
polish();
|
||||
@@ -155,8 +144,7 @@ qreal LazyListView::contentY() const {
|
||||
}
|
||||
|
||||
void LazyListView::setContentY(qreal contentY) {
|
||||
if (qFuzzyCompare(m_contentY, contentY))
|
||||
return;
|
||||
if (qFuzzyCompare(m_contentY, contentY)) return;
|
||||
m_contentY = contentY;
|
||||
emit contentYChanged();
|
||||
polish();
|
||||
@@ -167,12 +155,10 @@ QRectF LazyListView::viewport() const {
|
||||
}
|
||||
|
||||
void LazyListView::setViewport(const QRectF& viewport) {
|
||||
if (m_viewport == viewport)
|
||||
return;
|
||||
if (m_viewport == viewport) return;
|
||||
m_viewport = viewport;
|
||||
emit viewportChanged();
|
||||
if (m_useCustomViewport)
|
||||
polish();
|
||||
if (m_useCustomViewport) polish();
|
||||
}
|
||||
|
||||
bool LazyListView::useCustomViewport() const {
|
||||
@@ -180,8 +166,7 @@ bool LazyListView::useCustomViewport() const {
|
||||
}
|
||||
|
||||
void LazyListView::setUseCustomViewport(bool use) {
|
||||
if (m_useCustomViewport == use)
|
||||
return;
|
||||
if (m_useCustomViewport == use) return;
|
||||
m_useCustomViewport = use;
|
||||
emit useCustomViewportChanged();
|
||||
polish();
|
||||
@@ -192,8 +177,7 @@ qreal LazyListView::cacheBuffer() const {
|
||||
}
|
||||
|
||||
void LazyListView::setCacheBuffer(qreal buffer) {
|
||||
if (qFuzzyCompare(m_cacheBuffer, buffer))
|
||||
return;
|
||||
if (qFuzzyCompare(m_cacheBuffer, buffer)) return;
|
||||
m_cacheBuffer = buffer;
|
||||
emit cacheBufferChanged();
|
||||
polish();
|
||||
@@ -204,8 +188,7 @@ qreal LazyListView::estimatedHeight() const {
|
||||
}
|
||||
|
||||
void LazyListView::setEstimatedHeight(qreal height) {
|
||||
if (qFuzzyCompare(m_estimatedHeight, height))
|
||||
return;
|
||||
if (qFuzzyCompare(m_estimatedHeight, height)) return;
|
||||
m_estimatedHeight = height;
|
||||
emit estimatedHeightChanged();
|
||||
polish();
|
||||
@@ -216,17 +199,14 @@ bool LazyListView::asynchronous() const {
|
||||
}
|
||||
|
||||
void LazyListView::setAsynchronous(bool async) {
|
||||
if (m_asynchronous == async)
|
||||
return;
|
||||
if (m_asynchronous == async) return;
|
||||
m_asynchronous = async;
|
||||
emit asynchronousChanged();
|
||||
}
|
||||
|
||||
qreal LazyListView::effectiveEstimatedHeight() const {
|
||||
if (m_estimatedHeight >= 0)
|
||||
return m_estimatedHeight;
|
||||
if (m_knownHeightCount > 0)
|
||||
return m_knownHeightSum / m_knownHeightCount;
|
||||
if (m_estimatedHeight >= 0) return m_estimatedHeight;
|
||||
if (m_knownHeightCount > 0) return m_knownHeightSum / m_knownHeightCount;
|
||||
return 40;
|
||||
}
|
||||
|
||||
@@ -241,8 +221,7 @@ void LazyListView::untrackHeight(qreal height) {
|
||||
}
|
||||
|
||||
qreal LazyListView::delegateHeight(QQuickItem* item) {
|
||||
if (!item)
|
||||
return 0;
|
||||
if (!item) return 0;
|
||||
|
||||
auto* attached = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||
@@ -253,14 +232,12 @@ qreal LazyListView::delegateHeight(QQuickItem* item) {
|
||||
}
|
||||
|
||||
qreal LazyListView::delegateVisibleHeight(QQuickItem* item) {
|
||||
if (!item)
|
||||
return 0;
|
||||
if (!item) return 0;
|
||||
|
||||
auto* attached = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||
if (attached) {
|
||||
if (attached->visibleHeight() >= 0)
|
||||
return attached->visibleHeight();
|
||||
if (attached->visibleHeight() >= 0) return attached->visibleHeight();
|
||||
if (attached->preferredHeight() >= 0)
|
||||
return attached->preferredHeight();
|
||||
}
|
||||
@@ -269,8 +246,7 @@ qreal LazyListView::delegateVisibleHeight(QQuickItem* item) {
|
||||
}
|
||||
|
||||
bool LazyListView::isDelegateReady(QQuickItem* item) {
|
||||
if (!item)
|
||||
return false;
|
||||
if (!item) return false;
|
||||
auto* att = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||
return !att || att->ready();
|
||||
@@ -281,8 +257,7 @@ int LazyListView::removeDuration() const {
|
||||
}
|
||||
|
||||
void LazyListView::setRemoveDuration(int duration) {
|
||||
if (m_removeDuration == duration)
|
||||
return;
|
||||
if (m_removeDuration == duration) return;
|
||||
m_removeDuration = duration;
|
||||
emit removeDurationChanged();
|
||||
}
|
||||
@@ -292,8 +267,7 @@ int LazyListView::readyDelay() const {
|
||||
}
|
||||
|
||||
void LazyListView::setReadyDelay(int delay) {
|
||||
if (m_readyDelay == delay)
|
||||
return;
|
||||
if (m_readyDelay == delay) return;
|
||||
m_readyDelay = delay;
|
||||
emit readyDelayChanged();
|
||||
}
|
||||
@@ -308,17 +282,15 @@ void LazyListView::componentComplete() {
|
||||
resetContent();
|
||||
}
|
||||
|
||||
void LazyListView::geometryChange(const QRectF& newGeometry,
|
||||
const QRectF& oldGeometry) {
|
||||
void LazyListView::geometryChange(
|
||||
const QRectF& newGeometry, const QRectF& oldGeometry) {
|
||||
QQuickItem::geometryChange(newGeometry, oldGeometry);
|
||||
|
||||
if (!m_componentComplete)
|
||||
return;
|
||||
if (!m_componentComplete) return;
|
||||
|
||||
if (!qFuzzyCompare(newGeometry.width(), oldGeometry.width())) {
|
||||
for (auto& entry : m_delegates) {
|
||||
if (entry.item)
|
||||
entry.item->setWidth(newGeometry.width());
|
||||
if (entry.item) entry.item->setWidth(newGeometry.width());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,8 +298,7 @@ void LazyListView::geometryChange(const QRectF& newGeometry,
|
||||
}
|
||||
|
||||
void LazyListView::updatePolish() {
|
||||
if (!m_componentComplete || !m_model || !m_delegate)
|
||||
return;
|
||||
if (!m_componentComplete || !m_model || !m_delegate) return;
|
||||
|
||||
// Flush pending inserts — make items visible and clear the adding flag
|
||||
// so enter animations begin. When readyDelay > 0 the entire insert is
|
||||
@@ -335,9 +306,9 @@ void LazyListView::updatePolish() {
|
||||
|
||||
// Collect pending indices first — avoids scanning the entire hash each frame
|
||||
QList<int> pendingIndices;
|
||||
for (auto it = m_delegates.constBegin(); it != m_delegates.constEnd(); ++it) {
|
||||
if (it->pendingInsert && it->item)
|
||||
pendingIndices.append(it.key());
|
||||
for (auto it = m_delegates.constBegin(); it != m_delegates.constEnd();
|
||||
++it) {
|
||||
if (it->pendingInsert && it->item) pendingIndices.append(it.key());
|
||||
}
|
||||
|
||||
for (int pendingIdx : pendingIndices) {
|
||||
@@ -349,8 +320,7 @@ void LazyListView::updatePolish() {
|
||||
auto* item = entry.item;
|
||||
QTimer::singleShot(m_readyDelay, this, [this, item] {
|
||||
auto indexIt = m_itemToIndex.find(item);
|
||||
if (indexIt == m_itemToIndex.end())
|
||||
return;
|
||||
if (indexIt == m_itemToIndex.end()) return;
|
||||
const int idx = indexIt.value();
|
||||
auto it = m_delegates.find(idx);
|
||||
if (it == m_delegates.end() || it->item != item ||
|
||||
@@ -375,14 +345,11 @@ void LazyListView::updatePolish() {
|
||||
? m_layout[i].height
|
||||
: effectiveEstimatedHeight();
|
||||
if (h > 0) {
|
||||
if (hasVisItem)
|
||||
visualY += m_spacing;
|
||||
if (hasVisItem) visualY += m_spacing;
|
||||
hasVisItem = true;
|
||||
}
|
||||
if (i == idx)
|
||||
break;
|
||||
if (h > 0)
|
||||
visualY += h;
|
||||
if (i == idx) break;
|
||||
if (h > 0) visualY += h;
|
||||
}
|
||||
item->setY(visualY - m_contentY);
|
||||
}
|
||||
@@ -397,8 +364,8 @@ void LazyListView::updatePolish() {
|
||||
|
||||
// Animate from visual position to layout position
|
||||
if (idx >= 0 && idx < static_cast<int>(m_layout.size()))
|
||||
item->setProperty("y",
|
||||
m_layout[idx].targetY - m_contentY);
|
||||
item->setProperty(
|
||||
"y", m_layout[idx].targetY - m_contentY);
|
||||
|
||||
polish();
|
||||
});
|
||||
@@ -432,8 +399,7 @@ void LazyListView::updatePolish() {
|
||||
continue;
|
||||
|
||||
const int idx = entry.modelIndex;
|
||||
if (idx < 0 || idx >= layoutSize)
|
||||
continue;
|
||||
if (idx < 0 || idx >= layoutSize) continue;
|
||||
|
||||
if (m_layout[idx].heightKnown && qFuzzyIsNull(m_layout[idx].height))
|
||||
continue;
|
||||
@@ -444,8 +410,6 @@ void LazyListView::updatePolish() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Layout Engine ---
|
||||
|
||||
void LazyListView::relayout() {
|
||||
// Layout positioning uses preferredHeight (final/non-animated).
|
||||
// Only add spacing between items with non-zero height.
|
||||
@@ -455,8 +419,7 @@ void LazyListView::relayout() {
|
||||
const qreal layoutH = record.heightKnown ? record.height
|
||||
: effectiveEstimatedHeight();
|
||||
if (layoutH > 0) {
|
||||
if (hasLayoutItem)
|
||||
y += m_spacing;
|
||||
if (hasLayoutItem) y += m_spacing;
|
||||
hasLayoutItem = true;
|
||||
record.targetY = y;
|
||||
y += layoutH;
|
||||
@@ -483,8 +446,7 @@ void LazyListView::relayout() {
|
||||
h = m_layout[i].heightKnown ? m_layout[i].height
|
||||
: effectiveEstimatedHeight();
|
||||
if (h > 0) {
|
||||
if (hasVisItem)
|
||||
visY += m_spacing;
|
||||
if (hasVisItem) visY += m_spacing;
|
||||
hasVisItem = true;
|
||||
visY += h;
|
||||
}
|
||||
@@ -492,11 +454,9 @@ void LazyListView::relayout() {
|
||||
|
||||
// Account for dying delegates still visually present
|
||||
for (const auto& dying : std::as_const(m_dyingDelegates)) {
|
||||
if (!dying.item)
|
||||
continue;
|
||||
if (!dying.item) continue;
|
||||
const qreal dyingH = delegateVisibleHeight(dying.item);
|
||||
if (dyingH > 0)
|
||||
visY = std::max(visY, dying.item->y() + dyingH);
|
||||
if (dyingH > 0) visY = std::max(visY, dying.item->y() + dyingH);
|
||||
}
|
||||
|
||||
if (!qFuzzyCompare(m_contentHeight + 1.0, visY + 1.0)) {
|
||||
@@ -519,8 +479,7 @@ QRectF LazyListView::effectiveViewport() const {
|
||||
if (!m_useCustomViewport && m_layoutHeight > 0) {
|
||||
const qreal top = std::min(vp.y(), m_layoutHeight);
|
||||
const qreal bottom = std::max(vp.y() + vp.height(), 0.0);
|
||||
if (bottom > top)
|
||||
vp = QRectF(vp.x(), top, vp.width(), bottom - top);
|
||||
if (bottom > top) vp = QRectF(vp.x(), top, vp.width(), bottom - top);
|
||||
}
|
||||
|
||||
vp.adjust(0, -m_cacheBuffer, 0, m_cacheBuffer);
|
||||
@@ -541,12 +500,10 @@ QRectF LazyListView::effectiveViewport() const {
|
||||
}
|
||||
|
||||
std::pair<int, int> LazyListView::computeVisibleRange() const {
|
||||
if (m_layout.isEmpty())
|
||||
return {-1, -1};
|
||||
if (m_layout.isEmpty()) return {-1, -1};
|
||||
|
||||
const auto vp = effectiveViewport();
|
||||
if (vp.isEmpty())
|
||||
return {-1, -1};
|
||||
if (vp.isEmpty()) return {-1, -1};
|
||||
|
||||
const qreal vpTop = vp.y();
|
||||
const qreal vpBottom = vp.y() + vp.height();
|
||||
@@ -571,22 +528,18 @@ std::pair<int, int> LazyListView::computeVisibleRange() const {
|
||||
}
|
||||
}
|
||||
|
||||
if (first >= static_cast<int>(m_layout.size()))
|
||||
return {-1, -1};
|
||||
if (first >= static_cast<int>(m_layout.size())) return {-1, -1};
|
||||
|
||||
// Linear scan for last visible item
|
||||
int last = first;
|
||||
for (int i = first; i < static_cast<int>(m_layout.size()); ++i) {
|
||||
if (m_layout[i].targetY > vpBottom)
|
||||
break;
|
||||
if (m_layout[i].targetY > vpBottom) break;
|
||||
last = i;
|
||||
}
|
||||
|
||||
return {first, last};
|
||||
}
|
||||
|
||||
// --- Delegate Lifecycle ---
|
||||
|
||||
void LazyListView::syncDelegates() {
|
||||
const auto [first, last] = computeVisibleRange();
|
||||
|
||||
@@ -601,8 +554,7 @@ void LazyListView::syncDelegates() {
|
||||
const auto vp = effectiveViewport();
|
||||
QList<int> toRemove;
|
||||
for (auto it = m_delegates.begin(); it != m_delegates.end(); ++it) {
|
||||
if (visibleIndices.contains(it.key()))
|
||||
continue;
|
||||
if (visibleIndices.contains(it.key())) continue;
|
||||
if (!it->item || vp.isEmpty()) {
|
||||
toRemove.append(it.key());
|
||||
continue;
|
||||
@@ -622,11 +574,9 @@ void LazyListView::syncDelegates() {
|
||||
std::min(destroyBudget, static_cast<int>(toRemove.size())));
|
||||
int destroyed = 0;
|
||||
for (int idx : toRemove) {
|
||||
if (destroyed >= destroyBudget)
|
||||
break;
|
||||
if (destroyed >= destroyBudget) break;
|
||||
auto entry = m_delegates.take(idx);
|
||||
if (entry.item)
|
||||
m_itemToIndex.remove(entry.item);
|
||||
if (entry.item) m_itemToIndex.remove(entry.item);
|
||||
removedEntries.append(std::move(entry));
|
||||
++destroyed;
|
||||
}
|
||||
@@ -637,8 +587,7 @@ void LazyListView::syncDelegates() {
|
||||
QList<int> toCreate;
|
||||
if (first >= 0) {
|
||||
for (int i = first; i <= last; ++i) {
|
||||
if (!m_delegates.contains(i))
|
||||
toCreate.append(i);
|
||||
if (!m_delegates.contains(i)) toCreate.append(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,8 +596,7 @@ void LazyListView::syncDelegates() {
|
||||
: static_cast<int>(toCreate.size());
|
||||
int created = 0;
|
||||
for (int i : toCreate) {
|
||||
if (created >= createBudget)
|
||||
break;
|
||||
if (created >= createBudget) break;
|
||||
|
||||
auto entry = createDelegate(i);
|
||||
if (entry.item) {
|
||||
@@ -674,25 +622,21 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||
DelegateEntry entry;
|
||||
entry.modelIndex = modelIndex;
|
||||
|
||||
if (!m_delegate || !m_model)
|
||||
return entry;
|
||||
if (!m_delegate || !m_model) return entry;
|
||||
|
||||
const auto roleNames = m_model->roleNames();
|
||||
|
||||
// Use the delegate component's creation context for beginCreate
|
||||
// so bound components (pragma ComponentBehavior: Bound) are accepted.
|
||||
auto* compContext = m_delegate->creationContext();
|
||||
if (!compContext)
|
||||
compContext = qmlContext(this);
|
||||
if (!compContext)
|
||||
return entry;
|
||||
if (!compContext) compContext = qmlContext(this);
|
||||
if (!compContext) return entry;
|
||||
|
||||
auto* obj = m_delegate->beginCreate(compContext);
|
||||
entry.item = qobject_cast<QQuickItem*>(obj);
|
||||
|
||||
if (!entry.item) {
|
||||
if (obj)
|
||||
m_delegate->completeCreate();
|
||||
if (obj) m_delegate->completeCreate();
|
||||
delete obj;
|
||||
return entry;
|
||||
}
|
||||
@@ -705,16 +649,15 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||
for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
|
||||
const auto name = QString::fromUtf8(it.value());
|
||||
initialProps.insert(name, m_model->data(index, it.key()));
|
||||
if (name == QStringLiteral("modelData"))
|
||||
hasModelData = true;
|
||||
if (name == QStringLiteral("modelData")) hasModelData = true;
|
||||
}
|
||||
initialProps.insert(QStringLiteral("index"), modelIndex);
|
||||
|
||||
if (!hasModelData) {
|
||||
const auto role = roleNames.isEmpty() ? Qt::DisplayRole
|
||||
: roleNames.constBegin().key();
|
||||
initialProps.insert(QStringLiteral("modelData"),
|
||||
m_model->data(index, role));
|
||||
initialProps.insert(
|
||||
QStringLiteral("modelData"), m_model->data(index, role));
|
||||
}
|
||||
|
||||
m_delegate->setInitialProperties(entry.item, initialProps);
|
||||
@@ -728,8 +671,7 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||
m_layout[modelIndex].isNew) {
|
||||
auto* addingAttached = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(entry.item, true));
|
||||
if (addingAttached)
|
||||
addingAttached->setAdding(true);
|
||||
if (addingAttached) addingAttached->setAdding(true);
|
||||
}
|
||||
|
||||
m_delegate->completeCreate();
|
||||
@@ -740,15 +682,12 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||
// Height-change handler — uses m_itemToIndex for O(1) lookup.
|
||||
// Ignored while the delegate is not yet ready.
|
||||
auto onHeightChanged = [this, item = entry.item] {
|
||||
if (!isDelegateReady(item))
|
||||
return;
|
||||
if (!isDelegateReady(item)) return;
|
||||
auto indexIt = m_itemToIndex.find(item);
|
||||
if (indexIt == m_itemToIndex.end())
|
||||
return;
|
||||
if (indexIt == m_itemToIndex.end()) return;
|
||||
const int idx = indexIt.value();
|
||||
auto delegateIt = m_delegates.find(idx);
|
||||
if (delegateIt == m_delegates.end() || delegateIt->item != item)
|
||||
return;
|
||||
if (delegateIt == m_delegates.end() || delegateIt->item != item) return;
|
||||
const qreal h = delegateHeight(item);
|
||||
if (idx < static_cast<int>(m_layout.size()) &&
|
||||
!qFuzzyCompare(m_layout[idx].height + 1.0, h + 1.0)) {
|
||||
@@ -756,8 +695,7 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||
const bool wasKnown = m_layout[idx].heightKnown;
|
||||
m_layout[idx].height = h;
|
||||
m_layout[idx].heightKnown = true;
|
||||
if (wasKnown)
|
||||
untrackHeight(oldH);
|
||||
if (wasKnown) untrackHeight(oldH);
|
||||
trackHeight(h);
|
||||
|
||||
// If this tracked item is above the viewport, emit a
|
||||
@@ -785,58 +723,56 @@ LazyListView::DelegateEntry LazyListView::createDelegate(int modelIndex) {
|
||||
};
|
||||
|
||||
// Watch implicitHeight as fallback
|
||||
connect(entry.item,
|
||||
&QQuickItem::implicitHeightChanged,
|
||||
this,
|
||||
onHeightChanged);
|
||||
connect(
|
||||
entry.item, &QQuickItem::implicitHeightChanged, this, onHeightChanged);
|
||||
|
||||
// Watch attached properties if the delegate uses them
|
||||
auto* attached = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(entry.item, false));
|
||||
if (attached) {
|
||||
connect(attached,
|
||||
&LazyListViewAttached::preferredHeightChanged,
|
||||
this,
|
||||
onHeightChanged);
|
||||
connect(attached,
|
||||
&LazyListViewAttached::visibleHeightChanged,
|
||||
this,
|
||||
[this] { polish(); });
|
||||
connect(attached,
|
||||
&LazyListViewAttached::readyChanged,
|
||||
this,
|
||||
[this, item = entry.item] {
|
||||
auto indexIt = m_itemToIndex.find(item);
|
||||
if (indexIt == m_itemToIndex.end())
|
||||
return;
|
||||
const int idx = indexIt.value();
|
||||
if (idx >= static_cast<int>(m_layout.size()))
|
||||
return;
|
||||
auto* att = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||
if (!att || !att->ready())
|
||||
return;
|
||||
connect(
|
||||
attached,
|
||||
&LazyListViewAttached::preferredHeightChanged,
|
||||
this,
|
||||
onHeightChanged);
|
||||
connect(
|
||||
attached,
|
||||
&LazyListViewAttached::visibleHeightChanged,
|
||||
this,
|
||||
[this] { polish(); });
|
||||
connect(
|
||||
attached,
|
||||
&LazyListViewAttached::readyChanged,
|
||||
this,
|
||||
[this, item = entry.item] {
|
||||
auto indexIt = m_itemToIndex.find(item);
|
||||
if (indexIt == m_itemToIndex.end()) return;
|
||||
const int idx = indexIt.value();
|
||||
if (idx >= static_cast<int>(m_layout.size())) return;
|
||||
auto* att = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(item, false));
|
||||
if (!att || !att->ready()) return;
|
||||
|
||||
const qreal h = delegateHeight(item);
|
||||
const qreal oldLayoutH = m_layout[idx].heightKnown
|
||||
? m_layout[idx].height
|
||||
: effectiveEstimatedHeight();
|
||||
if (m_layout[idx].heightKnown)
|
||||
untrackHeight(m_layout[idx].height);
|
||||
m_layout[idx].height = h;
|
||||
m_layout[idx].heightKnown = true;
|
||||
trackHeight(h);
|
||||
const qreal h = delegateHeight(item);
|
||||
const qreal oldLayoutH = m_layout[idx].heightKnown
|
||||
? m_layout[idx].height
|
||||
: effectiveEstimatedHeight();
|
||||
if (m_layout[idx].heightKnown)
|
||||
untrackHeight(m_layout[idx].height);
|
||||
m_layout[idx].height = h;
|
||||
m_layout[idx].heightKnown = true;
|
||||
trackHeight(h);
|
||||
|
||||
if (att->trackViewport() &&
|
||||
!qFuzzyCompare(h + 1.0, oldLayoutH + 1.0)) {
|
||||
const qreal vpTop = m_useCustomViewport ? m_viewport.y()
|
||||
: m_contentY;
|
||||
if (m_layout[idx].targetY < vpTop)
|
||||
emit viewportAdjustNeeded(h - oldLayoutH);
|
||||
}
|
||||
if (att->trackViewport() &&
|
||||
!qFuzzyCompare(h + 1.0, oldLayoutH + 1.0)) {
|
||||
const qreal vpTop = m_useCustomViewport ? m_viewport.y()
|
||||
: m_contentY;
|
||||
if (m_layout[idx].targetY < vpTop)
|
||||
emit viewportAdjustNeeded(h - oldLayoutH);
|
||||
}
|
||||
|
||||
polish();
|
||||
});
|
||||
polish();
|
||||
});
|
||||
}
|
||||
|
||||
return entry;
|
||||
@@ -852,8 +788,7 @@ void LazyListView::destroyDelegate(DelegateEntry& entry) {
|
||||
}
|
||||
|
||||
void LazyListView::updateDelegateData(DelegateEntry& entry) {
|
||||
if (!m_model || !entry.item)
|
||||
return;
|
||||
if (!m_model || !entry.item) return;
|
||||
|
||||
const auto roleNames = m_model->roleNames();
|
||||
const auto index = m_model->index(entry.modelIndex, 0);
|
||||
@@ -861,10 +796,9 @@ void LazyListView::updateDelegateData(DelegateEntry& entry) {
|
||||
|
||||
for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
|
||||
const auto name = QString::fromUtf8(it.value());
|
||||
entry.item->setProperty(name.toUtf8().constData(),
|
||||
m_model->data(index, it.key()));
|
||||
if (name == QStringLiteral("modelData"))
|
||||
hasModelData = true;
|
||||
entry.item->setProperty(
|
||||
name.toUtf8().constData(), m_model->data(index, it.key()));
|
||||
if (name == QStringLiteral("modelData")) hasModelData = true;
|
||||
}
|
||||
|
||||
entry.item->setProperty("index", entry.modelIndex);
|
||||
@@ -876,53 +810,58 @@ void LazyListView::updateDelegateData(DelegateEntry& entry) {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Model Connection ---
|
||||
|
||||
void LazyListView::connectModel() {
|
||||
if (!m_model)
|
||||
return;
|
||||
if (!m_model) return;
|
||||
|
||||
m_modelConnections = {
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::rowsInserted,
|
||||
this,
|
||||
&LazyListView::onRowsInserted),
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::rowsAboutToBeRemoved,
|
||||
this,
|
||||
&LazyListView::onRowsAboutToBeRemoved),
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::rowsRemoved,
|
||||
this,
|
||||
&LazyListView::onRowsRemoved),
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::rowsMoved,
|
||||
this,
|
||||
&LazyListView::onRowsMoved),
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::dataChanged,
|
||||
this,
|
||||
&LazyListView::onDataChanged),
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::modelReset,
|
||||
this,
|
||||
&LazyListView::onModelReset),
|
||||
connect(m_model,
|
||||
&QAbstractItemModel::layoutChanged,
|
||||
this,
|
||||
[this] {
|
||||
for (auto& entry : m_delegates)
|
||||
updateDelegateData(entry);
|
||||
polish();
|
||||
}),
|
||||
connect(m_model,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
[this] {
|
||||
m_model = nullptr;
|
||||
resetContent();
|
||||
emit modelChanged();
|
||||
}),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::rowsInserted,
|
||||
this,
|
||||
&LazyListView::onRowsInserted),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::rowsAboutToBeRemoved,
|
||||
this,
|
||||
&LazyListView::onRowsAboutToBeRemoved),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::rowsRemoved,
|
||||
this,
|
||||
&LazyListView::onRowsRemoved),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::rowsMoved,
|
||||
this,
|
||||
&LazyListView::onRowsMoved),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::dataChanged,
|
||||
this,
|
||||
&LazyListView::onDataChanged),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::modelReset,
|
||||
this,
|
||||
&LazyListView::onModelReset),
|
||||
connect(
|
||||
m_model,
|
||||
&QAbstractItemModel::layoutChanged,
|
||||
this,
|
||||
[this] {
|
||||
for (auto& entry : m_delegates)
|
||||
updateDelegateData(entry);
|
||||
polish();
|
||||
}),
|
||||
connect(
|
||||
m_model,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
[this] {
|
||||
m_model = nullptr;
|
||||
resetContent();
|
||||
emit modelChanged();
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -962,11 +901,9 @@ void LazyListView::resetContent() {
|
||||
polish();
|
||||
}
|
||||
|
||||
void LazyListView::onRowsInserted(const QModelIndex& parent,
|
||||
int first,
|
||||
int last) {
|
||||
if (parent.isValid())
|
||||
return;
|
||||
void LazyListView::onRowsInserted(
|
||||
const QModelIndex& parent, int first, int last) {
|
||||
if (parent.isValid()) return;
|
||||
|
||||
const int insertCount = last - first + 1;
|
||||
// Insert new layout records
|
||||
@@ -990,19 +927,15 @@ void LazyListView::onRowsInserted(const QModelIndex& parent,
|
||||
polish();
|
||||
}
|
||||
|
||||
void LazyListView::onRowsAboutToBeRemoved(const QModelIndex& parent,
|
||||
int first,
|
||||
int last) {
|
||||
if (parent.isValid())
|
||||
return;
|
||||
void LazyListView::onRowsAboutToBeRemoved(
|
||||
const QModelIndex& parent, int first, int last) {
|
||||
if (parent.isValid()) return;
|
||||
|
||||
for (int i = first; i <= last; ++i) {
|
||||
if (!m_delegates.contains(i))
|
||||
continue;
|
||||
if (!m_delegates.contains(i)) continue;
|
||||
|
||||
auto entry = m_delegates.take(i);
|
||||
if (entry.item)
|
||||
m_itemToIndex.remove(entry.item);
|
||||
if (entry.item) m_itemToIndex.remove(entry.item);
|
||||
entry.pendingRemoval = true;
|
||||
|
||||
// Never made visible — skip remove animation
|
||||
@@ -1014,8 +947,7 @@ void LazyListView::onRowsAboutToBeRemoved(const QModelIndex& parent,
|
||||
if (m_removeDuration > 0 && entry.item) {
|
||||
auto* attached = qobject_cast<LazyListViewAttached*>(
|
||||
qmlAttachedPropertiesObject<LazyListView>(entry.item, false));
|
||||
if (attached)
|
||||
attached->setRemoving(true);
|
||||
if (attached) attached->setRemoving(true);
|
||||
|
||||
// Schedule destruction after the remove animation duration
|
||||
auto* item = entry.item;
|
||||
@@ -1037,18 +969,15 @@ void LazyListView::onRowsAboutToBeRemoved(const QModelIndex& parent,
|
||||
}
|
||||
}
|
||||
|
||||
void LazyListView::onRowsRemoved(const QModelIndex& parent,
|
||||
int first,
|
||||
int last) {
|
||||
if (parent.isValid())
|
||||
return;
|
||||
void LazyListView::onRowsRemoved(
|
||||
const QModelIndex& parent, int first, int last) {
|
||||
if (parent.isValid()) return;
|
||||
|
||||
const int removeCount = last - first + 1;
|
||||
|
||||
// Untrack known heights being removed
|
||||
for (int i = first; i <= last; ++i) {
|
||||
if (m_layout[i].heightKnown)
|
||||
untrackHeight(m_layout[i].height);
|
||||
if (m_layout[i].heightKnown) untrackHeight(m_layout[i].height);
|
||||
}
|
||||
|
||||
// Remove layout records
|
||||
@@ -1072,13 +1001,13 @@ void LazyListView::onRowsRemoved(const QModelIndex& parent,
|
||||
polish();
|
||||
}
|
||||
|
||||
void LazyListView::onRowsMoved(const QModelIndex& parent,
|
||||
int start,
|
||||
int end,
|
||||
const QModelIndex& destination,
|
||||
int row) {
|
||||
if (parent.isValid() || destination.isValid())
|
||||
return;
|
||||
void LazyListView::onRowsMoved(
|
||||
const QModelIndex& parent,
|
||||
int start,
|
||||
int end,
|
||||
const QModelIndex& destination,
|
||||
int row) {
|
||||
if (parent.isValid() || destination.isValid()) return;
|
||||
|
||||
const int count = end - start + 1;
|
||||
const int dest = row > start ? row - count : row;
|
||||
@@ -1101,10 +1030,8 @@ void LazyListView::onRowsMoved(const QModelIndex& parent,
|
||||
if (oldIdx >= start && oldIdx <= end) {
|
||||
newIdx = dest + (oldIdx - start);
|
||||
} else {
|
||||
if (oldIdx > end)
|
||||
newIdx -= count;
|
||||
if (newIdx >= dest)
|
||||
newIdx += count;
|
||||
if (oldIdx > end) newIdx -= count;
|
||||
if (newIdx >= dest) newIdx += count;
|
||||
}
|
||||
|
||||
auto entry = std::move(it.value());
|
||||
@@ -1120,17 +1047,16 @@ void LazyListView::onRowsMoved(const QModelIndex& parent,
|
||||
polish();
|
||||
}
|
||||
|
||||
void LazyListView::onDataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
const QList<int>& roles) {
|
||||
void LazyListView::onDataChanged(
|
||||
const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
const QList<int>& roles) {
|
||||
Q_UNUSED(roles)
|
||||
|
||||
if (topLeft.parent().isValid())
|
||||
return;
|
||||
if (topLeft.parent().isValid()) return;
|
||||
|
||||
for (int i = topLeft.row(); i <= bottomRight.row(); ++i) {
|
||||
if (m_delegates.contains(i))
|
||||
updateDelegateData(m_delegates[i]);
|
||||
if (m_delegates.contains(i)) updateDelegateData(m_delegates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,232 +12,265 @@
|
||||
namespace ZShell::components {
|
||||
|
||||
class LazyListViewAttached : public QObject {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight NOTIFY preferredHeightChanged)
|
||||
Q_PROPERTY(qreal visibleHeight READ visibleHeight WRITE setVisibleHeight NOTIFY visibleHeightChanged)
|
||||
Q_PROPERTY(bool ready READ ready NOTIFY readyChanged)
|
||||
Q_PROPERTY(bool adding READ adding NOTIFY addingChanged)
|
||||
Q_PROPERTY(bool removing READ removing NOTIFY removingChanged)
|
||||
Q_PROPERTY(bool trackViewport READ trackViewport WRITE setTrackViewport NOTIFY trackViewportChanged)
|
||||
Q_PROPERTY(
|
||||
qreal preferredHeight READ preferredHeight WRITE setPreferredHeight
|
||||
NOTIFY preferredHeightChanged)
|
||||
Q_PROPERTY(
|
||||
qreal visibleHeight READ visibleHeight WRITE setVisibleHeight NOTIFY
|
||||
visibleHeightChanged)
|
||||
Q_PROPERTY(bool ready READ ready NOTIFY readyChanged)
|
||||
Q_PROPERTY(bool adding READ adding NOTIFY addingChanged)
|
||||
Q_PROPERTY(bool removing READ removing NOTIFY removingChanged)
|
||||
Q_PROPERTY(
|
||||
bool trackViewport READ trackViewport WRITE setTrackViewport NOTIFY
|
||||
trackViewportChanged)
|
||||
|
||||
public:
|
||||
explicit LazyListViewAttached(QObject* parent = nullptr);
|
||||
public:
|
||||
explicit LazyListViewAttached(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] qreal preferredHeight() const;
|
||||
void setPreferredHeight(qreal height);
|
||||
[[nodiscard]] qreal preferredHeight() const;
|
||||
void setPreferredHeight(qreal height);
|
||||
|
||||
[[nodiscard]] qreal visibleHeight() const;
|
||||
void setVisibleHeight(qreal height);
|
||||
[[nodiscard]] qreal visibleHeight() const;
|
||||
void setVisibleHeight(qreal height);
|
||||
|
||||
[[nodiscard]] bool ready() const;
|
||||
void setReady(bool ready);
|
||||
[[nodiscard]] bool ready() const;
|
||||
void setReady(bool ready);
|
||||
|
||||
[[nodiscard]] bool adding() const;
|
||||
void setAdding(bool adding);
|
||||
[[nodiscard]] bool adding() const;
|
||||
void setAdding(bool adding);
|
||||
|
||||
[[nodiscard]] bool removing() const;
|
||||
void setRemoving(bool removing);
|
||||
[[nodiscard]] bool removing() const;
|
||||
void setRemoving(bool removing);
|
||||
|
||||
[[nodiscard]] bool trackViewport() const;
|
||||
void setTrackViewport(bool track);
|
||||
[[nodiscard]] bool trackViewport() const;
|
||||
void setTrackViewport(bool track);
|
||||
|
||||
signals:
|
||||
void preferredHeightChanged();
|
||||
void visibleHeightChanged();
|
||||
void readyChanged();
|
||||
void addingChanged();
|
||||
void removingChanged();
|
||||
void trackViewportChanged();
|
||||
signals:
|
||||
void preferredHeightChanged();
|
||||
void visibleHeightChanged();
|
||||
void readyChanged();
|
||||
void addingChanged();
|
||||
void removingChanged();
|
||||
void trackViewportChanged();
|
||||
|
||||
private:
|
||||
qreal m_preferredHeight = -1;
|
||||
qreal m_visibleHeight = -1;
|
||||
bool m_ready = false;
|
||||
bool m_adding = false;
|
||||
bool m_removing = false;
|
||||
bool m_trackViewport = false;
|
||||
private:
|
||||
qreal m_preferredHeight = -1;
|
||||
qreal m_visibleHeight = -1;
|
||||
bool m_ready = false;
|
||||
bool m_adding = false;
|
||||
bool m_removing = false;
|
||||
bool m_trackViewport = false;
|
||||
};
|
||||
|
||||
class LazyListView : public QQuickItem {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_ATTACHED(LazyListViewAttached)
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_ATTACHED(LazyListViewAttached)
|
||||
|
||||
// Model & Delegate
|
||||
Q_PROPERTY(QAbstractItemModel* model READ model WRITE setModel NOTIFY modelChanged)
|
||||
Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
|
||||
// Model & Delegate
|
||||
Q_PROPERTY(
|
||||
QAbstractItemModel* model READ model WRITE setModel NOTIFY modelChanged)
|
||||
Q_PROPERTY(
|
||||
QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY
|
||||
delegateChanged)
|
||||
|
||||
// Layout
|
||||
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
|
||||
Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentHeightChanged)
|
||||
Q_PROPERTY(qreal layoutHeight READ layoutHeight NOTIFY layoutHeightChanged)
|
||||
Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
|
||||
// Layout
|
||||
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
|
||||
Q_PROPERTY(
|
||||
qreal contentHeight READ contentHeight NOTIFY contentHeightChanged)
|
||||
Q_PROPERTY(qreal layoutHeight READ layoutHeight NOTIFY layoutHeightChanged)
|
||||
Q_PROPERTY(
|
||||
qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged)
|
||||
|
||||
// Viewport & Lazy Loading
|
||||
Q_PROPERTY(QRectF viewport READ viewport WRITE setViewport NOTIFY viewportChanged)
|
||||
Q_PROPERTY(bool useCustomViewport READ useCustomViewport WRITE setUseCustomViewport NOTIFY useCustomViewportChanged)
|
||||
Q_PROPERTY(qreal cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
|
||||
// Viewport & Lazy Loading
|
||||
Q_PROPERTY(
|
||||
QRectF viewport READ viewport WRITE setViewport NOTIFY viewportChanged)
|
||||
Q_PROPERTY(
|
||||
bool useCustomViewport READ useCustomViewport WRITE setUseCustomViewport
|
||||
NOTIFY useCustomViewportChanged)
|
||||
Q_PROPERTY(
|
||||
qreal cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY
|
||||
cacheBufferChanged)
|
||||
|
||||
// Sizing
|
||||
Q_PROPERTY(qreal estimatedHeight READ estimatedHeight WRITE setEstimatedHeight NOTIFY estimatedHeightChanged)
|
||||
// Sizing
|
||||
Q_PROPERTY(
|
||||
qreal estimatedHeight READ estimatedHeight WRITE setEstimatedHeight
|
||||
NOTIFY estimatedHeightChanged)
|
||||
|
||||
// Async
|
||||
Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
|
||||
// Async
|
||||
Q_PROPERTY(
|
||||
bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY
|
||||
asynchronousChanged)
|
||||
|
||||
// Animation Durations
|
||||
Q_PROPERTY(int removeDuration READ removeDuration WRITE setRemoveDuration NOTIFY removeDurationChanged)
|
||||
Q_PROPERTY(int readyDelay READ readyDelay WRITE setReadyDelay NOTIFY readyDelayChanged)
|
||||
// Animation Durations
|
||||
Q_PROPERTY(
|
||||
int removeDuration READ removeDuration WRITE setRemoveDuration NOTIFY
|
||||
removeDurationChanged)
|
||||
Q_PROPERTY(
|
||||
int readyDelay READ readyDelay WRITE setReadyDelay NOTIFY
|
||||
readyDelayChanged)
|
||||
|
||||
// State
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
// State
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
|
||||
public:
|
||||
explicit LazyListView(QQuickItem* parent = nullptr);
|
||||
~LazyListView() override;
|
||||
public:
|
||||
explicit LazyListView(QQuickItem* parent = nullptr);
|
||||
~LazyListView() override;
|
||||
|
||||
static LazyListViewAttached* qmlAttachedProperties(QObject* object);
|
||||
static LazyListViewAttached* qmlAttachedProperties(QObject* object);
|
||||
|
||||
// Model & Delegate
|
||||
[[nodiscard]] QAbstractItemModel* model() const;
|
||||
void setModel(QAbstractItemModel* model);
|
||||
// Model & Delegate
|
||||
[[nodiscard]] QAbstractItemModel* model() const;
|
||||
void setModel(QAbstractItemModel* model);
|
||||
|
||||
[[nodiscard]] QQmlComponent* delegate() const;
|
||||
void setDelegate(QQmlComponent* delegate);
|
||||
[[nodiscard]] QQmlComponent* delegate() const;
|
||||
void setDelegate(QQmlComponent* delegate);
|
||||
|
||||
// Layout
|
||||
[[nodiscard]] qreal spacing() const;
|
||||
void setSpacing(qreal spacing);
|
||||
// Layout
|
||||
[[nodiscard]] qreal spacing() const;
|
||||
void setSpacing(qreal spacing);
|
||||
|
||||
[[nodiscard]] qreal contentHeight() const;
|
||||
[[nodiscard]] qreal layoutHeight() const;
|
||||
[[nodiscard]] qreal contentHeight() const;
|
||||
[[nodiscard]] qreal layoutHeight() const;
|
||||
|
||||
[[nodiscard]] qreal contentY() const;
|
||||
void setContentY(qreal contentY);
|
||||
[[nodiscard]] qreal contentY() const;
|
||||
void setContentY(qreal contentY);
|
||||
|
||||
// Viewport
|
||||
[[nodiscard]] QRectF viewport() const;
|
||||
void setViewport(const QRectF& viewport);
|
||||
// Viewport
|
||||
[[nodiscard]] QRectF viewport() const;
|
||||
void setViewport(const QRectF& viewport);
|
||||
|
||||
[[nodiscard]] bool useCustomViewport() const;
|
||||
void setUseCustomViewport(bool use);
|
||||
[[nodiscard]] bool useCustomViewport() const;
|
||||
void setUseCustomViewport(bool use);
|
||||
|
||||
[[nodiscard]] qreal cacheBuffer() const;
|
||||
void setCacheBuffer(qreal buffer);
|
||||
[[nodiscard]] qreal cacheBuffer() const;
|
||||
void setCacheBuffer(qreal buffer);
|
||||
|
||||
// Sizing
|
||||
[[nodiscard]] qreal estimatedHeight() const;
|
||||
void setEstimatedHeight(qreal height);
|
||||
// Sizing
|
||||
[[nodiscard]] qreal estimatedHeight() const;
|
||||
void setEstimatedHeight(qreal height);
|
||||
|
||||
// Async
|
||||
[[nodiscard]] bool asynchronous() const;
|
||||
void setAsynchronous(bool async);
|
||||
// Async
|
||||
[[nodiscard]] bool asynchronous() const;
|
||||
void setAsynchronous(bool async);
|
||||
|
||||
// Animation Durations
|
||||
[[nodiscard]] int removeDuration() const;
|
||||
void setRemoveDuration(int duration);
|
||||
// Animation Durations
|
||||
[[nodiscard]] int removeDuration() const;
|
||||
void setRemoveDuration(int duration);
|
||||
|
||||
[[nodiscard]] int readyDelay() const;
|
||||
void setReadyDelay(int delay);
|
||||
[[nodiscard]] int readyDelay() const;
|
||||
void setReadyDelay(int delay);
|
||||
|
||||
// State
|
||||
[[nodiscard]] int count() const;
|
||||
signals:
|
||||
void modelChanged();
|
||||
void delegateChanged();
|
||||
void spacingChanged();
|
||||
void contentHeightChanged();
|
||||
void layoutHeightChanged();
|
||||
void contentYChanged();
|
||||
void viewportChanged();
|
||||
void useCustomViewportChanged();
|
||||
void cacheBufferChanged();
|
||||
void estimatedHeightChanged();
|
||||
void asynchronousChanged();
|
||||
void removeDurationChanged();
|
||||
void readyDelayChanged();
|
||||
void countChanged();
|
||||
void viewportAdjustNeeded(qreal delta);
|
||||
// State
|
||||
[[nodiscard]] int count() const;
|
||||
signals:
|
||||
void modelChanged();
|
||||
void delegateChanged();
|
||||
void spacingChanged();
|
||||
void contentHeightChanged();
|
||||
void layoutHeightChanged();
|
||||
void contentYChanged();
|
||||
void viewportChanged();
|
||||
void useCustomViewportChanged();
|
||||
void cacheBufferChanged();
|
||||
void estimatedHeightChanged();
|
||||
void asynchronousChanged();
|
||||
void removeDurationChanged();
|
||||
void readyDelayChanged();
|
||||
void countChanged();
|
||||
void viewportAdjustNeeded(qreal delta);
|
||||
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
void geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) override;
|
||||
void updatePolish() override;
|
||||
protected:
|
||||
void componentComplete() override;
|
||||
void geometryChange(
|
||||
const QRectF& newGeometry, const QRectF& oldGeometry) override;
|
||||
void updatePolish() override;
|
||||
|
||||
private:
|
||||
struct ItemRecord {
|
||||
qreal targetY = 0;
|
||||
qreal height = 0;
|
||||
bool heightKnown = false;
|
||||
bool isNew = false;
|
||||
};
|
||||
private:
|
||||
struct ItemRecord {
|
||||
qreal targetY = 0;
|
||||
qreal height = 0;
|
||||
bool heightKnown = false;
|
||||
bool isNew = false;
|
||||
};
|
||||
|
||||
struct DelegateEntry {
|
||||
int modelIndex = -1;
|
||||
QQuickItem* item = nullptr;
|
||||
bool pendingRemoval = false;
|
||||
bool pendingInsert = false;
|
||||
bool readyDelayStarted = false;
|
||||
};
|
||||
struct DelegateEntry {
|
||||
int modelIndex = -1;
|
||||
QQuickItem* item = nullptr;
|
||||
bool pendingRemoval = false;
|
||||
bool pendingInsert = false;
|
||||
bool readyDelayStarted = false;
|
||||
};
|
||||
|
||||
// Layout
|
||||
void relayout();
|
||||
[[nodiscard]] std::pair<int, int> computeVisibleRange() const;
|
||||
[[nodiscard]] QRectF effectiveViewport() const;
|
||||
[[nodiscard]] qreal effectiveEstimatedHeight() const;
|
||||
[[nodiscard]] static qreal delegateHeight(QQuickItem* item);
|
||||
[[nodiscard]] static qreal delegateVisibleHeight(QQuickItem* item);
|
||||
[[nodiscard]] static bool isDelegateReady(QQuickItem* item);
|
||||
void trackHeight(qreal height);
|
||||
void untrackHeight(qreal height);
|
||||
// Layout
|
||||
void relayout();
|
||||
[[nodiscard]] std::pair<int, int> computeVisibleRange() const;
|
||||
[[nodiscard]] QRectF effectiveViewport() const;
|
||||
[[nodiscard]] qreal effectiveEstimatedHeight() const;
|
||||
[[nodiscard]] static qreal delegateHeight(QQuickItem* item);
|
||||
[[nodiscard]] static qreal delegateVisibleHeight(QQuickItem* item);
|
||||
[[nodiscard]] static bool isDelegateReady(QQuickItem* item);
|
||||
void trackHeight(qreal height);
|
||||
void untrackHeight(qreal height);
|
||||
|
||||
// Delegate lifecycle
|
||||
void syncDelegates();
|
||||
DelegateEntry createDelegate(int modelIndex);
|
||||
void destroyDelegate(DelegateEntry& entry);
|
||||
void updateDelegateData(DelegateEntry& entry);
|
||||
// Delegate lifecycle
|
||||
void syncDelegates();
|
||||
DelegateEntry createDelegate(int modelIndex);
|
||||
void destroyDelegate(DelegateEntry& entry);
|
||||
void updateDelegateData(DelegateEntry& entry);
|
||||
|
||||
// Model connection
|
||||
void connectModel();
|
||||
void disconnectModel();
|
||||
void resetContent();
|
||||
void onRowsInserted(const QModelIndex& parent, int first, int last);
|
||||
void onRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last);
|
||||
void onRowsRemoved(const QModelIndex& parent, int first, int last);
|
||||
void onRowsMoved(const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row);
|
||||
void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QList<int>& roles);
|
||||
void onModelReset();
|
||||
// Model connection
|
||||
void connectModel();
|
||||
void disconnectModel();
|
||||
void resetContent();
|
||||
void onRowsInserted(const QModelIndex& parent, int first, int last);
|
||||
void onRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last);
|
||||
void onRowsRemoved(const QModelIndex& parent, int first, int last);
|
||||
void onRowsMoved(
|
||||
const QModelIndex& parent,
|
||||
int start,
|
||||
int end,
|
||||
const QModelIndex& destination,
|
||||
int row);
|
||||
void onDataChanged(
|
||||
const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight,
|
||||
const QList<int>& roles);
|
||||
void onModelReset();
|
||||
|
||||
// Members
|
||||
QAbstractItemModel* m_model = nullptr;
|
||||
QQmlComponent* m_delegate = nullptr;
|
||||
// Members
|
||||
QAbstractItemModel* m_model = nullptr;
|
||||
QQmlComponent* m_delegate = nullptr;
|
||||
|
||||
qreal m_spacing = 0;
|
||||
qreal m_contentHeight = 0;
|
||||
qreal m_layoutHeight = 0;
|
||||
qreal m_contentY = 0;
|
||||
qreal m_spacing = 0;
|
||||
qreal m_contentHeight = 0;
|
||||
qreal m_layoutHeight = 0;
|
||||
qreal m_contentY = 0;
|
||||
|
||||
QRectF m_viewport;
|
||||
bool m_useCustomViewport = false;
|
||||
qreal m_cacheBuffer = 0;
|
||||
QRectF m_viewport;
|
||||
bool m_useCustomViewport = false;
|
||||
qreal m_cacheBuffer = 0;
|
||||
|
||||
qreal m_estimatedHeight = -1;
|
||||
qreal m_knownHeightSum = 0;
|
||||
int m_knownHeightCount = 0;
|
||||
bool m_asynchronous = false;
|
||||
qreal m_estimatedHeight = -1;
|
||||
qreal m_knownHeightSum = 0;
|
||||
int m_knownHeightCount = 0;
|
||||
bool m_asynchronous = false;
|
||||
|
||||
int m_removeDuration = 300;
|
||||
int m_readyDelay = 0;
|
||||
int m_removeDuration = 300;
|
||||
int m_readyDelay = 0;
|
||||
|
||||
QVector<ItemRecord> m_layout;
|
||||
QHash<int, DelegateEntry> m_delegates;
|
||||
QHash<QQuickItem*, int> m_itemToIndex;
|
||||
QVector<DelegateEntry> m_dyingDelegates;
|
||||
QVector<ItemRecord> m_layout;
|
||||
QHash<int, DelegateEntry> m_delegates;
|
||||
QHash<QQuickItem*, int> m_itemToIndex;
|
||||
QVector<DelegateEntry> m_dyingDelegates;
|
||||
|
||||
bool m_componentComplete = false;
|
||||
bool m_relayoutPending = false;
|
||||
bool m_componentComplete = false;
|
||||
bool m_relayoutPending = false;
|
||||
|
||||
QList<QMetaObject::Connection> m_modelConnections;
|
||||
QList<QMetaObject::Connection> m_modelConnections;
|
||||
};
|
||||
|
||||
} // namespace ZShell::components
|
||||
|
||||
@@ -194,7 +194,8 @@ void WavyLine::paintLinear(QPainter* painter) {
|
||||
bool first = true;
|
||||
|
||||
for (int x = m_lineWidth / 2; x <= drawEnd; ++x) {
|
||||
const auto theta = m_frequency * 2 * M_PI * (x + m_startX) / len + phase;
|
||||
const auto theta =
|
||||
m_frequency * 2 * M_PI * (x + m_startX) / len + phase;
|
||||
const auto waveY = centerY + amplitude * qSin(theta);
|
||||
if (first) {
|
||||
path.moveTo(x, waveY);
|
||||
@@ -215,7 +216,10 @@ void WavyLine::paintArc(QPainter* painter) {
|
||||
const auto amplitude = m_lineWidth * m_amplitudeMultiplier;
|
||||
const auto cx = width() / 2.0;
|
||||
const auto cy = height() / 2.0;
|
||||
const auto radius = m_radius > 0 ? m_radius : (qMin(width(), height()) - m_lineWidth - 2 * amplitude) / 2.0;
|
||||
const auto radius =
|
||||
m_radius > 0
|
||||
? m_radius
|
||||
: (qMin(width(), height()) - m_lineWidth - 2 * amplitude) / 2.0;
|
||||
|
||||
if (radius <= 0) {
|
||||
return;
|
||||
|
||||
@@ -6,102 +6,116 @@
|
||||
namespace ZShell::controls {
|
||||
|
||||
class WavyLine : public QQuickPaintedItem {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(int lineWidth READ lineWidth WRITE setLineWidth NOTIFY lineWidthChanged FINAL)
|
||||
Q_PROPERTY(qreal amplitudeMultiplier READ amplitudeMultiplier WRITE setAmplitudeMultiplier NOTIFY
|
||||
amplitudeMultiplierChanged FINAL)
|
||||
Q_PROPERTY(int frequency READ frequency WRITE setFrequency NOTIFY frequencyChanged FINAL)
|
||||
Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged FINAL)
|
||||
Q_PROPERTY(qreal fullLength READ fullLength WRITE setFullLength NOTIFY fullLengthChanged FINAL)
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
|
||||
Q_PROPERTY(qreal waveProgress READ waveProgress WRITE setWaveProgress NOTIFY waveProgressChanged FINAL)
|
||||
Q_PROPERTY(PathType pathType READ pathType WRITE setPathType NOTIFY pathTypeChanged FINAL)
|
||||
Q_PROPERTY(qreal startAngle READ startAngle WRITE setStartAngle NOTIFY startAngleChanged FINAL)
|
||||
Q_PROPERTY(qreal fullAngle READ fullAngle WRITE setFullAngle NOTIFY fullAngleChanged FINAL)
|
||||
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged FINAL)
|
||||
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
int lineWidth READ lineWidth WRITE setLineWidth NOTIFY lineWidthChanged
|
||||
FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal amplitudeMultiplier READ amplitudeMultiplier WRITE
|
||||
setAmplitudeMultiplier NOTIFY amplitudeMultiplierChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
int frequency READ frequency WRITE setFrequency NOTIFY frequencyChanged
|
||||
FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal startX READ startX WRITE setStartX NOTIFY startXChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal fullLength READ fullLength WRITE setFullLength NOTIFY
|
||||
fullLengthChanged FINAL)
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal waveProgress READ waveProgress WRITE setWaveProgress NOTIFY
|
||||
waveProgressChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
PathType pathType READ pathType WRITE setPathType NOTIFY pathTypeChanged
|
||||
FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal startAngle READ startAngle WRITE setStartAngle NOTIFY
|
||||
startAngleChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal fullAngle READ fullAngle WRITE setFullAngle NOTIFY
|
||||
fullAngleChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal radius READ radius WRITE setRadius NOTIFY radiusChanged FINAL)
|
||||
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged FINAL)
|
||||
|
||||
public:
|
||||
enum PathType {
|
||||
Linear,
|
||||
Arc
|
||||
};
|
||||
Q_ENUM(PathType)
|
||||
public:
|
||||
enum PathType { Linear, Arc };
|
||||
Q_ENUM(PathType)
|
||||
|
||||
explicit WavyLine(QQuickItem* parent = nullptr);
|
||||
explicit WavyLine(QQuickItem* parent = nullptr);
|
||||
|
||||
[[nodiscard]] int lineWidth() const;
|
||||
void setLineWidth(int lineWidth);
|
||||
[[nodiscard]] int lineWidth() const;
|
||||
void setLineWidth(int lineWidth);
|
||||
|
||||
[[nodiscard]] qreal amplitudeMultiplier() const;
|
||||
void setAmplitudeMultiplier(qreal amplitudeMultiplier);
|
||||
[[nodiscard]] qreal amplitudeMultiplier() const;
|
||||
void setAmplitudeMultiplier(qreal amplitudeMultiplier);
|
||||
|
||||
[[nodiscard]] int frequency() const;
|
||||
void setFrequency(int frequency);
|
||||
[[nodiscard]] int frequency() const;
|
||||
void setFrequency(int frequency);
|
||||
|
||||
[[nodiscard]] qreal startX() const;
|
||||
void setStartX(qreal startX);
|
||||
[[nodiscard]] qreal startX() const;
|
||||
void setStartX(qreal startX);
|
||||
|
||||
[[nodiscard]] qreal fullLength() const;
|
||||
void setFullLength(qreal fullLength);
|
||||
[[nodiscard]] qreal fullLength() const;
|
||||
void setFullLength(qreal fullLength);
|
||||
|
||||
[[nodiscard]] QColor color() const;
|
||||
void setColor(const QColor& color);
|
||||
[[nodiscard]] QColor color() const;
|
||||
void setColor(const QColor& color);
|
||||
|
||||
[[nodiscard]] qreal waveProgress() const;
|
||||
void setWaveProgress(qreal progress);
|
||||
[[nodiscard]] qreal waveProgress() const;
|
||||
void setWaveProgress(qreal progress);
|
||||
|
||||
[[nodiscard]] PathType pathType() const;
|
||||
void setPathType(PathType pathType);
|
||||
[[nodiscard]] PathType pathType() const;
|
||||
void setPathType(PathType pathType);
|
||||
|
||||
[[nodiscard]] qreal startAngle() const;
|
||||
void setStartAngle(qreal startAngle);
|
||||
[[nodiscard]] qreal startAngle() const;
|
||||
void setStartAngle(qreal startAngle);
|
||||
|
||||
[[nodiscard]] qreal fullAngle() const;
|
||||
void setFullAngle(qreal fullAngle);
|
||||
[[nodiscard]] qreal fullAngle() const;
|
||||
void setFullAngle(qreal fullAngle);
|
||||
|
||||
[[nodiscard]] qreal radius() const;
|
||||
void setRadius(qreal radius);
|
||||
[[nodiscard]] qreal radius() const;
|
||||
void setRadius(qreal radius);
|
||||
|
||||
[[nodiscard]] qreal value() const;
|
||||
void setValue(qreal value);
|
||||
[[nodiscard]] qreal value() const;
|
||||
void setValue(qreal value);
|
||||
|
||||
void paint(QPainter* painter) override;
|
||||
void paint(QPainter* painter) override;
|
||||
|
||||
signals:
|
||||
void lineWidthChanged();
|
||||
void amplitudeMultiplierChanged();
|
||||
void frequencyChanged();
|
||||
void startXChanged();
|
||||
void fullLengthChanged();
|
||||
void colorChanged();
|
||||
void waveProgressChanged();
|
||||
void pathTypeChanged();
|
||||
void startAngleChanged();
|
||||
void fullAngleChanged();
|
||||
void radiusChanged();
|
||||
void valueChanged();
|
||||
signals:
|
||||
void lineWidthChanged();
|
||||
void amplitudeMultiplierChanged();
|
||||
void frequencyChanged();
|
||||
void startXChanged();
|
||||
void fullLengthChanged();
|
||||
void colorChanged();
|
||||
void waveProgressChanged();
|
||||
void pathTypeChanged();
|
||||
void startAngleChanged();
|
||||
void fullAngleChanged();
|
||||
void radiusChanged();
|
||||
void valueChanged();
|
||||
|
||||
private:
|
||||
void paintLinear(QPainter* painter);
|
||||
void paintArc(QPainter* painter);
|
||||
private:
|
||||
void paintLinear(QPainter* painter);
|
||||
void paintArc(QPainter* painter);
|
||||
|
||||
int m_lineWidth;
|
||||
qreal m_amplitudeMultiplier;
|
||||
int m_frequency;
|
||||
qreal m_startX;
|
||||
qreal m_fullLength;
|
||||
QColor m_color;
|
||||
qreal m_waveProgress;
|
||||
PathType m_pathType;
|
||||
qreal m_startAngle;
|
||||
qreal m_fullAngle;
|
||||
qreal m_radius;
|
||||
qreal m_value;
|
||||
qreal m_startAngleRad;
|
||||
qreal m_fullAngleRad;
|
||||
int m_lineWidth;
|
||||
qreal m_amplitudeMultiplier;
|
||||
int m_frequency;
|
||||
qreal m_startX;
|
||||
qreal m_fullLength;
|
||||
QColor m_color;
|
||||
qreal m_waveProgress;
|
||||
PathType m_pathType;
|
||||
qreal m_startAngle;
|
||||
qreal m_fullAngle;
|
||||
qreal m_radius;
|
||||
qreal m_value;
|
||||
qreal m_startAngleRad;
|
||||
qreal m_fullAngleRad;
|
||||
};
|
||||
|
||||
} // namespace ZShell::controls
|
||||
|
||||
Reference in New Issue
Block a user