diff --git a/storybook/main.cpp b/storybook/main.cpp index 21cbaa2257..2163c3a8ed 100644 --- a/storybook/main.cpp +++ b/storybook/main.cpp @@ -2,8 +2,9 @@ #include #include -#include -#include +#include "cachecleaner.h" +#include "directorieswatcher.h" +#include "sectionsdecoratormodel.h" int main(int argc, char *argv[]) { @@ -34,6 +35,8 @@ int main(int argc, char *argv[]) for (const auto& path : additionalImportPaths) engine.addImportPath(path); + qmlRegisterType("Storybook", 1, 0, "SectionsDecoratorModel"); + auto watcherFactory = [additionalImportPaths](QQmlEngine*, QJSEngine*) { auto watcher = new DirectoriesWatcher(); watcher->addPaths(additionalImportPaths); diff --git a/storybook/main.qml b/storybook/main.qml index 38a2202db1..03e090c378 100644 --- a/storybook/main.qml +++ b/storybook/main.qml @@ -31,36 +31,47 @@ ApplicationWindow { ListElement { title: "ProfileDialogView" + section: "Views" } ListElement { title: "CommunitiesPortalLayout" - } - ListElement { - title: "StatusCommunityCard" + section: "Views" } ListElement { title: "LoginView" + section: "Views" } ListElement { title: "AboutView" - } - ListElement { - title: "LanguageCurrencySettings" + section: "Views" } ListElement { title: "CommunityProfilePopupInviteFriendsPanel" + section: "Panels" } ListElement { title: "CommunityProfilePopupInviteMessagePanel" + section: "Panels" + } + ListElement { + title: "StatusCommunityCard" + section: "Panels" } ListElement { title: "InviteFriendsToCommunityPopup" - } - ListElement { - title: "BrowserSettings" + section: "Popups" } ListElement { title: "CreateChannelPopup" + section: "Popups" + } + ListElement { + title: "LanguageCurrencySettings" + section: "Settings" + } + ListElement { + title: "BrowserSettings" + section: "Settings" } ListElement { title: "UserListPanel" diff --git a/storybook/sectionsdecoratormodel.cpp b/storybook/sectionsdecoratormodel.cpp index c41f4ba04f..3c1309bce2 100644 --- a/storybook/sectionsdecoratormodel.cpp +++ b/storybook/sectionsdecoratormodel.cpp @@ -9,6 +9,9 @@ SectionsDecoratorModel::SectionsDecoratorModel(QObject *parent) void SectionsDecoratorModel::setSourceModel(QAbstractItemModel *sourceModel) { + if (m_sourceModel == nullptr && sourceModel == nullptr) + return; + if (m_sourceModel != nullptr) { qWarning("Changing source model is not supported!"); return; @@ -74,7 +77,14 @@ QHash SectionsDecoratorModel::roleNames() const void SectionsDecoratorModel::flipFolding(int index) { + if (index < 0 || index >= m_rowsMetadata.size()) + return; + auto &row = m_rowsMetadata[index]; + + if (!row.isSection) + return; + row.folded = !row.folded; const auto idx = this->index(index, 0, {}); diff --git a/storybook/src/Storybook/FilteredPagesList.qml b/storybook/src/Storybook/FilteredPagesList.qml index d04ac33013..b590deb6d8 100644 --- a/storybook/src/Storybook/FilteredPagesList.qml +++ b/storybook/src/Storybook/FilteredPagesList.qml @@ -4,6 +4,8 @@ import QtQuick.Controls 2.14 import SortFilterProxyModel 0.2 +import Storybook 1.0 + ColumnLayout { id: root @@ -24,6 +26,12 @@ ColumnLayout { } } + SectionsDecoratorModel { + id: sectionsModel + + sourceModel: filteredModel + } + TextField { id: textField @@ -42,8 +50,9 @@ ColumnLayout { Layout.fillWidth: true Layout.fillHeight: true - model: filteredModel + model: sectionsModel onPageSelected: root.pageSelected(page) + onSectionClicked: sectionsModel.flipFolding(index) } } diff --git a/storybook/src/Storybook/PagesList.qml b/storybook/src/Storybook/PagesList.qml index 4478663cb8..e18d18a128 100644 --- a/storybook/src/Storybook/PagesList.qml +++ b/storybook/src/Storybook/PagesList.qml @@ -8,15 +8,42 @@ ListView { clip: true property string currentPage + signal pageSelected(string page) + signal sectionClicked(int index) - delegate: Button { - width: parent.width + readonly property string foldedPrefix: "▶ " + readonly property string unfoldedPrefix: "▼ " - text: model.title - checked: root.currentPage === model.title + delegate: ItemDelegate { + id: delegate - onClicked: root.pageSelected(model.title) - onCheckableChanged: checkable = false + width: ListView.view.width + + TextMetrics { + id: textMetrics + text: root.unfoldedPrefix + font: delegate.font + } + + function sectionPrefix(isFolded) { + return isFolded ? foldedPrefix : unfoldedPrefix + } + + text: model.isSection + ? sectionPrefix(model.isFolded) + model.section + ` (${model.subitemsCount})` + : model.title + + font.bold: model.isSection + highlighted: root.currentPage === model.title + + onClicked: model.isSection + ? sectionClicked(index) + : root.pageSelected(model.title) + + Component.onCompleted: { + if (!model.isSection) + leftPadding += textMetrics.advanceWidth + } } } diff --git a/storybook/tests/tst_SectionsDecoratorModel.cpp b/storybook/tests/tst_SectionsDecoratorModel.cpp index aa27fe31ee..b56e013e89 100644 --- a/storybook/tests/tst_SectionsDecoratorModel.cpp +++ b/storybook/tests/tst_SectionsDecoratorModel.cpp @@ -75,6 +75,36 @@ private slots: QVERIFY(model.roleNames().contains(TestSourceModel::SectionRole)); } + void changingSourceModelHasNoEffectTest() { + TestSourceModel src1(QStringList{"Section 1", "Section 1", "Section 1", "Section 2", "Section 2", "Section 3"}); + TestSourceModel src2(QStringList{}); + + SectionsDecoratorModel model; + + QCOMPARE(model.rowCount(), 0); + QCOMPARE(model.roleNames().count(), 3); + + model.setSourceModel(nullptr); + + QCOMPARE(model.rowCount(), 0); + QCOMPARE(model.roleNames().count(), 3); + + model.setSourceModel(&src1); + + QCOMPARE(model.rowCount(), 9); + QCOMPARE(model.roleNames().count(), 5); + + model.setSourceModel(&src2); + + QCOMPARE(model.rowCount(), 9); + QCOMPARE(model.roleNames().count(), 5); + + model.setSourceModel(nullptr); + + QCOMPARE(model.rowCount(), 9); + QCOMPARE(model.roleNames().count(), 5); + } + void initialUnfoldedStateTest() { TestSourceModel src(QStringList{"Section 1", "Section 1", "Section 1", "Section 2", "Section 2", "Section 3"}); SectionsDecoratorModel model; @@ -305,6 +335,195 @@ private slots: QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::SubitemsCountRole).toInt(), 1); } + void flipFoldingForNonSectionHasNoEffecttest() { + + TestSourceModel src(QStringList{"Section 1", "Section 1", "Section 1", "Section 2", "Section 2", "Section 3"}); + SectionsDecoratorModel model; + model.setSourceModel(&src); + + QCOMPARE(model.rowCount(), 9); + + QSignalSpy modelResetSpy(&model, &SectionsDecoratorModel::modelReset); + QSignalSpy rowsInsertedSpy(&model, &SectionsDecoratorModel::rowsInserted); + QSignalSpy rowsRemovedSpy(&model, &SectionsDecoratorModel::rowsRemoved); + + model.flipFolding(9); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(1000); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(-1); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(-1000); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(1); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(2); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(3); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(1); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(2); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(3); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + + model.flipFolding(8); + QCOMPARE(model.rowCount(), 9); + QCOMPARE(modelResetSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + QCOMPARE(rowsRemovedSpy.count(), 0); + + QCOMPARE(model.data(model.index(0, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(1, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(2, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(3, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(4, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(5, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(6, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(7, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + QCOMPARE(model.data(model.index(8, 0), SectionsDecoratorModel::IsFoldedRole).toBool(), false); + } + void unfoldingTest() { TestSourceModel src(QStringList{"Section 1", "Section 1", "Section 1", "Section 2", "Section 2", "Section 3"}); SectionsDecoratorModel model; @@ -472,7 +691,7 @@ private slots: SectionsDecoratorModel model; model.setSourceModel(&proxy); - QSignalSpy spy(&model, SIGNAL(modelReset())); + QSignalSpy spy(&model, &SectionsDecoratorModel::modelReset); proxy.setFilterRole(TestSourceModel::TitleRole); proxy.setFilterWildcard("*1");