Skip to content

Commit 593501a

Browse files
committedJan 23, 2019
Add button, menu and shortcut to expand/collapse
1 parent f22a7a9 commit 593501a

File tree

5 files changed

+190
-37
lines changed

5 files changed

+190
-37
lines changed
 

‎.gitlab-ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ stages:
1616

1717
lint:
1818
stage: lint
19-
script:
19+
script:
2020
- qmllint desktop/qml/*.qml
2121

2222
build:

‎core/locationmodel.cpp

+58-10
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ bool LocationModel::addLocations(const QString &baseName, int length, double wid
224224
}
225225
}
226226
QSqlDatabase::database().commit();
227+
depthChanged();
227228

228229
return true;
229230
}
@@ -299,25 +300,72 @@ bool LocationModel::removeIndexes(const QModelIndexList &indexList)
299300
}
300301
location->removeList(idList);
301302

303+
depthChanged();
302304
return tmodel->removeIndexes(sourceIndexList);
303305
}
304306

305-
/** Return a list of all QModelIndex of location tree. */
306-
QModelIndexList LocationModel::treeIndexes() const
307+
/*!
308+
* Return a list of all QModelIndex of location tree.
309+
*
310+
* If \a depth is greater or equal to 0, only indexes of this depth
311+
* will be return, including their parents if \a includeParent is true.
312+
*/
313+
QModelIndexList LocationModel::treeIndexes(int depth, bool includeParent) const
307314
{
308315
QModelIndex root;
309-
QModelIndexList treeList;
316+
QModelIndexList tmpList;
317+
QModelIndexList indexList;
318+
QMap<QModelIndex, int> indexDepth;
319+
320+
for (int row = 0; row < rowCount(root); row++) {
321+
QModelIndex idx = index(row, 0, root);
322+
tmpList.push_back(idx);
323+
indexDepth[idx] = 0;
324+
if (depth < 0 || indexDepth[idx] == depth || (indexDepth[idx] < depth && includeParent))
325+
indexList.push_back(idx);
326+
}
310327

311-
for (int row = 0; row < rowCount(root); row++)
312-
treeList.push_back(index(row, 0, root));
328+
for (int i = 0; i < tmpList.length(); i++) {
329+
QModelIndex parent = tmpList[i];
330+
for (int row = 0; row < rowCount(parent); row++) {
331+
QModelIndex idx = index(row, 0, parent);
332+
indexDepth[idx] = indexDepth.value(parent) + 1;
333+
if (indexDepth[idx] < depth)
334+
tmpList.push_back(idx);
335+
if (depth < 0 || indexDepth[idx] == depth || (indexDepth[idx] < depth && includeParent))
336+
indexList.push_back(idx);
337+
}
338+
}
313339

314-
for (int i = 0; i < treeList.length(); i++) {
315-
QModelIndex parent = treeList[i];
316-
for (int row = 0; row < rowCount(parent); row++)
317-
treeList.push_back(index(row, 0, parent));
340+
return indexList;
341+
}
342+
343+
int LocationModel::depth() const
344+
{
345+
QModelIndex root;
346+
QModelIndexList tmpList;
347+
QMap<QModelIndex, int> indexDepth;
348+
int d = 0;
349+
350+
for (int row = 0; row < rowCount(root); row++) {
351+
QModelIndex idx = index(row, 0, root);
352+
tmpList.push_back(idx);
353+
indexDepth[idx] = 0;
354+
}
355+
356+
for (int i = 0; i < tmpList.length(); i++) {
357+
QModelIndex parent = tmpList[i];
358+
for (int row = 0; row < rowCount(parent); row++) {
359+
QModelIndex idx = index(row, 0, parent);
360+
indexDepth[idx] = indexDepth.value(parent) + 1;
361+
tmpList.push_back(idx);
362+
363+
if (indexDepth[idx] > d)
364+
d = indexDepth[idx];
365+
}
318366
}
319367

320-
return treeList;
368+
return d;
321369
}
322370

323371
/** Return a list of all QModelIndex of location tree. */

‎core/locationmodel.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class CORESHARED_EXPORT LocationModel : public SortFilterProxyModel
3333

3434
Q_PROPERTY(bool showOnlyEmptyLocations READ showOnlyEmptyLocations WRITE
3535
setShowOnlyEmptyLocations NOTIFY showOnlyEmptyLocationsChanged)
36+
Q_PROPERTY(int depth READ depth NOTIFY depthChanged)
3637

3738
public:
3839
LocationModel(QObject *parent = nullptr, const QString &tableName = "location");
@@ -56,7 +57,8 @@ class CORESHARED_EXPORT LocationModel : public SortFilterProxyModel
5657
Q_INVOKABLE bool duplicateLocations(const QModelIndexList &indexList);
5758
Q_INVOKABLE bool updateIndexes(const QVariantMap &map, const QModelIndexList &indexList);
5859
Q_INVOKABLE bool removeIndexes(const QModelIndexList &indexList);
59-
Q_INVOKABLE QModelIndexList treeIndexes() const;
60+
Q_INVOKABLE QModelIndexList treeIndexes(int depth = -1, bool includeParent = true) const;
61+
Q_INVOKABLE int depth() const;
6062
Q_INVOKABLE QItemSelection treeSelection() const;
6163
Q_INVOKABLE QModelIndexList treeHasIds(const QVariantList &idList) const;
6264
Q_INVOKABLE virtual void refresh() override;
@@ -69,6 +71,7 @@ class CORESHARED_EXPORT LocationModel : public SortFilterProxyModel
6971

7072
signals:
7173
void showOnlyEmptyLocationsChanged();
74+
void depthChanged();
7275

7376
private:
7477
bool m_showOnlyEmptyLocations;

‎desktop/qml/LocationView.qml

+36-21
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Item {
4141
property alias draggedPlantingId: treeView.draggedPlantingId
4242

4343
property LocationModel locationModel
44+
property alias treeDepth: locationModel.depth
4445
property int treeViewHeight: treeView.flickableItem.contentHeight
4546
property int treeViewWidth: treeView.implicitWidth
4647
property bool alwaysShowCheckbox: false
@@ -99,8 +100,16 @@ Item {
99100
}
100101
}
101102

102-
function collapseAll() {
103-
var indexList = locationModel.treeIndexes();
103+
function expandAll(depth) {
104+
var indexList = locationModel.treeIndexes(depth);
105+
for (var i = 0; i < indexList.length; i++) {
106+
var index = indexList[i];
107+
treeView.expand(index);
108+
}
109+
}
110+
111+
function collapseAll(depth) {
112+
var indexList = locationModel.treeIndexes(depth, false);
104113
for (var i = 0; i < indexList.length; i++) {
105114
var index = indexList[i];
106115
treeView.collapse(index);
@@ -289,29 +298,35 @@ Item {
289298
ThinDivider { anchors { bottom: parent.bottom; left: parent.left; right: parent.right } }
290299
}
291300

292-
ScrollView {
293-
id: scrollView
294-
anchors {
295-
top: headerRectangle.bottom
296-
left: parent.left
297-
right: parent.right
298-
bottom: parent.bottom
299-
}
301+
// ScrollView {
302+
// id: scrollView
303+
// anchors {
304+
// top: headerRectangle.bottom
305+
// left: parent.left
306+
// right: parent.right
307+
// bottom: parent.bottom
308+
// }
300309

301-
clip: true
310+
// clip: true
302311

303-
Flickable {
304-
id: flickable
312+
// Flickable {
313+
// id: flickable
305314

306-
boundsBehavior: Flickable.StopAtBounds
307-
contentHeight: treeView.flickableItem.contentHeight
308-
contentWidth: width
315+
// boundsBehavior: Flickable.StopAtBounds
316+
// contentHeight: treeView.flickableItem.contentHeight
317+
// contentWidth: width
309318

310-
ScrollBar.vertical: ScrollBar { id: verticalScrollBar }
319+
// ScrollBar.vertical: ScrollBar { id: verticalScrollBar }
311320

312321
Controls1.TreeView {
313322
id: treeView
314-
anchors.fill: parent
323+
// anchors.fill: parent
324+
anchors {
325+
top: headerRectangle.bottom
326+
left: parent.left
327+
right: parent.right
328+
bottom: parent.bottom
329+
}
315330

316331
property int draggedPlantingId: -1
317332
property date plantingDate: Planting.plantingDate(draggedPlantingId)
@@ -336,7 +351,7 @@ Item {
336351

337352
frameVisible: false
338353
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
339-
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
354+
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
340355
implicitWidth: headerRectangle.implicitWidth + 80
341356

342357
Controls1.TableViewColumn {
@@ -684,5 +699,5 @@ Item {
684699
}
685700
}
686701
}
687-
}
688-
}
702+
// }
703+
//}

‎desktop/qml/LocationsPage.qml

+91-4
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,41 @@ Page {
106106
onActivated: seasonSpinBox.previousYear();
107107
}
108108

109+
Shortcut {
110+
sequence: "Shift+A"
111+
enabled: navigationIndex === 2 && filterField.visible && !addDialog.activeFocus && !editDialog.activeFocus
112+
context: Qt.ApplicationShortcut
113+
onActivated: expandButton.expandLevel(0)
114+
}
115+
116+
Shortcut {
117+
sequence: "Shift+B"
118+
enabled: navigationIndex === 2 && filterField.visible && !addDialog.activeFocus && !editDialog.activeFocus
119+
context: Qt.ApplicationShortcut
120+
onActivated: expandButton.expandLevel(1)
121+
}
122+
123+
Shortcut {
124+
sequence: "Shift+C"
125+
enabled: navigationIndex === 2 && filterField.visible && !addDialog.activeFocus && !editDialog.activeFocus
126+
context: Qt.ApplicationShortcut
127+
onActivated: expandButton.expandLevel(2)
128+
}
129+
130+
Shortcut {
131+
sequence: "Shift+D"
132+
enabled: navigationIndex === 2 && filterField.visible && !addDialog.activeFocus && !editDialog.activeFocus
133+
context: Qt.ApplicationShortcut
134+
onActivated: expandButton.expandLevel(3)
135+
}
136+
137+
Shortcut {
138+
sequence: "Shift+E"
139+
enabled: navigationIndex === 2 && filterField.visible && !addDialog.activeFocus && !editDialog.activeFocus
140+
context: Qt.ApplicationShortcut
141+
onActivated: expandButton.expandLevel(4)
142+
}
143+
109144
onEditModeChanged: {
110145
if (!editMode) {
111146
locationView.clearSelection();
@@ -234,6 +269,54 @@ Page {
234269
}
235270
}
236271

272+
RoundButton {
273+
id: expandButton
274+
flat: true
275+
text: "\ue313"
276+
font.family: "Material Icons"
277+
font.pixelSize: 24
278+
onClicked: expandMenu.open();
279+
280+
property int depth: locationView.treeDepth
281+
property var expandBoolList: ({})
282+
283+
function expandLevel(level) {
284+
if (expandBoolList[level]) {
285+
locationView.collapseAll(level, false)
286+
} else {
287+
locationView.expandAll(level)
288+
for (var i = 0; i < level; i++)
289+
expandBoolList[i] = true
290+
}
291+
expandBoolList[level] = !expandBoolList[level]
292+
expandBoolListChanged();
293+
}
294+
295+
Component.onCompleted: {
296+
for (var i; i < depth; i++)
297+
expandBoolList[i+1] = false
298+
}
299+
300+
ToolTip.text: qsTr("Expand and collapse location levels")
301+
ToolTip.delay: Units.shortDuration
302+
ToolTip.visible: hovered
303+
304+
Menu {
305+
id: expandMenu
306+
y: expandButton.height
307+
308+
Repeater {
309+
model: expandButton.depth
310+
MenuItem {
311+
text: index + 1
312+
checkable: true
313+
checked: expandButton.expandBoolList[index]
314+
onTriggered: expandButton.expandLevel(index)
315+
}
316+
}
317+
}
318+
}
319+
237320
Button {
238321
id: duplicateButton
239322
flat: true
@@ -387,7 +470,6 @@ Page {
387470
// visible: unassignedPlantingsCheckbox.checked & !editMode
388471
visible: !editMode
389472

390-
391473
padding: 0
392474
Layout.fillWidth: true
393475
// Layout.fillHeight: true
@@ -407,7 +489,7 @@ Page {
407489

408490
RoundButton {
409491
id: showPlantingPaneButton
410-
text: ">"
492+
z: -1
411493
Material.background: "white"
412494
width: 60
413495
height: width
@@ -434,11 +516,16 @@ Page {
434516
}
435517
}
436518

519+
Rectangle {
520+
color: "white"
521+
anchors.fill: parent
522+
}
523+
437524
Column {
438525
id: emptyPlantingStateColumn
439-
z: 1
440526
spacing: Units.smallSpacing
441-
visible: !plantingsView.rowsNumber
527+
visible: !plantingsView.rowsNumber && showPlantingsPane
528+
z:2
442529
anchors {
443530
centerIn: parent
444531
}

0 commit comments

Comments
 (0)