Skip to content

Commit

Permalink
Value map combobox filter
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 committed Apr 17, 2024
1 parent 1339088 commit 8ccd7c7
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 115 deletions.
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ set(QFIELD_CORE_SRCS
tracker.cpp
trackingmodel.cpp
valuemapmodel.cpp
valuemapmodelbase.cpp
vertexmodel.cpp
viewstatus.cpp)

Expand Down Expand Up @@ -215,6 +216,7 @@ set(QFIELD_CORE_HDRS
tracker.h
trackingmodel.h
valuemapmodel.h
valuemapmodelbase.h
vertexmodel.h
viewstatus.h
${CMAKE_CURRENT_BINARY_DIR}/qfield.h)
Expand Down
104 changes: 13 additions & 91 deletions src/core/valuemapmodel.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/***************************************************************************
valuemapmodel.cpp
valuemapmodelbase.cpp
-------------------
begin : March 2019
Expand All @@ -16,114 +16,36 @@
* *
***************************************************************************/

#include "qgsvaluemapfieldformatter.h"
#include "valuemapmodel.h"

#include <QDebug>
#include "valuemapmodelbase.h"

ValueMapModel::ValueMapModel( QObject *parent )
: QAbstractListModel( parent )
{
}

QVariant ValueMapModel::map() const
{
return mConfiguredMap;
}

void ValueMapModel::setMap( const QVariant &map )
: QSortFilterProxyModel( parent )
, mSourceModel( new ValueMapModelBase( this ) )
{
mMap.clear();
// QGIS 3
const QVariantList list = map.toList();
if ( !list.empty() )
{
beginInsertRows( QModelIndex(), 0, list.size() );

for ( const QVariant &item : list )
{
const QVariantMap mapItem = item.toMap();

const QString key = mapItem.firstKey();
const QVariant value = mapItem.value( key );

mMap.append( qMakePair( value, key ) );
}
endInsertRows();
}
else // QGIS 2 compat
{
const QVariantMap valueMap = map.toMap();
if ( !valueMap.empty() )
{
beginInsertRows( QModelIndex(), 0, valueMap.size() );
setSourceModel( mSourceModel );

QMapIterator<QString, QVariant> i( valueMap );
while ( i.hasNext() )
{
i.next();
const QString key = i.key();
const QVariant value = i.value();
setFilterRole( ValueRole );

mMap.append( qMakePair( value, key ) );
}
endInsertRows();
}
}

mConfiguredMap = map;
emit mapChanged();
}

int ValueMapModel::rowCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return mMap.size();
connect( mSourceModel, &ValueMapModelBase::mapChanged, this, &ValueMapModel::mapChanged );
}

QVariant ValueMapModel::data( const QModelIndex &index, int role ) const
QVariant ValueMapModel::map() const
{
if ( role == KeyRole )
return mMap.at( index.row() ).first;
else
return mMap.at( index.row() ).second;
return mSourceModel->map();
}

QHash<int, QByteArray> ValueMapModel::roleNames() const
void ValueMapModel::setMap( const QVariant &map )
{
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();

roles[KeyRole] = "key";
roles[ValueRole] = "value";

return roles;
mSourceModel->setMap( map );
}

int ValueMapModel::keyToIndex( const QVariant &key ) const
{
int i = 0;
for ( const auto &item : mMap )
{
if ( item.first.toString() == key.toString() )
{
return i;
}
++i;
}
return -1;
return mSourceModel->keyToIndex( key );
}

QVariant ValueMapModel::keyForValue( const QString &value ) const
{
QVariant result;

auto match = std::find_if( mMap.begin(), mMap.end(), [&value]( const QPair<QVariant, QString> &x ) { return x.second == value; } );

if ( match != mMap.end() )
result = match->first;

if ( result == QgsValueMapFieldFormatter::NULL_VALUE )
result = QVariant();

return result;
return mSourceModel->keyForValue( value );
}
29 changes: 9 additions & 20 deletions src/core/valuemapmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,15 @@
* *
***************************************************************************/


#ifndef VALUEMAPMODEL_H
#define VALUEMAPMODEL_H

#include <QAbstractListModel>
#include <QVariant>
#include "valuemapmodelbase.h"

