feat(Storybook): Foldable sections in pages list

Based on SectionsDecoratorModel extending source model
by foldable sections.

Closes: #7928
This commit is contained in:
Michał Cieślak 2022-11-16 14:40:29 +01:00 committed by Michał
parent c1d5fdd04a
commit c5b409a42a
6 changed files with 298 additions and 19 deletions

View File

@ -2,8 +2,9 @@
#include <QQmlApplicationEngine>
#include <QtWebEngine>
#include <cachecleaner.h>
#include <directorieswatcher.h>
#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<SectionsDecoratorModel>("Storybook", 1, 0, "SectionsDecoratorModel");
auto watcherFactory = [additionalImportPaths](QQmlEngine*, QJSEngine*) {
auto watcher = new DirectoriesWatcher();
watcher->addPaths(additionalImportPaths);

View File

@ -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"

View File

@ -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<int, QByteArray> 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, {});

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -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");