Skip to content

Commit 103b819

Browse files
Added empty state
Modified MMDrawer to animate on height changes Updated the value map model to update the config during a load Modified MMListMultiSelect to expand when the search is tapped Added spinner when loading more items
1 parent cd5ad06 commit 103b819

12 files changed

Lines changed: 180 additions & 70 deletions

app/filter/uniquevaluesfiltermodel.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ void UniqueValuesFilterModel::populate()
9595

9696
QgsVectorLayer *layerClone = layer->clone();
9797

98+
mIsLoading = true;
99+
emit isLoadingChanged();
100+
98101
mResultWatcher.setFuture( QtConcurrent::run( &UniqueValuesFilterModel::loadUniqueValues, this, layerClone, fieldIndex ) );
99102
}
100103

@@ -128,8 +131,16 @@ void UniqueValuesFilterModel::onLoadingFinished()
128131
mItems.clear();
129132
mItems = mResultWatcher.result();
130133

131-
// TODO: do we need boolean to indicate if the model is loading?
132134
// TODO: measure how long it takes to move results from future result to mItems ~ there might be a way to avoid the copy
133135

134136
endResetModel();
137+
emit countChanged();
138+
139+
mIsLoading = false;
140+
emit isLoadingChanged();
141+
}
142+
143+
bool UniqueValuesFilterModel::isLoading() const
144+
{
145+
return mIsLoading;
135146
}

app/filter/uniquevaluesfiltermodel.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class UniqueValuesFilterModel : public QAbstractListModel
2424

2525
Q_PROPERTY( QString layerId READ layerId WRITE setLayerId NOTIFY layerIdChanged )
2626
Q_PROPERTY( QString fieldName READ fieldName WRITE setFieldName NOTIFY fieldNameChanged )
27+
Q_PROPERTY( bool isLoading READ isLoading NOTIFY isLoadingChanged )
28+
Q_PROPERTY( int count READ rowCount NOTIFY countChanged )
2729

2830
public:
2931
explicit UniqueValuesFilterModel( QObject *parent = nullptr );
@@ -38,11 +40,15 @@ class UniqueValuesFilterModel : public QAbstractListModel
3840
QString fieldName() const;
3941
void setFieldName( const QString &fieldName );
4042

43+
bool isLoading() const;
44+
4145
Q_INVOKABLE void populate();
4246

4347
signals:
4448
void layerIdChanged();
4549
void fieldNameChanged();
50+
void isLoadingChanged();
51+
void countChanged();
4652

4753
public slots:
4854
void onLoadingFinished();
@@ -55,6 +61,7 @@ class UniqueValuesFilterModel : public QAbstractListModel
5561

5662
QVariantList mItems;
5763
QFutureWatcher<QVariantList> mResultWatcher;
64+
bool mIsLoading = false;
5865
};
5966

6067
#endif // UNIQUEVALUESFILTERMODEL_H

app/filter/valuemapfiltermodel.cpp

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99

1010
#include "valuemapfiltermodel.h"
1111

12+
#include <QtConcurrentRun>
13+
1214
ValueMapFilterModel::ValueMapFilterModel( QObject *parent )
1315
: QAbstractListModel( parent )
1416
{
17+
connect( &mResultWatcher, &QFutureWatcher<QList<Item>>::finished, this, &ValueMapFilterModel::onLoadingFinished );
1518
}
1619

1720
int ValueMapFilterModel::rowCount( const QModelIndex &parent ) const
@@ -51,6 +54,11 @@ QVariantMap ValueMapFilterModel::config() const
5154
return mConfig;
5255
}
5356

57+
bool ValueMapFilterModel::isLoading() const
58+
{
59+
return mIsLoading;
60+
}
61+
5462
void ValueMapFilterModel::setConfig( const QVariantMap &config )
5563
{
5664
if ( mConfig == config )
@@ -59,17 +67,29 @@ void ValueMapFilterModel::setConfig( const QVariantMap &config )
5967
mConfig = config;
6068
emit configChanged();
6169

62-
populate();
70+
if ( mResultWatcher.isRunning() )
71+
{
72+
mHasPendingLoad = true;
73+
return;
74+
}
75+
76+
startLoad();
6377
}
6478

65-
void ValueMapFilterModel::populate()
79+
void ValueMapFilterModel::startLoad()
6680
{
67-
beginResetModel();
81+
mIsLoading = true;
82+
emit isLoadingChanged();
6883

69-
mItems.clear();
84+
mResultWatcher.setFuture( QtConcurrent::run( &ValueMapFilterModel::loadItems, mConfig ) );
85+
}
86+
87+
QList<ValueMapFilterModel::Item> ValueMapFilterModel::loadItems( const QVariantMap &config )
88+
{
89+
const QVariantList mapList = config.value( QStringLiteral( "map" ) ).toList();
7090

71-
const QVariantList mapList = mConfig.value( QStringLiteral( "map" ) ).toList();
72-
mItems.reserve( mapList.size() );
91+
QList<Item> items;
92+
items.reserve( mapList.size() );
7393

7494
for ( const QVariant &entry : mapList )
7595
{
@@ -83,8 +103,29 @@ void ValueMapFilterModel::populate()
83103
item.description = entryMap.constBegin().key();
84104
item.key = entryMap.constBegin().value().toString();
85105

86-
mItems.append( item );
106+
items.append( item );
87107
}
88108

109+
return items;
110+
}
111+
112+
void ValueMapFilterModel::onLoadingFinished()
113+
{
114+
beginResetModel();
115+
116+
mItems = mResultWatcher.result();
117+
89118
endResetModel();
119+
emit countChanged();
120+
121+
if ( mHasPendingLoad )
122+
{
123+
mHasPendingLoad = false;
124+
startLoad();
125+
}
126+
else
127+
{
128+
mIsLoading = false;
129+
emit isLoadingChanged();
130+
}
90131
}