#include <QSortFilterProxyModel>


/**
* A model that manages the key/value pairs for a ValueMap widget.
*/
class ValueMapModel : public QAbstractListModel
class ValueMapModel : public QSortFilterProxyModel
{
Q_OBJECT

Expand All @@ -39,8 +37,6 @@ class ValueMapModel : public QAbstractListModel
*/
Q_PROPERTY( QVariant valueMap READ map WRITE setMap NOTIFY mapChanged )

Q_ENUMS( ValueMapRoles )


public:
//! The roles provided by this model
Expand All @@ -50,26 +46,20 @@ class ValueMapModel : public QAbstractListModel
ValueRole //!< obtain the value
};

/**
* Create a new value map model
*/
Q_ENUM( ValueMapRoles )

explicit ValueMapModel( QObject *parent = nullptr );

/**
* The map, see the property description
*/
QVariant map() const;

/**
* The map, see the property description
*/
void setMap( const QVariant &map );

int rowCount( const QModelIndex &parent = QModelIndex() ) const override;

QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;

QHash<int, QByteArray> roleNames() const override;

/**
* Returns the row (index) of a key or -1 if not found.
*/
Expand All @@ -87,8 +77,7 @@ class ValueMapModel : public QAbstractListModel
void mapChanged();

private:
QList<QPair<QVariant, QString>> mMap;
QVariant mConfiguredMap;
ValueMapModelBase *mSourceModel = nullptr;
};

#endif // VALUEMAPMODEL_H
130 changes: 130 additions & 0 deletions src/core/valuemapmodelbase.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/***************************************************************************
valuemapmodelbase.cpp
-------------------
begin : March 2019
copyright : (C) 2019 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsvaluemapfieldformatter.h"
#include "valuemapmodel.h"
#include "valuemapmodelbase.h"

#include <QDebug>

ValueMapModelBase::ValueMapModelBase( QObject *parent )
: QAbstractListModel( parent )
{
}

QVariant ValueMapModelBase::map() const
{
return mConfiguredMap;
}

void ValueMapModelBase::setMap( const QVariant &map )
{
mMap.clear();
// QGIS 3
const QVariantList list = map.toList();
if ( !list.empty() )
{
beginInsertRows( QModelIndex(), 0, list.size() );

for ( const QVariant &item : list )
{
const QVariantMap mapItem = item.toMap();

const QString &key = mapItem.firstKey();
const QVariant value = mapItem.value( key );

mMap.append( qMakePair( value, key ) );
}
endInsertRows();
}
else // QGIS 2 compat
{
const QVariantMap valueMap = map.toMap();
if ( !valueMap.empty() )
{
beginInsertRows( QModelIndex(), 0, valueMap.size() );

QMapIterator<QString, QVariant> i( valueMap );
while ( i.hasNext() )
{
i.next();
const QString key = i.key();
const QVariant value = i.value();

mMap.append( qMakePair( value, key ) );
}
endInsertRows();
}
}

mConfiguredMap = map;
emit mapChanged();
}

int ValueMapModelBase::rowCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return mMap.size();
}

QVariant ValueMapModelBase::data( const QModelIndex &index, int role ) const
{
if ( role == ValueMapModel::KeyRole )
return mMap.at( index.row() ).first;
else
return mMap.at( index.row() ).second;
}

QHash<int, QByteArray> ValueMapModelBase::roleNames() const
{
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();

roles[ValueMapModel::KeyRole] = "key";
roles[ValueMapModel::ValueRole] = "value";

return roles;
}

int ValueMapModelBase::keyToIndex( const QVariant &key ) const
{
int i = 0;
for ( const auto &item : mMap )
{
if ( item.first.toString() == key.toString() )
{
return i;
}
++i;
}
return -1;
}

QVariant ValueMapModelBase::keyForValue( const QString &value ) const
{
QVariant result;

auto match = std::find_if( mMap.begin(), mMap.end(), [&value]( const QPair<QVariant, QString> &x ) { return x.second == value; } );

if ( match != mMap.end() )
result = match->first;

if ( result == QgsValueMapFieldFormatter::NULL_VALUE )
result = QVariant();

return result;
}

0 comments on commit 8ccd7c7

Please sign in to comment.