C++ (Qt)class HashModel : public QAbstractTableModel{ Q_OBJECT private: int m_empty; QHash<QString, QString> m_hash; public: HashModel(QObject *p=0) : QAbstractTableModel(p), m_empty(0) {} // ..... implementation ..... };
C++ (Qt)QString HashModel::id2key(const QModelIndex& id) const{ if(!id.isValid()) return QString(); return row2key(id.row());} QString HashModel::row2key(int row) const{ if(row >= m_hash.count()) return QString(); return m_hash.keys().at(row);}
C++ (Qt)QVariant HashModel::data(const QModelIndex &id, int role) const{ if (!id.isValid()) return QVariant(); switch(role) { case Qt::EditRole: case Qt::DisplayRole: QString key = id2key(id); if(key.isNull()) return key; switch (id.column()) { case 0: return key; case 1: return m_hash[key]; } return QVariant(); // .... } return QVariant();}
C++ (Qt)bool HashModel::insertRows(int row, int count, const QModelIndex &parent){ if(parent.isValid()) return false; beginInsertRows(parent, row, row+count-1); m_empty+=count; endInsertRows(); return true;}
C++ (Qt)bool HashModel::insertItem(const QString& key, const QString& val){ if(key.isEmpty() || m_hash.contains(key)) return false; beginInsertRows(QModelIndex(), m_hash.count(), m_hash.count()); m_hash[key] = val; endInsertRows(); return true;}
C++ (Qt)bool HashModel::insertItem(const QString& key, const QString& val){ if(key.isEmpty() || m_hash.contains(key)) return false; insertRow(m_hash.count()); Q_ASSERT(m_empty>0); m_empty--; m_hash[key] = val; emit dataChanged(createIndex(0,0), createIndex(m_hash.count()-1,1)); return true;}
C++ (Qt)bool HashModel::insertItem(const QString& key, const QString& val){ if(key.isEmpty() || hasItem(key)) return false; if(m_empty > 0) { insertToEmpty(key, val); } else { insertToHash(key, val); } return true;} void HashModel::insertToEmpty(const QString& key, const QString& val){ Q_ASSERT(m_empty > 0); m_empty--; m_hash[key] = val; emit dataChanged(createIndex(0,0), createIndex(m_hash.count()-1,1));} void HashModel::insertToHash(const QString& key, const QString& val){ Q_ASSERT(!hasItem(key)); beginInsertRows(QModelIndex(), m_hash.count(), m_hash.count()); m_hash[key] = val; endInsertRows();}
C++ (Qt)bool HashModel::setData(const QModelIndex &id, const QVariant &val, int role){ if(!id.isValid()) return false; if(role != Qt::EditRole) return false; QString key = id2key(id); QString sval = val.value<QString>(); switch(id.column()) { case 1: if(key.isNull()) return false; m_hash[key] = sval; emit dataChanged(id, id); return true; case 0: if(hasItem(sval)) return false; QString rval = ""; if(!key.isNull()) { rval = m_hash[key]; m_hash.remove(key); m_empty++; } insertToEmpty(sval, rval); return true; } return false;}
C++ (Qt)bool HashModel::setItem(const QString& key, const QString& val){ if(key.isEmpty() || !hasItem(key)) return false; m_hash[key] = val; emit dataChanged(createIndex(0,1), createIndex(m_hash.count()-1,1)); return true;}
C++ (Qt)QModelIndexList HashModel::match(const QModelIndex &id, int role, const QVariant &val, int hints, Qt::MatchFlags fl) const{ if(id.column() == 0 && role == Qt::DisplayRole) { int rf = fl&0x0F; if(rf == Qt::MatchExactly || rf == Qt::MatchFixedString && fl&Qt::MatchCaseSensitive) { QString key = val.value<QString>(); QModelIndexList res; if(hasItem(key)) { int start = fl&Qt::MatchWrap ? 0 : id.row(); int pos = m_hash.keys().indexOf(key, start); if(pos != -1) res.append(createIndex(pos, id.column())); } return res; } } return QAbstractTableModel::match(id, role, val, hints, fl);}
C++ (Qt)class HashController : public QObject{ Q_OBJECT private: QAbstractItemView *m_view; HashModel *m_model; public: HashController(QAbstractItemView *view); public slots: void insertItem(const QString& key, const QString& val); void removeItem(); };
C++ (Qt)void HashController::insertItem(const QString& key, const QString& val){ if(m_model->hasItem(key)) { m_model->setItem(key, val); } else { m_model->insertItem(key, val); }}
C++ (Qt)void HashController::removeItem(){ QModelIndex id = m_view->currentIndex(); if(!id.isValid()) return; m_model->removeRow(id.row());}
C++ (Qt)void HashController::insertItem(const QString& key, const QString& val){ QModelIndexList ml = m_model->match(m_model->index(0,0), Qt::DisplayRole, key, -1, Qt::MatchExactly); if(ml.empty()) { int fin = m_model->rowCount(); m_model->insertRow(fin); QModelIndex ki = m_model->index(fin, 0); m_model->setData(ki, key); QModelIndexList ml2 = m_model->match(m_model->index(0,0), Qt::DisplayRole, key, -1, Qt::MatchExactly); QModelIndex ki2 = ml2.first(); QModelIndex kv2 = m_model->index(ki2.row(), 1); m_model->setData(kv2, val); } else { QModelIndex ki = ml.first(); QModelIndex kv = m_model->index(ki.row(), 1); m_model->setData(kv, val); }}
C++ (Qt) for(int i=row; i<row+count; i++) { m_empty++; }