Home > Blockchain >  How to efficiently lookup items in QAbstractTableModel::data?
How to efficiently lookup items in QAbstractTableModel::data?

Time:11-03

From what I have seen, Qt documentation and majority of examples online assume that we are happy with (column, row)-based lookup in data(). But what If my table is based on a custom structure? For instance let's have:

struct MyDrive
{
    QString serialNo;
    QString user;
    QString pc;
    QString ipAddress;
    QString category;
};

where serialNo is the key. So any operation uses it for removing/modifying an item, making QMap as an ideal candidate.

But how to connect this structure with QModelIndex's data? QAbstractTableModel::data asks for data with (column,row) as key, making it more suitable for QVector<QVector>> or something similar (somewhere I read I should avoid using containers with non-constant access time (like map) in data()).

I can imagine using, well, a map with QModelIndex as key and serialNo as value, which would be used as key to my (serialNo-based) map but this looks very inefficient -- QModelIndex addresses concrete entry (serialNo, user, pc, ...) after all so we'd be duplicating the same item over and over again. I was also thinking about having a <serialNo, MyDrive*> map but this is just a workaround to an ugly design decision.

I can't believe I'm the first one with this scenario, so how is it usually solved?

CodePudding user response:

You can use QAbstractItemModel::match to find items by serial qt help And enter all the necessary data into the table. This will allow you not to use containers, but how efficient is this a question...

Second solution is subclass AbstractItemModel Reference. Now you can do what you want and use any container by implementing data() function.

CodePudding user response:

I may have misunderstood the issue you are facing but here we go. I'm assuming that you have many instances of MyDrive. Here is an (incomplete) implementation of a QAbstractTableModel subclass. The trick is to pass the right instance of MyDrive to the appropriate QModelIndex. When you later modify or access data from that index, you no longer really need to use the serialNo anymore as the internal pointer of that index is the MyDrive instance you passed when creating that index:

class MyTable : public QAbstractTableModel
{
public:
    
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
    {
        auto* my_drive = static_cast<MyDrive*>(index.internalPointer());
        auto drive_key = my_drive->serialNo;
        // use the key if you desire for lookups etc
        //...
        //        return your data;
    }
    
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
    {
        auto* my_drive = static_cast<MyDrive*>(index.internalPointer());
        auto drive_key = my_drive->serialNo;
        // use they key again if you like
    }
    
    QModelIndex index(int row, int column, const QModelIndex &parent) const
    {
        // insert checks here for parent and to ensure row and column are within appropriate bounds etc
        // your returned index will now store your MyDrive instance which you will later access from the data and setData methods
        return createIndex(row, column, m_data   row);
    }
    
private:
    
    // array of MyDrive instances
    MyDrive* m_data;
};
  • Related