app/filter/valuemapfiltermodel.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,21 @@
1111
#define VALUEMAPFILTERMODEL_H
1212

1313
#include <QAbstractListModel>
14+
#include <QFutureWatcher>
1415
#include <QtQml/qqmlregistration.h>
1516

1617
/**
1718
* Populates a list model from a QGIS ValueMap editor widget config.
18-
* Exposes TextRole (display label) and ValueRole (stored key) for each entry.
19+
* Exposes DisplayRole (display label) and KeyRole (stored key) for each entry.
1920
*/
2021
class ValueMapFilterModel : public QAbstractListModel
2122
{
2223
Q_OBJECT
2324
QML_ELEMENT
2425

2526
Q_PROPERTY( QVariantMap config READ config WRITE setConfig NOTIFY configChanged )
27+
Q_PROPERTY( bool isLoading READ isLoading NOTIFY isLoadingChanged )
28+
Q_PROPERTY( int count READ rowCount NOTIFY countChanged )
2629

2730
public:
2831
enum Roles
@@ -34,6 +37,8 @@ class ValueMapFilterModel : public QAbstractListModel
3437
explicit ValueMapFilterModel( QObject *parent = nullptr );
3538
~ValueMapFilterModel() override = default;
3639

40+
bool isLoading() const;
41+
3742
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
3843
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
3944
QHash<int, QByteArray> roleNames() const override;
@@ -43,19 +48,28 @@ class ValueMapFilterModel : public QAbstractListModel
4348

4449
signals:
4550
void configChanged();
51+
void isLoadingChanged();
52+
void countChanged();
4653

47-
private:
48-
void populate();
54+
private slots:
55+
void onLoadingFinished();
4956

57+
private:
5058
struct Item
5159
{
5260
QString description;
5361
QString key;
5462
};
5563

64+
static QList<Item> loadItems( const QVariantMap &config );
65+
void startLoad();
66+
5667
QVariantMap mConfig;
5768

5869
QList<Item> mItems;
70+
QFutureWatcher<QList<Item>> mResultWatcher;
71+
bool mIsLoading = false;
72+
bool mHasPendingLoad = false;
5973
};
6074

6175
#endif // VALUEMAPFILTERMODEL_H

app/layerfeaturesmodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class LayerFeaturesModel : public FeaturesModel
7373
int featuresLimit() const;
7474
QgsVectorLayer *layer() const;
7575
QString searchExpression() const;
76+
bool fetchingResults() const { return mFetchingResults; }
7677

7778
void setSearchExpression( const QString &searchExpression );
7879
void setLayer( QgsVectorLayer *newLayer );

app/qml/components/MMDrawer.qml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,21 @@ Drawer {
4343
layer.effect: MMShadow {}
4444

4545
Rectangle {
46-
color: __style.polarColor
4746
width: parent.width
4847
height: parent.height / 2
4948
y: parent.height / 2
49+
50+
color: __style.polarColor
5051
}
5152
}
5253

5354
contentItem: Column {
5455
id: mainColumn
5556

5657
anchors.fill: parent
58+
5759
spacing: 0
58-
focus : true
60+
focus: true
5961

6062
Keys.onReleased: function( event ) {
6163
if ( event.key === Qt.Key_Back || event.key === Qt.Key_Escape ) {
@@ -74,9 +76,7 @@ Drawer {
7476

7577
width: parent.width
7678

77-
onCloseClicked: {
78-
root.close()
79-
}
79+
onCloseClicked: root.close()
8080
}
8181

8282
Item {
@@ -98,7 +98,6 @@ Drawer {
9898
let leftSideOverflow = ( parent.width - minSidesPadding - __style.maxPageWidth ) / 2
9999
return leftSideOverflow + minLeftPadding
100100
}
101-
102101
return minLeftPadding
103102
}
104103

@@ -107,7 +106,6 @@ Drawer {
107106
let rightSideOverflow = ( parent.width - minSidesPadding - __style.maxPageWidth ) / 2
108107
return rightSideOverflow + minRightPadding
109108
}
110-
111109
return minRightPadding
112110
}
113111

@@ -123,7 +121,12 @@ Drawer {
123121
id: bottomSpacer
124122

125123
width: parent.width
126-
height: root.drawerBottomMargin > 0 ? __style.safeAreaBottom + root.drawerBottomMargin :0
124+
height: root.drawerBottomMargin > 0 ? __style.safeAreaBottom + root.drawerBottomMargin : 0
127125
}
128126
}
127+
128+
// add behaviour on height
129+
Behavior on implicitHeight {
130+
PropertyAnimation { duration: 200; easing.type: Easing.InOutQuad }
131+
}
129132
}

0 commit comments

Comments
 (0)