diff --git a/autotests/delegatesizehelpertest.cpp b/autotests/delegatesizehelpertest.cpp index 77d5cf6ce..7473e3e43 100644 --- a/autotests/delegatesizehelpertest.cpp +++ b/autotests/delegatesizehelpertest.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL #include +#include #include #include "delegatesizehelper.h" @@ -30,7 +31,7 @@ void DelegateSizeHelperTest::risingPercentage_data() QTest::addColumn("currentPercentageWidth"); QTest::addColumn("currentWidth"); - QTest::newRow("zero") << qreal(0) << int(0) << qreal(0); + QTest::newRow("zero") << qreal(0) << int(100) << qreal(0); QTest::newRow("one hundred") << qreal(100) << int(0) << qreal(0); QTest::newRow("one fifty") << qreal(150) << int(50) << qreal(75); QTest::newRow("two hundred") << qreal(200) << int(100) << qreal(200); @@ -43,16 +44,18 @@ void DelegateSizeHelperTest::risingPercentage() QFETCH(int, currentPercentageWidth); QFETCH(qreal, currentWidth); + auto item = QQuickItem(); + item.setWidth(parentWidth); + DelegateSizeHelper delegateSizeHelper; + delegateSizeHelper.setParentItem(&item); delegateSizeHelper.setStartBreakpoint(100); delegateSizeHelper.setEndBreakpoint(200); delegateSizeHelper.setStartPercentWidth(0); delegateSizeHelper.setEndPercentWidth(100); - delegateSizeHelper.setParentWidth(parentWidth); - - QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth); - QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth); + QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth); + QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth); } void DelegateSizeHelperTest::fallingPercentage_data() @@ -74,16 +77,18 @@ void DelegateSizeHelperTest::fallingPercentage() QFETCH(int, currentPercentageWidth); QFETCH(qreal, currentWidth); + auto item = QQuickItem(); + item.setWidth(parentWidth); + DelegateSizeHelper delegateSizeHelper; + delegateSizeHelper.setParentItem(&item); delegateSizeHelper.setStartBreakpoint(100); delegateSizeHelper.setEndBreakpoint(200); delegateSizeHelper.setStartPercentWidth(100); delegateSizeHelper.setEndPercentWidth(0); - delegateSizeHelper.setParentWidth(parentWidth); - - QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth); - QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth); + QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth); + QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth); } void DelegateSizeHelperTest::equalPercentage_data() @@ -105,16 +110,18 @@ void DelegateSizeHelperTest::equalPercentage() QFETCH(int, currentPercentageWidth); QFETCH(qreal, currentWidth); + auto item = QQuickItem(); + item.setWidth(parentWidth); + DelegateSizeHelper delegateSizeHelper; + delegateSizeHelper.setParentItem(&item); delegateSizeHelper.setStartBreakpoint(100); delegateSizeHelper.setEndBreakpoint(200); delegateSizeHelper.setStartPercentWidth(50); delegateSizeHelper.setEndPercentWidth(50); - delegateSizeHelper.setParentWidth(parentWidth); - - QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth); - QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth); + QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth); + QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth); } void DelegateSizeHelperTest::equalBreakpoint_data() @@ -124,9 +131,9 @@ void DelegateSizeHelperTest::equalBreakpoint_data() QTest::addColumn("currentPercentageWidth"); QTest::addColumn("currentWidth"); - QTest::newRow("start higher") << int(100) << int(0) << int(-1) << qreal(0); + QTest::newRow("start higher") << int(100) << int(0) << int(100) << qreal(1000); QTest::newRow("equal") << int(50) << int(50) << int(50) << qreal(500); - QTest::newRow("end higher") << int(0) << int(100) << int(-1) << qreal(0); + QTest::newRow("end higher") << int(0) << int(100) << int(100) << qreal(1000); } /** @@ -140,16 +147,18 @@ void DelegateSizeHelperTest::equalBreakpoint() QFETCH(int, currentPercentageWidth); QFETCH(qreal, currentWidth); + auto item = QQuickItem(); + item.setWidth(1000); + DelegateSizeHelper delegateSizeHelper; + delegateSizeHelper.setParentItem(&item); delegateSizeHelper.setStartBreakpoint(100); delegateSizeHelper.setEndBreakpoint(100); delegateSizeHelper.setStartPercentWidth(startPercentageWidth); delegateSizeHelper.setEndPercentWidth(endPercentageWidth); - delegateSizeHelper.setParentWidth(1000); - - QCOMPARE(delegateSizeHelper.currentPercentageWidth(), currentPercentageWidth); - QCOMPARE(delegateSizeHelper.currentWidth(), currentWidth); + QCOMPARE(delegateSizeHelper.availablePercentageWidth(), currentPercentageWidth); + QCOMPARE(delegateSizeHelper.availableWidth(), currentWidth); } QTEST_GUILESS_MAIN(DelegateSizeHelperTest) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7cd010e9..2cdb3e066 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,8 @@ if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT NEOCHAT_FLATPAK AND NOT NEOC add_subdirectory(purpose) endif() +add_subdirectory(libneochat) + add_library(neochat STATIC controller.cpp controller.h @@ -109,8 +111,6 @@ add_library(neochat STATIC events/imagepackevent.h models/reactionmodel.cpp models/reactionmodel.h - delegatesizehelper.cpp - delegatesizehelper.h models/livelocationsmodel.cpp models/livelocationsmodel.h models/locationsmodel.cpp @@ -413,6 +413,7 @@ endif() target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models ${CMAKE_CURRENT_SOURCE_DIR}/enums) target_link_libraries(neochat PRIVATE settingsplugin timelineplugin devtoolsplugin loginplugin chatbarplugin) target_link_libraries(neochat PUBLIC + LibNeoChat Qt::Core Qt::Quick Qt::Qml diff --git a/src/chatbar/ChatBar.qml b/src/chatbar/ChatBar.qml index 284930048..a9f68601e 100644 --- a/src/chatbar/ChatBar.qml +++ b/src/chatbar/ChatBar.qml @@ -8,7 +8,9 @@ import QtQuick.Controls as QQC2 import QtQuick.Layouts import org.kde.kirigami as Kirigami + import org.kde.neochat +import org.kde.neochat.libneochat as LibNeoChat /** * @brief A component for typing and sending chat messages. @@ -165,7 +167,7 @@ QQC2.Control { } leftPadding: rightPadding - rightPadding: (root.width - chatBarSizeHelper.currentWidth) / 2 + rightPadding: (root.width - chatBarSizeHelper.availableWidth) / 2 topPadding: 0 bottomPadding: 0 @@ -353,15 +355,14 @@ QQC2.Control { } } } - DelegateSizeHelper { + LibNeoChat.DelegateSizeHelper { id: chatBarSizeHelper + parentItem: root startBreakpoint: Kirigami.Units.gridUnit * 46 endBreakpoint: Kirigami.Units.gridUnit * 66 startPercentWidth: 100 endPercentWidth: NeoChatConfig.compactLayout ? 100 : 85 maxWidth: NeoChatConfig.compactLayout ? -1 : Kirigami.Units.gridUnit * 60 - - parentWidth: root.width } Component { diff --git a/src/libneochat/CMakeLists.txt b/src/libneochat/CMakeLists.txt new file mode 100644 index 000000000..8cba65d7a --- /dev/null +++ b/src/libneochat/CMakeLists.txt @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2023 Tobias Fella +# SPDX-License-Identifier: BSD-3-Clause + +add_library(LibNeoChat STATIC) + +target_sources(LibNeoChat PRIVATE + delegatesizehelper.cpp +) + +ecm_add_qml_module(LibNeoChat GENERATE_PLUGIN_SOURCE + URI org.kde.neochat.libneochat + OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat/libneochat +) + +generate_export_header(LibNeoChat BASE_NAME LibNeoChat) +target_link_libraries(LibNeoChat PUBLIC + Qt::Core + Qt::Quick +) diff --git a/src/delegatesizehelper.cpp b/src/libneochat/delegatesizehelper.cpp similarity index 55% rename from src/delegatesizehelper.cpp rename to src/libneochat/delegatesizehelper.cpp index aae61fa06..6bd1d2ff3 100644 --- a/src/delegatesizehelper.cpp +++ b/src/libneochat/delegatesizehelper.cpp @@ -12,20 +12,60 @@ DelegateSizeHelper::DelegateSizeHelper(QObject *parent) { } -qreal DelegateSizeHelper::parentWidth() const +QQuickItem *DelegateSizeHelper::parentItem() const { - return m_parentWidth; + return m_parentItem; } -void DelegateSizeHelper::setParentWidth(qreal parentWidth) +void DelegateSizeHelper::setParentItem(QQuickItem *parentItem) { - if (parentWidth == m_parentWidth) { + if (parentItem == m_parentItem) { return; } - m_parentWidth = parentWidth; - Q_EMIT parentWidthChanged(); - Q_EMIT currentPercentageWidthChanged(); - Q_EMIT currentWidthChanged(); + m_parentItem = parentItem; + + if (m_parentItem) { + connect(m_parentItem, &QQuickItem::widthChanged, this, [this]() { + Q_EMIT availablePercentageWidthChanged(); + Q_EMIT availableWidthChanged(); + }); + } + + Q_EMIT parentItemChanged(); + Q_EMIT availablePercentageWidthChanged(); + Q_EMIT availableWidthChanged(); +} + +qreal DelegateSizeHelper::leftPadding() const +{ + return m_leftPadding; +} + +void DelegateSizeHelper::setLeftPadding(qreal leftPadding) +{ + if (qFuzzyCompare(leftPadding, m_leftPadding)) { + return; + } + m_leftPadding = leftPadding; + Q_EMIT leftPaddingChanged(); + Q_EMIT availablePercentageWidthChanged(); + Q_EMIT availableWidthChanged(); +} + +qreal DelegateSizeHelper::rightPadding() const +{ + return m_rightPadding; +} + +void DelegateSizeHelper::setRightPadding(qreal rightPadding) +{ + if (qFuzzyCompare(rightPadding, m_rightPadding)) { + return; + } + m_rightPadding = rightPadding; + Q_EMIT rightPaddingChanged(); + Q_EMIT availablePercentageWidthChanged(); + Q_EMIT availableWidthChanged(); } qreal DelegateSizeHelper::startBreakpoint() const @@ -86,7 +126,14 @@ void DelegateSizeHelper::setEndPercentWidth(int endPercentWidth) qreal DelegateSizeHelper::maxWidth() const { - return m_maxWidth; + if (m_maxWidth == std::nullopt) { + if (m_parentItem) { + return m_parentItem->width(); + } + return 0.0; + } + + return *m_maxWidth; } void DelegateSizeHelper::setMaxWidth(qreal maxWidth) @@ -98,21 +145,23 @@ void DelegateSizeHelper::setMaxWidth(qreal maxWidth) Q_EMIT maxWidthChanged(); } -int DelegateSizeHelper::calculateCurrentPercentageWidth() const +qreal DelegateSizeHelper::maxAvailableWidth() const { - // Don't do anything if m_parentWidth hasn't been set yet. - if (m_parentWidth < 0) { - return -1; + if (!m_parentItem || qFuzzyCompare(m_parentItem->width(), 0)) { + return 0; } + return std::max(m_parentItem->width() - m_leftPadding - m_rightPadding, 0.0); +} + +int DelegateSizeHelper::calculateAvailablePercentageWidth() const +{ // Don't bother with calculations for a horizontal line. if (m_startPercentWidth == m_endPercentWidth) { return m_startPercentWidth; } // Dividing by zero is a bad idea. - if (m_startBreakpoint == m_endBreakpoint) { - qWarning() << "DelegateSizeHelper::calculateCurrentPercentageWidth() - m_startBreakpoint is equal to m_endBreakpoint this would lead to divide by " - "zero, aborting"; - return -1; + if (m_startBreakpoint == m_endBreakpoint || qFuzzyCompare(maxAvailableWidth(), 0)) { + return 100; } // Fit to y = mx + c @@ -124,32 +173,19 @@ int DelegateSizeHelper::calculateCurrentPercentageWidth() const int maxPercentWidth = endPercentBigger ? m_endPercentWidth : m_startPercentWidth; int minPercentWidth = endPercentBigger ? m_startPercentWidth : m_endPercentWidth; - int calcPercentWidth = std::round(m * m_parentWidth + c); + int calcPercentWidth = std::round(m * maxAvailableWidth() + c); return std::clamp(calcPercentWidth, minPercentWidth, maxPercentWidth); } -int DelegateSizeHelper::currentPercentageWidth() const +int DelegateSizeHelper::availablePercentageWidth() const { - return calculateCurrentPercentageWidth(); + return calculateAvailablePercentageWidth(); } -qreal DelegateSizeHelper::currentWidth() const +qreal DelegateSizeHelper::availableWidth() const { - if (m_parentWidth < 0) { - return 0.0; - } - int percentWidth = calculateCurrentPercentageWidth(); - // - 1 means bad input values so don't try to calculate. - if (percentWidth == -1) { - return 0.0; - } - - qreal absoluteWidth = m_parentWidth * percentWidth * 0.01; - if (m_maxWidth < 0.0) { - return std::round(absoluteWidth); - } else { - return std::round(std::min(absoluteWidth, m_maxWidth)); - } + qreal absoluteWidth = maxAvailableWidth() * availablePercentageWidth() * 0.01; + return std::round(std::min(absoluteWidth, maxWidth())); } #include "moc_delegatesizehelper.cpp" diff --git a/src/delegatesizehelper.h b/src/libneochat/delegatesizehelper.h similarity index 62% rename from src/delegatesizehelper.h rename to src/libneochat/delegatesizehelper.h index 752a7b96e..702dc8358 100644 --- a/src/delegatesizehelper.h +++ b/src/libneochat/delegatesizehelper.h @@ -5,6 +5,7 @@ #include #include +#include /** * @class DelegateSizeHelper @@ -27,9 +28,25 @@ class DelegateSizeHelper : public QObject QML_ELEMENT /** - * @brief The width of the component's parent. + * @brief The parent item that defines the available content area. */ - Q_PROPERTY(qreal parentWidth READ parentWidth WRITE setParentWidth NOTIFY parentWidthChanged) + Q_PROPERTY(QQuickItem *parentItem READ parentItem WRITE setParentItem NOTIFY parentItemChanged) + + /** + * @brief The amount of padding to be removed from the left of the available content area. + * + * The padding is removed before calculating the available width, i.e. max available width + * at 100% is equal to parent width minus padding. + */ + Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding NOTIFY leftPaddingChanged) + + /** + * @brief The amount of padding to be removed from the right of the available content area. + * + * The padding is removed before calculating the available width, i.e. max available width + * at 100% is equal to parent width minus padding. + */ + Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding NOTIFY rightPaddingChanged) /** * @brief The width (in px) when the width percentage should start to transition. @@ -67,7 +84,7 @@ class DelegateSizeHelper : public QObject * * @sa parentWidth, startBreakpoint, endBreakpoint */ - Q_PROPERTY(int currentPercentageWidth READ currentPercentageWidth NOTIFY currentPercentageWidthChanged) + Q_PROPERTY(int availablePercentageWidth READ availablePercentageWidth NOTIFY availablePercentageWidthChanged) /** * @brief The width (in px) of the component at the current parentWidth. @@ -76,50 +93,60 @@ class DelegateSizeHelper : public QObject * * @sa parentWidth */ - Q_PROPERTY(qreal currentWidth READ currentWidth NOTIFY currentWidthChanged) + Q_PROPERTY(qreal availableWidth READ availableWidth NOTIFY availableWidthChanged) public: explicit DelegateSizeHelper(QObject *parent = nullptr); - qreal parentWidth() const; - void setParentWidth(qreal parentWidth); + QQuickItem *parentItem() const; + void setParentItem(QQuickItem *parentItem); + + qreal leftPadding() const; + void setLeftPadding(qreal leftPadding); + qreal rightPadding() const; + void setRightPadding(qreal rightPadding); qreal startBreakpoint() const; void setStartBreakpoint(qreal startBreakpoint); - qreal endBreakpoint() const; void setEndBreakpoint(qreal endBreakpoint); int startPercentWidth() const; void setStartPercentWidth(int startPercentWidth); - int endPercentWidth() const; void setEndPercentWidth(int endPercentWidth); qreal maxWidth() const; void setMaxWidth(qreal maxWidth); - int currentPercentageWidth() const; + qreal maxAvailableWidth() const; - qreal currentWidth() const; + int availablePercentageWidth() const; + qreal availableWidth() const; Q_SIGNALS: - void parentWidthChanged(); + void parentItemChanged(); + void leftPaddingChanged(); + void rightPaddingChanged(); void startBreakpointChanged(); void endBreakpointChanged(); void startPercentWidthChanged(); void endPercentWidthChanged(); void maxWidthChanged(); - void currentPercentageWidthChanged(); - void currentWidthChanged(); + void availablePercentageWidthChanged(); + void availableWidthChanged(); private: - qreal m_parentWidth = -1.0; - qreal m_startBreakpoint; - qreal m_endBreakpoint; - int m_startPercentWidth; - int m_endPercentWidth; - qreal m_maxWidth = -1.0; + QPointer m_parentItem; - int calculateCurrentPercentageWidth() const; + qreal m_leftPadding = 0.0; + qreal m_rightPadding = 0.0; + + qreal m_startBreakpoint = 0.0; + qreal m_endBreakpoint = 0.0; + int m_startPercentWidth = 100; + int m_endPercentWidth = 85; + std::optional m_maxWidth = std::nullopt; + + int calculateAvailablePercentageWidth() const; }; diff --git a/src/qml/SpaceHierarchyDelegate.qml b/src/qml/SpaceHierarchyDelegate.qml index b970e5c1d..f542b9679 100644 --- a/src/qml/SpaceHierarchyDelegate.qml +++ b/src/qml/SpaceHierarchyDelegate.qml @@ -10,6 +10,7 @@ import org.kde.kirigamiaddons.delegates as Delegates import org.kde.kirigamiaddons.labs.components as Components import org.kde.neochat +import org.kde.neochat.libneochat as LibNeoChat Item { id: root @@ -44,7 +45,7 @@ Item { anchors.horizontalCenter: root.horizontalCenter anchors.verticalCenter: root.verticalCenter - width: sizeHelper.currentWidth + width: sizeHelper.availableWidth highlighted: dropArea.containsDrag @@ -201,15 +202,14 @@ Item { } } - DelegateSizeHelper { + LibNeoChat.DelegateSizeHelper { id: sizeHelper + parentItem: root startBreakpoint: Kirigami.Units.gridUnit * 46 endBreakpoint: Kirigami.Units.gridUnit * 66 startPercentWidth: 100 endPercentWidth: 85 maxWidth: Kirigami.Units.gridUnit * 60 - - parentWidth: root.treeView ? root.treeView.width : 0 } Component { diff --git a/src/qml/SpaceHomePage.qml b/src/qml/SpaceHomePage.qml index e1fc44ecb..8fed26002 100644 --- a/src/qml/SpaceHomePage.qml +++ b/src/qml/SpaceHomePage.qml @@ -8,6 +8,7 @@ import QtQuick.Layouts import org.kde.kirigami as Kirigami import org.kde.neochat +import org.kde.neochat.libneochat as LibNeoChat import org.kde.neochat.settings ColumnLayout { @@ -93,15 +94,14 @@ ColumnLayout { onTextChanged: spaceChildSortFilterModel.filterText = text } } - DelegateSizeHelper { + LibNeoChat.DelegateSizeHelper { id: sizeHelper + parentItem: root startBreakpoint: Kirigami.Units.gridUnit * 46 endBreakpoint: Kirigami.Units.gridUnit * 66 startPercentWidth: 100 endPercentWidth: 85 maxWidth: Kirigami.Units.gridUnit * 60 - - parentWidth: root.width } } Kirigami.Separator { diff --git a/src/timeline/CMakeLists.txt b/src/timeline/CMakeLists.txt index a395174c9..8e6538a72 100644 --- a/src/timeline/CMakeLists.txt +++ b/src/timeline/CMakeLists.txt @@ -90,4 +90,5 @@ ecm_add_qml_module(timeline GENERATE_PLUGIN_SOURCE target_link_libraries(timeline PRIVATE Qt::Quick KF6::Kirigami + LibNeoChat ) diff --git a/src/timeline/MessageDelegate.qml b/src/timeline/MessageDelegate.qml index d63a4c91a..af5fa44c6 100644 --- a/src/timeline/MessageDelegate.qml +++ b/src/timeline/MessageDelegate.qml @@ -10,6 +10,7 @@ import org.kde.kirigami as Kirigami import org.kde.kirigamiaddons.components as KirigamiComponents import org.kde.neochat +import org.kde.neochat.libneochat as LibNeoChat /** * @brief The base delegate for all messages in the timeline. @@ -185,7 +186,7 @@ TimelineDelegate { /** * @brief The width available to the bubble content. */ - property real contentMaxWidth: (root.isThreaded ? bubbleSizeHelper.parentWidth : bubbleSizeHelper.currentWidth) - bubble.leftPadding - bubble.rightPadding + property real contentMaxWidth: (root.isThreaded ? bubbleSizeHelper.parentWidth : bubbleSizeHelper.availableWidth) - bubble.leftPadding - bubble.rightPadding Message.room: root.room Message.timeline: root.ListView.view @@ -321,14 +322,14 @@ TimelineDelegate { model: root.readMarkers } - DelegateSizeHelper { + LibNeoChat.DelegateSizeHelper { id: bubbleSizeHelper + parentItem: mainContainer + leftPadding: avatar.anchors.leftMargin + (NeoChatConfig.showAvatarInTimeline ? avatar.width + bubble.anchors.leftMargin : 0) startBreakpoint: Kirigami.Units.gridUnit * 25 endBreakpoint: Kirigami.Units.gridUnit * 40 startPercentWidth: root.alwaysFillWidth ? 100 : 90 endPercentWidth: root.alwaysFillWidth ? 100 : 60 - - parentWidth: mainContainer.availableWidth - (NeoChatConfig.showAvatarInTimeline ? avatar.width + bubble.anchors.leftMargin : 0) } } diff --git a/src/timeline/timelinedelegate.cpp b/src/timeline/timelinedelegate.cpp index 6ba8ab325..50dc8a254 100644 --- a/src/timeline/timelinedelegate.cpp +++ b/src/timeline/timelinedelegate.cpp @@ -6,6 +6,17 @@ TimelineDelegate::TimelineDelegate(QQuickItem *parent) : QQuickItem(parent) { + m_sizeHelper.setParentItem(this); + connect(&m_sizeHelper, &DelegateSizeHelper::leftPaddingChanged, this, [this]() { + Q_EMIT leftPaddingChanged(); + resizeContent(); + updatePolish(); + }); + connect(&m_sizeHelper, &DelegateSizeHelper::rightPaddingChanged, this, [this]() { + Q_EMIT rightPaddingChanged(); + resizeContent(); + updatePolish(); + }); } QQuickItem *TimelineDelegate::contentItem() @@ -56,38 +67,22 @@ void TimelineDelegate::setAlwaysFillWidth(bool alwaysFillWidth) qreal TimelineDelegate::leftPadding() { - return m_leftPadding; + return m_sizeHelper.leftPadding(); } void TimelineDelegate::setLeftPadding(qreal leftPadding) { - if (qFuzzyCompare(leftPadding, m_leftPadding)) { - return; - } - - m_leftPadding = leftPadding; - Q_EMIT leftPaddingChanged(); - - resizeContent(); - updatePolish(); + m_sizeHelper.setLeftPadding(leftPadding); } qreal TimelineDelegate::rightPadding() { - return m_rightPadding; + return m_sizeHelper.rightPadding(); } void TimelineDelegate::setRightPadding(qreal rightPadding) { - if (qFuzzyCompare(rightPadding, m_rightPadding)) { - return; - } - - m_rightPadding = rightPadding; - Q_EMIT rightPaddingChanged(); - - resizeContent(); - updatePolish(); + m_sizeHelper.setRightPadding(rightPadding); } void TimelineDelegate::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) @@ -114,68 +109,27 @@ void TimelineDelegate::componentComplete() void TimelineDelegate::setCurveValues() { - m_leftPadding = qreal(m_units->largeSpacing()); - m_rightPadding = qreal(m_units->largeSpacing()); + m_sizeHelper.setLeftPadding(qreal(m_units->largeSpacing())); + m_sizeHelper.setRightPadding(qreal(m_units->largeSpacing())); - m_startBreakpoint = qreal(m_units->gridUnit() * 46); - m_endBreakpoint = qreal(m_units->gridUnit() * 66); - m_maxWidth = qreal(m_units->gridUnit() * 60); + m_sizeHelper.setStartBreakpoint(qreal(m_units->gridUnit() * 46)); + m_sizeHelper.setEndBreakpoint(qreal(m_units->gridUnit() * 66)); + m_sizeHelper.setMaxWidth(qreal(m_units->gridUnit() * 60)); resizeContent(); } -int TimelineDelegate::availablePercentageWidth() const -{ - // Don't bother with calculations for a horizontal line. - if (m_startPercentWidth == m_endPercentWidth) { - return m_startPercentWidth; - } - // Dividing by zero is a bad idea. - if (m_startBreakpoint == m_endBreakpoint || qFuzzyCompare(width(), 0)) { - return 100; - } - - // Fit to y = mx + c - qreal m = (m_endPercentWidth - m_startPercentWidth) / (m_endBreakpoint - m_startBreakpoint); - qreal c = m_startPercentWidth - m * m_startBreakpoint; - - // This allows us to clamp correctly if the start or end width is bigger. - bool endPercentBigger = m_endPercentWidth > m_startPercentWidth; - int maxPercentWidth = endPercentBigger ? m_endPercentWidth : m_startPercentWidth; - int minPercentWidth = endPercentBigger ? m_startPercentWidth : m_endPercentWidth; - - int calcPercentWidth = std::round(m * maxAvailableWidth() + c); - return std::clamp(calcPercentWidth, minPercentWidth, maxPercentWidth); -} - -qreal TimelineDelegate::maxAvailableWidth() const -{ - if (qFuzzyCompare(width(), 0)) { - return 0; - } - - return std::max(width() - m_leftPadding - m_rightPadding, 0.0); -} - -qreal TimelineDelegate::availableWidth() const -{ - if (m_alwaysFillWidth) { - return maxAvailableWidth(); - } - - qreal absoluteWidth = maxAvailableWidth() * availablePercentageWidth() * 0.01; - return std::round(std::min(absoluteWidth, m_maxWidth)); -} - void TimelineDelegate::resizeContent() { if (m_contentItem == nullptr || !isComponentComplete()) { return; } - const auto leftPadding = m_leftPadding + (maxAvailableWidth() - availableWidth()) / 2; + auto availableWidth = m_alwaysFillWidth ? m_sizeHelper.maxAvailableWidth() : m_sizeHelper.availableWidth(); + + const auto leftPadding = m_sizeHelper.leftPadding() + (m_sizeHelper.maxAvailableWidth() - availableWidth) / 2; m_contentItem->setPosition(QPointF(leftPadding, 0)); - m_contentItem->setSize(QSizeF(availableWidth(), m_contentItem->implicitHeight())); + m_contentItem->setSize(QSizeF(availableWidth, m_contentItem->implicitHeight())); } void TimelineDelegate::updateImplicitHeight() diff --git a/src/timeline/timelinedelegate.h b/src/timeline/timelinedelegate.h index 52fc5dae2..b8c6c6b01 100644 --- a/src/timeline/timelinedelegate.h +++ b/src/timeline/timelinedelegate.h @@ -8,6 +8,8 @@ #include +#include "delegatesizehelper.h" + /** * @brief The base Item for all delegates in the timeline. * @@ -77,17 +79,8 @@ private: Kirigami::Platform::Units *m_units = nullptr; void setCurveValues(); - qreal m_leftPadding; - qreal m_rightPadding; + DelegateSizeHelper m_sizeHelper; - qreal m_startBreakpoint; - qreal m_endBreakpoint; - int m_startPercentWidth = 100; - int m_endPercentWidth = 85; - qreal m_maxWidth; - int availablePercentageWidth() const; - qreal maxAvailableWidth() const; - qreal availableWidth() const; bool m_alwaysFillWidth = false; void resizeContent();