Здравствуйте. Нужен хелп.
Есть 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) прога намертво виснет!
даже не знаю в чем беда!
Разобрался. Неверно указывал parent для индексов, поэтому получались бесконечные вызовы beginRemoveRows;
что-то я поторопился...
Упростил задачу до нельзя.
Есть две таблицы 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);
}
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 );
}
М | Оборачивайте длинные куски кода в тэг [expand][/expand] http://www.forum.crossplatform.ru/index.php?showtopic=1455 |
ВОН ОН ГДЕ ЖУК ЗАРЫЛСЯ!!!!
При удалении QModelIndex (что неизбежно делать надо при removeRows()) я забывал удалять из m_internalIds идентификаторы, тем самым путая логику.
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)