I have a QMap
called map
. I initialize this map
with couple of row of data from my database. Now I send this map
to another class which contain GUI classes. In my GUI I have a TableView item. I need to show this map
in any order in this TableView.
I have seen couple of examples, but all of them are for one vector which has only one field. And they used another class to form the view. I wondered if anyone has done this before and can help me with that.
Wrap the QMap
in a subclass of QAbstractTableModel
and set it to the view. Following, a basic functional example:
File "mapmodel.h"
#ifndef MAPMODEL_H
#define MAPMODEL_H
#include <QAbstractTableModel>
#include <QMap>
class MapModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum MapRoles {
KeyRole = Qt::UserRole + 1,
ValueRole
};
explicit MapModel(QObject *parent = 0);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
inline void setMap(QMap<int, QString>* map) { _map = map; }
private:
QMap<int, QString>* _map;
};
#endif // MAPMODEL_H
File "mapmodel.cpp"
#include "mapmodel.h"
MapModel::MapModel(QObject *parent) :
QAbstractTableModel(parent)
{
_map = NULL;
}
int MapModel::rowCount(const QModelIndex& parent) const
{
if (_map)
return _map->count();
return 0;
}
int MapModel::columnCount(const QModelIndex & parent) const
{
return 2;
}
QVariant MapModel::data(const QModelIndex& index, int role) const
{
if (!_map)
return QVariant();
if (index.row() < 0 ||
index.row() >= _map->count() ||
role != Qt::DisplayRole) {
return QVariant();
}
if (index.column() == 0)
return _map->keys().at(index.row());
if (index.column() == 1)
return _map->values().at(index.row());
return QVariant();
}
Example of use:
// ...
QMap<int, QString> map;
map.insert(1, "value 1");
map.insert(2, "value 2");
map.insert(3, "value 3");
MapModel mapmodel;
mapmodel.setMap(&map);
YourTableView.setModel(&mapmodel);
// ...
It will show a table view populated as follows:
As @André said the solution relying on QMap
keys()
and values()
methods is not efficient at all and shouldn't be used.
Instead you should use iterators!
so using the same .h
#ifndef MAPMODEL_H
#define MAPMODEL_H
#include <QAbstractTableModel>
#include <QMap>
class MapModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum MapRoles {
KeyRole = Qt::UserRole + 1,
ValueRole
};
explicit MapModel(QObject *parent = 0);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
void setMap(QMap<int, QString>* map);
private:
QMap<int, QString>* _map;
};
#endif // MAPMODEL_H
the cpp would be something like this:
#include "mapmodel.h"
MapModel::MapModel(QObject *parent) :
QAbstractTableModel(parent), _map(nullptr)
{}
void MapModel::setMap(QMap<int, QString>* map)
{
beginModelReset();
_map = map;
endModelReset();
}
int MapModel::rowCount(const QModelIndex& parent) const
{
if (_map)
return _map->count();
return 0;
}
int MapModel::columnCount(const QModelIndex & parent) const
{
return 2;
}
QVariant MapModel::data(const QModelIndex& index, int role) const
{
if (!_map || !index.isValid() || index.row() >= _map->count() || role != Qt::DisplayRole)
return QVariant();
auto it = _map.cbegin();
it += index.row();
if (index.column() == 0)
return it.key();
if (index.column() == 1)
return it.value();
return QVariant();
}
The main change is in MapModel::data
where you use an iterator and as @Claudiu commented, you must use beginModelReset
and endModelReset
in MapModel::setMap
. (to allow you to be able to change the map on your model and signal your Views)
If you want some examples, I've done it for QAbstractListModel
on FamilyModel2
. Here is the header, here the cpp. It is using a wrapper for the Map that you can find here.
Check the constructor FamilyModel2::FamilyModel2
where external signals are connected in order to manage insertion of entries and also emit dataChanged
when your data is updated ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With