|
что-то я поторопился...
Упростил задачу до нельзя.
Есть две таблицы PROFILE_SYSTEMS и PROFILES структура PROFILE_SYSTEMs: system_id INT PK NN AI, name TEXT структура PROFILES: profile_id INT PK NN AI, system_id INT NN, name TEXT
соответственно вырисовывается иерархия - корень - PROFILE_SYSTEMS.system_id - потомок PROFILES.profile_id Сделал модель, которая содержит в себе две QSqlTableModel Вот код модели:
Заголовочный файл:
class ProfilesModel : public QAbstractItemModel { Q_OBJECT
private: QSqlTableModel *m_systemsModel; QSqlTableModel *m_profilesModel;
enum Tables{ SystemsTable, ProfilesTable };
struct InternalId { QModelIndex parentIndex; Tables table;
bool operator==( const InternalId &other ) const { return parentIndex == other.parentIndex && table == other.table; } };
enum SystemsTableColumns{ s_SystemId, s_Name }; enum ProfilesTableColumns{ p_ProfileId, p_SystemId, p_Name };
mutable QList<InternalId> m_internalIds;
void setCurrentSystem( const QModelIndex &system ) const;
public: explicit ProfilesModel(QObject *parent = 0);
virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex parent ( const QModelIndex & index ) const;
virtual bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
virtual bool insertRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex() ); virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual int columnCount(const QModelIndex &parent) const;
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const;
};
#endif // PROFILESMODEL_H
Исходный код:
ProfilesModel::ProfilesModel(QObject *parent) : QAbstractItemModel(parent) { m_systemsModel = new QSqlTableModel(this); m_systemsModel->setTable("profile_systems"); m_systemsModel->setEditStrategy( QSqlTableModel::OnFieldChange ); m_systemsModel->select();
m_profilesModel = new QSqlTableModel(this); m_profilesModel->setTable("profiles"); m_profilesModel->setEditStrategy( QSqlTableModel::OnFieldChange ); m_profilesModel->select();
}
QModelIndex ProfilesModel::index(int row, int column, const QModelIndex &parent) const { InternalId id;
if( parent.isValid() ) { id.parentIndex = index(parent.row(),s_SystemId); id.table = ProfilesTable; } else { id.parentIndex = parent; id.table = SystemsTable; }
int index = m_internalIds.indexOf( id ); if( index == -1 ) { m_internalIds << id; index = m_internalIds.count() - 1; }
InternalId &iid = m_internalIds[index]; return createIndex(row,column,(void*)&iid); }
QModelIndex ProfilesModel::parent(const QModelIndex &index) const { InternalId *id = static_cast<InternalId*>(index.internalPointer()); if( id == 0 ) return QModelIndex();
return id->parentIndex; }
bool ProfilesModel::setData(const QModelIndex &index, const QVariant &value, int role) { InternalId *id = static_cast<InternalId*>(index.internalPointer()); if( id == 0 ) return false;
switch( id->table ) { case SystemsTable: { return m_systemsModel->setData( m_systemsModel->index(index.row(), index.column()), value, role); } case ProfilesTable: { setCurrentSystem( id->parentIndex ); return m_profilesModel->setData( m_profilesModel->index(index.row(), index.column()), value, role); } default: { return false; } } }
QVariant ProfilesModel::data(const QModelIndex &index, int role) const { InternalId *id = static_cast<InternalId*>(index.internalPointer()); if( id == 0 ) return QVariant();
switch( id->table ) { case SystemsTable: { return m_systemsModel->index( index.row(), index.column() ).data(role); } case ProfilesTable: { setCurrentSystem( id->parentIndex ); return m_profilesModel->index( index.row(), index.column() ).data(role); } default: { return QVariant(); } } }
bool ProfilesModel::insertRows(int row, int count, const QModelIndex &parent) { InternalId *id = static_cast<InternalId*>(parent.internalPointer()); if( id == 0 ) {
QSqlRecord rec = m_systemsModel->record(); rec.setNull("system_id"); rec.setValue("name",tr("Unnamed"));
bool ok = true; for( int i = row; i < row+count; i++ ) ok = m_systemsModel->insertRecord(row,rec);
if( ok ) { beginInsertRows(parent,row,count+row-1); endInsertRows(); return true; } else { return false; } } else {
QSqlRecord rec = m_profilesModel->record(); rec.setNull("profile_id"); rec.setValue("name",tr("Unnamed")); rec.setValue("system_id",parent.data(Qt::EditRole));
bool ok = true; int last = row+count; for( int i = row; i < last; i++ ) ok = m_profilesModel->insertRecord(i,rec);
if(ok) { beginInsertRows(parent,row,count+row-1); endInsertRows(); return true; } else { return false; } } }
bool ProfilesModel::removeRows(int row, int count, const QModelIndex &parent) { InternalId *id = static_cast<InternalId*>(parent.internalPointer()); if( id == 0 ) { if( m_systemsModel->removeRows(row,count) ) { beginRemoveRows(parent,row,row+count-1); endRemoveRows(); return true; } else { return false; } } else { setCurrentSystem(parent);
if( m_profilesModel->removeRows(row,count) ) { beginRemoveRows(parent,row,row+count-1); endRemoveRows(); return true; } else { return false; } } }
int ProfilesModel::rowCount(const QModelIndex &parent) const { if( parent.isValid() ) { setCurrentSystem(parent); return m_profilesModel->rowCount(); } else { return m_systemsModel->rowCount(); } }
int ProfilesModel::columnCount(const QModelIndex &parent) const { if( parent.isValid() ) { return m_profilesModel->columnCount(); } else { return m_systemsModel->columnCount(); } }
Qt::ItemFlags ProfilesModel::flags(const QModelIndex &index) const { InternalId *id = static_cast<InternalId*>(index.internalPointer()); if( id == 0 ) return 0;
switch( id->table ) { case SystemsTable: { return m_systemsModel->flags( m_systemsModel->index(index.row(),index.column()) ); } case ProfilesTable: { return m_profilesModel->flags( m_profilesModel->index(index.row(),index.column()) ); } default: { return 0; } } }
void ProfilesModel::setCurrentSystem(const QModelIndex &system) const { QString filter = "system_id = " + system.data(Qt::EditRole).toString(); if( m_profilesModel->filter() != filter ) m_profilesModel->setFilter(filter); }
для показа модели поместил на форму два QListView один показывает PROFILE_SYSTEMS.name другой показывает PROFILES.name
вот исходный код
ProfilesForm::ProfilesForm(QWidget *parent) : QWidget(parent) { setupUi(this);
m_model = new ProfilesModel();
// m_tableSizes->setItemDelegate( new QItemDelegate() ); // m_tableSizes->setSelectionModel( new QItemSelectionModel(m_model) ); m_listSystem->setModel( m_model ); m_listSystem->setModelColumn( 1 ); m_listSystem->setItemDelegate( new QItemDelegate() ); m_listSystem->setSelectionModel( new QItemSelectionModel(m_model) );
m_listProfiles->setModel(m_model); m_listProfiles->setItemDelegate( new QItemDelegate() ); m_listProfiles->setSelectionModel( new QItemSelectionModel(m_model) ); m_listProfiles->setRootIndex( m_model->index(0,0) ); m_listProfiles->setModelColumn( 2 );
connect(m_listSystem->selectionModel(),SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),this,SLOT(systemChanged(QModelIndex,QModelIndex))); }
void ProfilesForm::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: retranslateUi(this); break; default: break; } }
void ProfilesForm::on_m_pushAddProfileSystem_clicked() { m_model->insertRow( m_model->rowCount() ); }
void ProfilesForm::on_m_pushDeleteProfileSystem_clicked() { QModelIndex idx = m_model->index( m_listSystem->currentIndex().row(), 0 ); m_model->removeRow(idx.row()); }
void ProfilesForm::on_m_pushAddProfile_clicked() { QModelIndex idx = m_model->index( m_listSystem->currentIndex().row(), 0 ); m_model->insertRow( m_model->rowCount(idx), idx); }
void ProfilesForm::on_m_pushDeleteProfile_clicked() { QModelIndex idx = m_model->index( m_listSystem->currentIndex().row(), 0 ); m_model->removeRow( m_listProfiles->currentIndex().row(), idx); }
void ProfilesForm::systemChanged(const QModelIndex ¤t, const QModelIndex &) { QModelIndex idx = m_model->index(current.row(),0); m_listProfiles->setRootIndex( idx ); m_listProfiles->setModelColumn( 2 ); }
функция beginRemoveRows() ведет себя очень странно - если в модели больше 3 элементов и я удаляю предпоследний, то возврата из beginRemoveRows() происходит.
Теперь вопрос - каким образом указывать предков для элементов таблицы PROFILES? У меня сейчас так - каждый QModelIndex из таблицы PROFILES имеет предка PROFILE_SYSTEMS.system_id
|
|
Здравствуйте. Нужен хелп.
Есть 2 SQL таблицы.
leafs( leaf_id int primary key auto_increment, name text ) sizes( size_id int primary key auto_increment, leaf_id int, name )
соответственно sizes.size_id = leaf_id
Сделал свою модель. В моделе храню две QSqlTableModel - одна для leafs, другая для sizes В своей моделе сделал иерархию. Корень записи из leafs, ветка 1-го уровня - записи из sizes.
Для показа/редиктирования модели сделал два виджета QTableView. Один показывает leafs, другой sizes. Когда выбираю строку из leafs, генерится сигнал currentRowChanged(QModelIndex current,QModelIndex previous). В нем я делаю m_sizesModel->setRootIndex(current);
Все работает, записи добавляются и в ту и другую таблицы, данные изменяются корректно.
Когда доходит дело до удаления записей начинается лажа. согласно документации для удаления записей я должен переопределить метод removeRows( int row, int count, QModelIndex parent) в нем я должен вызвать метод beginRemoveRows() прежде чем удалять данные и endRemoveRows() после того как данные удалены.
В метод приходят корректные аргументы (т.е. валидный индекс, номер строки и кол-во) при вызове метода beginRemoveRows(parent,row,row+count-1) прога намертво виснет!
даже не знаю в чем беда!
|