Название: Прокси модель и удаление строки
Отправлено: Kunashir от Июль 06, 2011, 12:39
День добрый!
Имеется табличная модель наследник от QAbstractTableModel. Она отображает на QTableView через QSortFilterProxyModel. Все нормально работает и даже идет удаление, но при этом процессе в Креаторе (в отладочном режиме) выводится QSortFilterProxyModel: inconsistent changes reported by source model. И удаление 1000 строк идет около минут - ИМХО долго, думаю может из-за этого ошибки.
Подскажите куда копать?
Название: Re: Прокси модель и удаление строки
Отправлено: Пантер от Июль 06, 2011, 12:40
Код приложи модели, прокси и как настраиваешь отображение.
Название: Re: Прокси модель и удаление строки
Отправлено: Kunashir от Июль 06, 2011, 12:49
Модель: catalogTableModel.h class CatalogTableModel : public QAbstractTableModel { Q_OBJECT public: explicit CatalogTableModel(TlsPrices *lsItem, QObject *parent); ~CatalogTableModel (); int rowCount (const QModelIndex &parent = QModelIndex ()) const; int columnCount (const QModelIndex &parent = QModelIndex ()) const; QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; Qt::ItemFlags flags (const QModelIndex &index) const; QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const; bool hasChildren (const QModelIndex &parent = QModelIndex ()) const; bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex ()); bool removeRowsWithCondition(int column, QString value); bool insertRows (int row, int count, const QModelIndex &parent = QModelIndex ()); TlsPrices* getPointerToData () { return listItem;} void setHeaderList (QList<QString> ls) { keys = ls;}
private: TlsPrices *listItem; QList <QString> lsNameAttr; QList <QString> keys; //списко названий столбцов };
catalogTableModel.cpp #include <QSize> #include <QFont> #include <QFontMetrics> #include "catalogtablemodel.h"
CatalogTableModel::CatalogTableModel(TlsPrices *lsItem, QObject *parent) : QAbstractTableModel(parent) { listItem = lsItem;
}
CatalogTableModel::~CatalogTableModel() {
}
int CatalogTableModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return listItem->count() ; }
int CatalogTableModel::columnCount(const QModelIndex &parent) const { return keys.count();//7;//lsNameAttr.count() ; }
QVariant CatalogTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { return keys.at(section); } return QAbstractItemModel::headerData(section, orientation, role); }
Qt::ItemFlags CatalogTableModel::flags(const QModelIndex &index) const { bool isSpec = false; if (keys.count() < 6) isSpec = true; if (index.column() == 6 || (index.column() == 2 && isSpec)) return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
return QAbstractItemModel::flags(index); }
QVariant CatalogTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !listItem->count()) return QVariant (); if (role == Qt::FontRole) { return QFont ("Helvetica"); } if (role == Qt::SizeHintRole) { //Рассчет наилучшего размера //макс длина 200, если больше, то переносим QFont f ("Helvetica"); QFontMetrics fm (f); if (index.column() == 0 || index.column() == 1 || index.column() == 3) { int w = fm.width (listItem->at(index.row())->getData(index.column()).toString()); int h = fm.height() - 2; if ( (w/200) > 1) { double ost = w/double (200); h = h*ost; //(w/200); w = 200; } return QSize (w, h); } return QSize (50, 25); //QFont //listItem->at(index.row())->getData(index.column()).toString().; } // QList <QString> keys = listItem->keys(); if (role == Qt::DisplayRole || role == Qt::EditRole) { bool isSpec = false; if (keys.count() < 6) { isSpec = true; if (index.column() == 4) { double summa = listItem->at(index.row())->getData(2, isSpec).toDouble()*listItem->at(index.row())->getData(3, isSpec).toDouble(); return summa; } } return listItem->at(index.row())->getData(index.column(), isSpec);
} else if ( role == Qt::UserRole) {
} return QVariant (); }
bool CatalogTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.column() == 6) { listItem->at(index.row())->order = value.toInt();
return true; }
// bool isSpec = false; if (keys.count() < 6) { //isSpec = true; if (index.column() == 2) { listItem->at(index.row())->price = value.toDouble(); reset ();//чтобы обновить вьюхи return true; }
} return false; }
bool CatalogTableModel::insertRows (int row, int count, const QModelIndex &parent) { // Q_UNUSED (parent); // CATALOG_ITEM newItem ; // newItem.id = "0"; // //newItem.code = "0000002"; // //for (int i = 0; i < columnCount(QModelIndex()); i++)
// beginInsertRows(QModelIndex (), row, row + count - 1); // //вызов сигнала // (*listItem).insert("0", newItem); // keys.append("0");
// endInsertRows(); // // emit sItemChanged(newItem, true); return true; }
bool CatalogTableModel::removeRows (int row, int count, const QModelIndex &parent) { //TODO: Q_UNUSED (parent); beginRemoveRows(QModelIndex(), row, row + count - 1); //int column = row + count; for (int i = 0; i < count; ++i) { delete listItem->at(row); listItem->removeAt(row); } emit layoutChanged(); endRemoveRows(); return true; }
bool CatalogTableModel::hasChildren(const QModelIndex &parent) const { return !parent.isValid(); }
//Удаление строк модели по условию //Вход: //column - колонка условия //value - значение для условия bool CatalogTableModel::removeRowsWithCondition(int column, QString value) { //int i = 0; int sizeOfList = listItem->count()-1; //while (i < sizeOfList) for (int i = sizeOfList; i >= 0; --i) { if (listItem->at(i)->getData(column).toString() == value) { removeRows(i, 1); // sizeOfList = listItem->count(); // continue; } //++i; } }
кусок из mainwindows.cpp void MainWindow::setHierarhy() {
if (ui->checkBox->isChecked()) { tableProxyModel->setSourceModel(model.getTableModel());//вот с этой моделью работаю ui->treeView->setVisible(false); } else { tableProxyModel->setSourceModel(&model); ui->treeView->setVisible(true); } }
//удаление одной строки
void MainWindow::delRowPrice() { //model.getTableModel()->removeRows( tableProxyModel->mapToSource(ui->tableView->currentIndex()).row(), 1); int row = ui->tableView->currentIndex().row(); if (ui->tableView->currentIndex().isValid()) tableProxyModel->removeRows(ui->tableView->currentIndex().row(), 1); //tableProxyModel->removeRow(ui->tableView->currentIndex().row()); ui->tableView->setCurrentIndex(tableProxyModel->index(row, 0)); }
Название: Re: Прокси модель и удаление строки
Отправлено: Kunashir от Июль 07, 2011, 15:32
Проблема видимо в синхронизации прокси и исходной модели... но как правильно делать удаления я не нашел. Пока решил это отключением прокси модели, потом удалением из исходной и новым подключением прокси.
Название: Re: Прокси модель и удаление строки
Отправлено: Kolobok от Июль 07, 2011, 17:42
Убери emit layoutChanged(); из CatalogTableModel::removeRows(). Оно там лишнее. И проблему может решит :)
Название: Re: Прокси модель и удаление строки
Отправлено: MoPDoBoPoT от Июль 07, 2011, 20:19
Ещё кое-что в глаза бросилось. Это, конечно, не относиться к проблеме топика, но всё же: В методе setData() после небольшого изменения ресетиться вся модель, хотя можно было сигналить с помощью dataChanged().
Название: Re: Прокси модель и удаление строки
Отправлено: Kunashir от Июль 08, 2011, 07:45
Убери emit layoutChanged(); из CatalogTableModel::removeRows(). Оно там лишнее. И проблему может решит :)
Без него вообще происходит крах где-то в недрах endRemoveRows(); У меня впечатление, что я как-то не правильно использую связку с прокси моделью, но только как правильно не пойму. Павилк: сброс модели поставил, так как при изменение данных не происходило обновление на вьюхи... Попробую с dataChanged().
|