on xenial help sign in
First quick unfinished stab at the category expansion
a6d169bAlbert Astals
Components/FilterGrid.qml+1−59
@@ -35,7 +35,7 @@ Item {
35
35
36 /* Whether, when collapsed, a button should be displayed enabling the user to expand
36 /* Whether, when collapsed, a button should be displayed enabling the user to expand
37 the grid to its full size. */
37 the grid to its full size. */
38− property bool expandable: true
38+ readonly property bool expandable: model.count > collapsedRowCount * iconTileGrid.columns
39
39
40 property var model: null
40 property var model: null
41
41
@@ -76,62 +76,4 @@ Item {
76 }
76 }
77
77
78 }
78 }
79−
80− Item {
81− anchors {
82− left: parent.left
83− right: parent.right
84− top: iconTileGrid.bottom
85− }
86− visible: (expandable && filter && model.count > collapsedRowCount * iconTileGrid.columns)
87− height: (visible) ? childrenRect.height + units.gu(2) : 0
88−
89− AbstractButton {
90− id: button
91− objectName: "filterToggleButton"
92−
93− anchors {
94− top: parent.top
95− horizontalCenter: parent.horizontalCenter
96− }
97− width: units.gu(22)
98− height: units.gu(4)
99−
100− UbuntuShape {
101− anchors.fill: parent
102− color: "#33ffffff" // FIXME no palette
103− radius: "small"
104− }
105−
106− UbuntuShape {
107− id: borderPressed
108−
109− anchors.fill: parent
110− radius: "small"
111− borderSource: "radius_pressed.sci"
112− opacity: button.pressed ? 1.0 : 0.0
113− Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } }
114− }
115−
116− Label {
117− anchors {
118− verticalCenter: parent.verticalCenter
119− left: parent.left
120− right: parent.right
121− leftMargin: units.gu(1)
122− rightMargin: units.gu(1)
123− }
124− text: (filter) ? "+ View all (" + model.count + ")" : "- Show fewer"
125− fontSize: "small"
126− color: Theme.palette.selected.backgroundText
127− opacity: 0.6
128− style: Text.Raised
129− styleColor: "black"
130− elide: Text.ElideMiddle
131− horizontalAlignment: Text.AlignHCenter
132− }
133−
134− onClicked: filter = !filter
135− }
136− }
137}
79}
Components/ListItems/Header.qml+7
@@ -25,6 +25,8 @@ Item {
25 */
25 */
26 property alias text: label.text
26 property alias text: label.text
27
27
28+ signal clicked(variant mouse)
29+
28 height: units.gu(4.5)
30 height: units.gu(4.5)
29
31
30 Item {
32 Item {
@@ -64,4 +66,9 @@ Item {
64 bottom: parent.bottom
66 bottom: parent.bottom
65 }
67 }
66 }
68 }
69+
70+ MouseArea {
71+ anchors.fill: parent
72+ onClicked: parent.clicked(mouse)
73+ }
67}
74}
Dash/Apps/ApplicationsFilterGrid.qml−2
@@ -22,8 +22,6 @@ import "../../Components/IconUtil.js" as IconUtil
22FilterGrid {
22FilterGrid {
23 id: filterGrid
23 id: filterGrid
24
24
25− filter: false
26− expandable: false
27 minimumHorizontalSpacing: units.gu(0.5)
25 minimumHorizontalSpacing: units.gu(0.5)
28 maximumNumberOfColumns: 6
26 maximumNumberOfColumns: 6
29 delegateWidth: units.gu(11)
27 delegateWidth: units.gu(11)
Dash/DashApps.qml+12−13
@@ -117,8 +117,13 @@ ScopeView {
117 delegate: Base {
117 delegate: Base {
118 id: container
118 id: container
119 highlightWhenPressed: false
119 highlightWhenPressed: false
120+ property var loader: loader
121+ // Needed because of the GridView.onRemove anim in Tile.qml
122+ // TODO see how can we do away without the clip (i.e. not run the animation if we are collapsing)
123+ clip: true
120
124
121 Loader {
125 Loader {
126+ id: loader
122 anchors {
127 anchors {
123 top: parent.top
128 top: parent.top
124 left: parent.left
129 left: parent.left
@@ -142,25 +147,19 @@ ScopeView {
142 }
147 }
143 }
148 }
144 }
149 }
145−
146− ListView.onRemove: SequentialAnimation {
147− PropertyAction {
148− target: container; property: "ListView.delayRemove"; value: true
149− }
150− NumberAnimation {
151− target: container; property: "height"; to: 0;
152− duration: 250; easing.type: Easing.InOutQuad
153− }
154− PropertyAction {
155− target: container; property: "ListView.delayRemove"; value: false
156− }
157− }
158 }
150 }
159
151
160 sectionProperty: "category"
152 sectionProperty: "category"
161 sectionDelegate: Header {
153 sectionDelegate: Header {
162 width: categoryView.width
154 width: categoryView.width
163 text: categoryListModel.getCategory(section)
155 text: categoryListModel.getCategory(section)
156+ onClicked: {
157+ var obj = categoryView.item(delegateIndex)
158+ if (obj && obj.loader.item.expandable) {
159+ obj.loader.item.filter = !obj.loader.item.filter
160+ categoryView.maximizeVisibleArea(delegateIndex);
161+ }
162+ }
164 }
163 }
165 pageHeader: PageHeader {
164 pageHeader: PageHeader {
166 id: pageHeader
165 id: pageHeader
Dash/Music/MusicFilterGrid.qml−1
@@ -20,7 +20,6 @@ import "../../Components"
20FilterGrid {
20FilterGrid {
21 id: filterGrid
21 id: filterGrid
22
22
23− expandable: false
24 minimumHorizontalSpacing: units.gu(2)
23 minimumHorizontalSpacing: units.gu(2)
25 maximumNumberOfColumns: 5
24 maximumNumberOfColumns: 5
26 delegateWidth: units.gu(17)
25 delegateWidth: units.gu(17)
Dash/Video/VideosFilterGrid.qml−1
@@ -20,7 +20,6 @@ import "../../Components"
20FilterGrid {
20FilterGrid {
21 id: filtergrid
21 id: filtergrid
22
22
23− expandable: false
24 minimumHorizontalSpacing: units.gu(0.5)
23 minimumHorizontalSpacing: units.gu(0.5)
25 maximumNumberOfColumns: 5
24 maximumNumberOfColumns: 5
26 delegateWidth: units.gu(11)
25 delegateWidth: units.gu(11)
plugins/ListViewWithPageHeader/listviewwithpageheader.cpp+34−10
@@ -160,16 +160,16 @@ ListViewWithPageHeader::ListViewWithPageHeader()
160// m_clipItem = new QQuickRectangle(contentItem());
160// m_clipItem = new QQuickRectangle(contentItem());
161// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
161// ((QQuickRectangle*)m_clipItem)->setColor(Qt::gray);
162
162
163− m_headerShowAnimation = new QQuickNumberAnimation(this);
163+ m_contentYAnimation = new QQuickNumberAnimation(this);
164− m_headerShowAnimation->setEasing(QEasingCurve::OutQuad);
164+ m_contentYAnimation->setEasing(QEasingCurve::OutQuad);
165− m_headerShowAnimation->setProperty("contentY");
165+ m_contentYAnimation->setProperty("contentY");
166− m_headerShowAnimation->setDuration(200);
166+ m_contentYAnimation->setDuration(200);
167− m_headerShowAnimation->setTargetObject(this);
167+ m_contentYAnimation->setTargetObject(this);
168
168
169 connect(this, SIGNAL(contentWidthChanged()), this, SLOT(onContentWidthChanged()));
169 connect(this, SIGNAL(contentWidthChanged()), this, SLOT(onContentWidthChanged()));
170 connect(this, SIGNAL(contentHeightChanged()), this, SLOT(onContentHeightChanged()));
170 connect(this, SIGNAL(contentHeightChanged()), this, SLOT(onContentHeightChanged()));
171 connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
171 connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
172− connect(m_headerShowAnimation, SIGNAL(stopped()), this, SLOT(onShowHeaderAnimationFinished()));
172+ connect(m_contentYAnimation, SIGNAL(stopped()), this, SLOT(onShowHeaderAnimationFinished()));
173}
173}
174
174
175ListViewWithPageHeader::~ListViewWithPageHeader()
175ListViewWithPageHeader::~ListViewWithPageHeader()
@@ -374,8 +374,32 @@ void ListViewWithPageHeader::showHeader()
374 layout();
374 layout();
375 }
375 }
376 }
376 }
377− m_headerShowAnimation->setTo(to);
377+ m_contentYAnimation->setTo(to);
378− m_headerShowAnimation->start();
378+ contentYAnimationIsShownHeader = true;
379+ m_contentYAnimation->start();
380+ }
381+}
382+
383+QQuickItem *ListViewWithPageHeader::item(int modelIndex) const
384+{
385+ ListItem *item = itemAtIndex(modelIndex);
386+ if (item)
387+ return item->m_item;
388+ else
389+ return nullptr;
390+}
391+
392+void ListViewWithPageHeader::maximizeVisibleArea(int modelIndex)
393+{
394+ ListItem *listItem = itemAtIndex(modelIndex);
395+ if (listItem)
396+ {
397+ // Check if we can scroll the list up to show more stuff
398+ if (m_clipItem->y() + listItem->y() > contentY() && m_clipItem->y() + listItem->y() + listItem->height() > contentY() + height()) {
399+ m_contentYAnimation->setTo(m_clipItem->y() + listItem->y());
400+ contentYAnimationIsShownHeader = false;
401+ m_contentYAnimation->start();
402+ }
379 }
403 }
380}
404}
381
405
@@ -435,7 +459,7 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
435 // We will be changing the clip item, need to accomadate for it
459 // We will be changing the clip item, need to accomadate for it
436 // otherwise we move the firstItem down/up twice (unless the
460 // otherwise we move the firstItem down/up twice (unless the
437 // show header animation is running, where we want to keep the viewport stable)
461 // show header animation is running, where we want to keep the viewport stable)
438− if (!m_headerShowAnimation->isRunning()) {
462+ if (!(m_contentYAnimation->isRunning() && contentYAnimationIsShownHeader)) {
439 diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
463 diff += oldHeaderItemShownHeight - m_headerItemShownHeight;
440 } else {
464 } else {
441 diff = -diff;
465 diff = -diff;
@@ -445,7 +469,7 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
445 updateClipItem();
469 updateClipItem();
446 ListItem *firstItem = m_visibleItems.first();
470 ListItem *firstItem = m_visibleItems.first();
447 firstItem->setY(firstItem->y() + diff);
471 firstItem->setY(firstItem->y() + diff);
448− if (m_headerShowAnimation->isRunning()) {
472+ if (m_contentYAnimation->isRunning() && contentYAnimationIsShownHeader) {
449 adjustMinYExtent();
473 adjustMinYExtent();
450 }
474 }
451 }
475 }
plugins/ListViewWithPageHeader/listviewwithpageheader.h+4−1
@@ -88,6 +88,8 @@ public:
88
88
89 Q_INVOKABLE void positionAtBeginning();
89 Q_INVOKABLE void positionAtBeginning();
90 Q_INVOKABLE void showHeader();
90 Q_INVOKABLE void showHeader();
91+ Q_INVOKABLE QQuickItem *item(int modelIndex) const;
92+ Q_INVOKABLE void maximizeVisibleArea(int modelIndex);
91
93
92Q_SIGNALS:
94Q_SIGNALS:
93 void modelChanged();
95 void modelChanged();
@@ -182,7 +184,8 @@ private:
182 qreal m_previousContentY;
184 qreal m_previousContentY;
183 qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
185 qreal m_headerItemShownHeight; // The height of header shown when the header is shown outside its topmost position
184 // i.e. it's being shown after dragging down in the middle of the list
186 // i.e. it's being shown after dragging down in the middle of the list
187+ bool contentYAnimationIsShownHeader;
185− QQuickNumberAnimation *m_headerShowAnimation;
188+ QQuickNumberAnimation *m_contentYAnimation;
186
189
187 QQmlComponent *m_sectionDelegate;
190 QQmlComponent *m_sectionDelegate;
188 QString m_sectionProperty;
191 QString m_sectionProperty;
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+3−3
@@ -1245,7 +1245,7 @@ private Q_SLOTS:
1245
1245
1246 lvwph->showHeader();
1246 lvwph->showHeader();
1247
1247
1248− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1248+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1249 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1249 QTRY_COMPARE(lvwph->m_visibleItems.count(), 5);
1250 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1250 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1251 verifyItem(0, -375., 150., true);
1251 verifyItem(0, -375., 150., true);
@@ -1301,7 +1301,7 @@ private Q_SLOTS:
1301
1301
1302 lvwph->showHeader();
1302 lvwph->showHeader();
1303
1303
1304− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1304+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1305 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1305 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1306 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1306 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1307 verifyItem(0, -20., 150., false);
1307 verifyItem(0, -20., 150., false);
@@ -1339,7 +1339,7 @@ private Q_SLOTS:
1339
1339
1340 lvwph->showHeader();
1340 lvwph->showHeader();
1341
1341
1342− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1342+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1343 QTRY_VERIFY (lvwph->isAtYEnd());
1343 QTRY_VERIFY (lvwph->isAtYEnd());
1344 }
1344 }
1345
1345
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertestsection.cpp+3−3
@@ -1506,7 +1506,7 @@ private Q_SLOTS:
1506
1506
1507 lvwph->showHeader();
1507 lvwph->showHeader();
1508
1508
1509− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1509+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1510 QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1510 QTRY_COMPARE(lvwph->m_visibleItems.count(), 3);
1511 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1511 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1512 verifyItem(0, -20., 190., false, "Agressive", true);
1512 verifyItem(0, -20., 190., false, "Agressive", true);
@@ -1565,7 +1565,7 @@ private Q_SLOTS:
1565
1565
1566 lvwph->showHeader();
1566 lvwph->showHeader();
1567
1567
1568− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1568+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1569 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1569 QTRY_COMPARE(lvwph->m_visibleItems.count(), 4);
1570 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1570 QCOMPARE(lvwph->m_firstVisibleIndex, 0);
1571 verifyItem(0, -375., 190., true, "Agressive", true);
1571 verifyItem(0, -375., 190., true, "Agressive", true);
@@ -1607,7 +1607,7 @@ private Q_SLOTS:
1607
1607
1608 lvwph->showHeader();
1608 lvwph->showHeader();
1609
1609
1610− QTRY_VERIFY(!lvwph->m_headerShowAnimation->isRunning());
1610+ QTRY_VERIFY(!lvwph->m_contentYAnimation->isRunning());
1611 QTRY_VERIFY (lvwph->isAtYEnd());
1611 QTRY_VERIFY (lvwph->isAtYEnd());
1612 }
1612 }
1613
1613