Название: [РЕШЕНО][QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 03, 2010, 15:02
Добрый день - не могу разобраться с проблемой. Программа валиться при попытке вызова переопределенного метода removeRows gdb Program received signal SIGSEGV, Segmentation fault. 0x004369f4 in CustomersForm::slDeleteCustomer (this=0x9f85aa0) at ..\TrM.plasticity\forms\customersform.cpp:188 188 pModel->removeRows(row, 1, QModelIndex()); (gdb) bt #0 0x004369f4 in CustomersForm::slDeleteCustomer (this=0x9f85aa0) at ..\TrM.plasticity\forms\customersform.cpp:188 #1 0x0044507a in CustomersForm::qt_metacall (this=0x9f85aa0, _c=QMetaObject::InvokeMetaMethod, _id=2, _a=0x226e9c) at moc\moc_customersform.cpp:130 #2 0x6a201d7c in QMetaObject::metacall (object=0x9f85aa0, cl=QMetaObject::InvokeMetaMethod, idx=38, argv=0x226e9c) at kernel\qmetaobject.cpp:237 #3 0x6a211b94 in QMetaObject::activate (sender=0xa00e010, m=0x1909000, local_signal_index=1, argv=0x226e9c) at kernel\qobject.cpp:3287 #4 0x01116338 in QAction::triggered (this=0xa00e010, _t1=false) at tmp/moc/debug_shared/moc_qaction.cpp:263 #5 0x01115889 in QAction::activate (this=0xa00e010, event=QAction::Trigger) at kernel\qaction.cpp:1255 #6 0x01517454 in QMenuPrivate::activateCausedStack (this=0xa047ab0, causedStack=@0x226f6c, action=0xa00e010, action_e=QAction::Trigger, self=true) at widgets\qmenu.cpp:1002 #7 0x01517893 in QMenuPrivate::activateAction (this=0xa047ab0, action=0xa00e010, action_e=QAction::Trigger, self=true) at widgets\qmenu.cpp:1094 #8 0x0151b9bb in QMenu::mouseReleaseEvent (this=0x229dd0, e=0x2276f8) at widgets\qmenu.cpp:2312 #9 0x0116ced2 in QWidget::event (this=0x229dd0, event=0x2276f8) at kernel\qwidget.cpp:8044 #10 0x0151c011 in QMenu::event (this=0x229dd0, e=0x2276f8) at widgets\qmenu.cpp:2421 #11 0x01122526 in QApplicationPrivate::notify_helper (this=0x3e5ca0, receiver=0x229dd0, e=0x2276f8) at kernel\qapplication.cpp:4302 #12 0x01120729 in QApplication::notify (this=0x22ff40, receiver=0x229dd0, e=0x2276f8) at kernel\qapplication.cpp:3867 #13 0x6a1fd47a in QCoreApplication::notifyInternal (this=0x22ff40, receiver=0x229dd0, event=0x2276f8) at kernel\qcoreapplication.cpp:726 #14 0x01779506 in QCoreApplication::sendSpontaneousEvent (receiver=0x229dd0, event=0x2276f8) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:218 #15 0x0111ef46 in QApplicationPrivate::sendMouseEvent (receiver=0x229dd0, event=0x2276f8, alienWidget=0x0, nativeWidget=0x229dd0, buttonDown=0x1b7841c, lastMouseReceiver=@0x1b78420, spontaneous=true) at kernel\qapplication.cpp:2965 #16 0x01187e6b in QETWidget::translateMouseEvent (this=0x229dd0, msg=@0x227bac) at kernel\qapplication_win.cpp:3171 #17 0x011834db in QtWndProc@16 (hwnd=0x2a090e, message=514, wParam=0, lParam=1966130) at kernel\qapplication_win.cpp:1629 #18 0x7e368734 in USER32!GetDC () from C:\WINDOWS\system32\user32.dll #19 0x002a090e in ?? () #20 0x00000202 in ?? () #21 0x7e368816 in USER32!GetDC () from C:\WINDOWS\system32\user32.dll #22 0x01182ab3 in qt_is_translatable_mouse_event (message=0) at kernel\qapplication_win.cpp:1401 #23 0x7e3689cd in USER32!GetWindowLongW () from C:\WINDOWS\system32\user32.dll #24 0x00000000 in ?? () class TMCustomerItemModel : public QAbstractTableModel переопределенная модель class TMCustomer; class TMCustomerItemModel : public QAbstractTableModel { Q_OBJECT public: // INQUIRY TMCustomerItemModel(QString sDb, QObject* parent = 0); int rowCount(const QModelIndex &parent = QModelIndex()) const {Q_UNUSED(parent);return plCustomers.size();} int columnCount(const QModelIndex &parent = QModelIndex()) const {Q_UNUSED(parent);return 5;} QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole); bool insertRows(int position, int rows, const QModelIndex &index=QModelIndex()); bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()); Qt::ItemFlags flags(const QModelIndex &index) const; private: // CLASS MEMBERS QList<TMCustomer*> plCustomers; QSqlDatabase db; }; место вызова void CustomersForm::slDeleteCustomer() { QItemSelectionModel *selectionModel = ui->lwCustomers->selectionModel(); QModelIndexList indexes = selectionModel->selectedRows(); QModelIndex index; ui->lwCustomers->setUpdatesEnabled(false); foreach (index, indexes) { int row = index.row(); qDebug() << "CustomersForm::slDeleteCustomer() called on" << row; pModel->removeRows(row, 1, QModelIndex()); } ui->lwCustomers->setUpdatesEnabled(true); }
Прошу совета.
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: crossly от Август 03, 2010, 15:47
а можно на реализацию метода посмотреть??
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 03, 2010, 15:56
Прошу: Дебаг не выводиться - валиться раньше. bool TMCustomerItemModel::removeRows(int position, int rows, const QModelIndex &index) { qDebug() << "TMCustomerItemModel::removeRows called:" << position << rows; Q_UNUSED(index); this->beginRemoveRows(QModelIndex(), position, position+rows-1); for (int row = 0; row < rows; ++row) { TMCustomer* pCustomer; pCustomer = plCustomers.takeAt(index.row()); pCustomer->deleteCustomer(); delete pCustomer; } this->endRemoveRows(); return true; }
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: BRE от Август 03, 2010, 17:10
Почитай как работает метод takeAt, что происходит с индексами после его выполнения. Для примера можно посмотреть как это реализовано в QStringListModel.
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 03, 2010, 18:12
Почитай как работает метод takeAt, что происходит с индексами после его выполнения. Для примера можно посмотреть как это реализовано в QStringListModel.
Проблема в том, что он валится до takeAt. К тому же он тут не причем. Пример из ItemViews->Address Book bool TableModel::removeRows(int position, int rows, const QModelIndex &index) { Q_UNUSED(index); beginRemoveRows(QModelIndex(), position, position+rows-1);
for (int row=0; row < rows; ++row) { listOfPairs.removeAt(position); }
endRemoveRows(); return true; } P.S. Хотя нет реализация removeRows у меня неправильная тем не менее валиться он до вызова функции takeAt. Не выводиться qDebug() << "TMCustomerItemModel::removeRows called:" << position << rows;
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: asvil от Август 03, 2010, 18:53
selectionModel на равенсто нулю почему не проверяете? Если модель для предстваления не установлена, модели "выделения" не существует.
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 03, 2010, 22:35
selectionModel на равенсто нулю почему не проверяете? Если модель для предстваления не установлена, модели "выделения" не существует.
Простите я видимо, чего-то не знаю - может я трасерт gdb неправильно читаю? Дело в том что проходит сигнал, валиться в области вызова функции removeRows переопределенной от QAbstractModel. foreach (index, indexes) может продолжать исполнение, если selectionModel === Null? И продолжать цикл вызывая removeRows?
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: asvil от Август 03, 2010, 23:55
Да, я не прав, недоглядел. Ну тогда указатель на модель возможно равен нулю?
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 04, 2010, 00:33
Да, я не прав, недоглядел. Ну тогда указатель на модель возможно равен нулю?
Нет, или не прошел бы foreach, насколько я помню спецификацию. Прошу обратить внимание на gdb->bt
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: crossly от Август 04, 2010, 08:50
а давайте весь код посмотрим... :)
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 04, 2010, 11:31
а давайте весь код посмотрим... :)
h #ifndef CUSTOMERSFORM_H #define CUSTOMERSFORM_H
#include <QDialog> #include <QAbstractItemModel> #include <QSqlDatabase> #include <QDataWidgetMapper>
namespace Ui { class CustomersForm; }
class TMCustomer;
class TMCustomerItemModel : public QAbstractTableModel { Q_OBJECT public: // INQUIRY TMCustomerItemModel(QString sDb, QObject* parent = 0); int rowCount(const QModelIndex &parent = QModelIndex()) const {Q_UNUSED(parent);return plCustomers.size();} int columnCount(const QModelIndex &parent = QModelIndex()) const {Q_UNUSED(parent);return 5;} QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole); bool insertRows(int position, int rows, const QModelIndex &index=QModelIndex()); bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()); Qt::ItemFlags flags(const QModelIndex &index) const; private: // CLASS MEMBERS QList<TMCustomer*> plCustomers; QSqlDatabase db; };
class CustomersForm : public QDialog { Q_OBJECT public: explicit CustomersForm(QWidget *parent = 0); ~CustomersForm();
QAction* addCustomer; QAction* deleteCustomer; TMCustomerItemModel* pModel; protected: void changeEvent(QEvent *e); signals: void customerSelected(int iId); private: Ui::CustomersForm *ui; QDataWidgetMapper *mapper; private slots: void slAddCustomer(); void slDeleteCustomer(); void slShowListMenu(const QPoint &point); };
#endif // CUSTOMERSFORM_H
cpp include <QMenu> #include <QDebug> #include <QSqlError> #include <QModelIndex> #include <QSqlTableModel>
#include "customersform.h" #include "ui_customersform.h" #include "trm_wrapper/tmcustomer.h"
TMCustomerItemModel::TMCustomerItemModel(QString sDb, QObject *parent): QAbstractTableModel(parent) { db = QSqlDatabase::database(sDb);
QSqlQuery query(db); query.prepare("SELECT id FROM trm_customers"); query.exec(); while(query.next()) { TMCustomer* pCustomer; pCustomer = new TMCustomer(sDb, query.value(0).toInt()); if(pCustomer->isValid()) this->plCustomers.append(pCustomer); } }
QVariant TMCustomerItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant();
if (index.row() < 0 || index.row() > plCustomers.size()) return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole) { switch(index.column()) { case 0: return plCustomers.at(index.row())->getShortName(); break; case 1: return plCustomers.at(index.row())->getFullName(); break; case 2: return plCustomers.at(index.row())->getChiefShortName(); break; case 3: return plCustomers.at(index.row())->getChiefFullName(); break; case 4: return plCustomers.at(index.row())->getEmail(); break; } } return QVariant(); } bool TMCustomerItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::EditRole) { int row = index.row(); bool isOk; switch(index.column()) { case 0: isOk = plCustomers.at(row)->setShortName(value.toString(), false); break; case 1: isOk = plCustomers.at(row)->setFullName(value.toString(), false); break; case 2: isOk = plCustomers.at(row)->setChiefShortName(value.toString(), false); break; case 3: isOk = plCustomers.at(row)->setChiefFullName(value.toString(),false); break; case 4: isOk = plCustomers.at(row)->setEmail(value.toString(), false); break; } if(isOk) emit(dataChanged(index, index)); return isOk; } return false; }
bool TMCustomerItemModel::insertRows(int position, int rows, const QModelIndex &index) { Q_UNUSED(position); Q_UNUSED(rows); Q_UNUSED(index); TMCustomer *pCustomer; pCustomer = new TMCustomer("trm"); beginInsertRows(QModelIndex(), rowCount() - 1, rowCount()); plCustomers.append(pCustomer); endInsertRows(); }
bool TMCustomerItemModel::removeRows(int position, int rows, const QModelIndex &index) { qDebug() << "TMCustomerItemModel::removeRows called:" << position << rows; Q_UNUSED(index); this->beginRemoveRows(QModelIndex(), position, position+rows-1); for (int row = 0; row < rows; ++row) { TMCustomer* pCustomer; pCustomer = plCustomers.takeAt(index.row()); pCustomer->deleteCustomer(); delete pCustomer; } this->endRemoveRows(); return true; }
Qt::ItemFlags TMCustomerItemModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::ItemIsEnabled; return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; }
CustomersForm::CustomersForm(QWidget *parent) : QDialog(parent), ui(new Ui::CustomersForm) { ui->setupUi(this); //QSqlTableModel* pModel; //QSqlDatabase db = QSqlDatabase::database("trm"); //pModel = new QSqlTableModel(this, db); TMCustomerItemModel* pModel; pModel = new TMCustomerItemModel(QString("trm")); //pModel->setTable("trm_customers"); //pModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //pModel->select(); ui->lwCustomers->setModel(pModel); ui->lwCustomers->setContextMenuPolicy(Qt::CustomContextMenu);
addCustomer = new QAction(tr("Добавить заказчика"),this); deleteCustomer = new QAction(tr("Удалить заказчика"), this);
connect(addCustomer, SIGNAL(triggered()), this , SLOT(slAddCustomer())); connect(deleteCustomer, SIGNAL(triggered()), this , SLOT(slDeleteCustomer()));
connect(ui->lwCustomers, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slShowListMenu(const QPoint &)));
mapper = new QDataWidgetMapper(this); mapper->setModel(pModel); mapper->addMapping(ui->leCustomerNameShort, 0); mapper->addMapping(ui->leCustomerNameFull, 1); mapper->addMapping(ui->leGeneralDirectorShortName, 2); mapper->addMapping(ui->leGeneralDirectorName, 3); mapper->addMapping(ui->leEmail, 4); mapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit); connect(ui->lwCustomers, SIGNAL(clicked(QModelIndex)), mapper, SLOT(setCurrentModelIndex(QModelIndex))); }
void CustomersForm::slShowListMenu(const QPoint &point) { QList<QAction *> actions; actions.append(addCustomer); if (ui->lwCustomers->indexAt(point).isValid()) { QModelIndex index = ui->lwCustomers->indexAt(point);
actions.append(deleteCustomer); } if (actions.count() > 0) QMenu::exec(actions, ui->lwCustomers->mapToGlobal(point)); }
CustomersForm::~CustomersForm() { delete ui; }
void CustomersForm::slAddCustomer() { //TMCustomer *pCustomer = new TMCustomer("trm", tr("Новый заказчик")); //if(pCustomer->isValid()) // pModel->append(pCustomer); }
void CustomersForm::slDeleteCustomer() { QItemSelectionModel *selectionModel = ui->lwCustomers->selectionModel(); QModelIndexList indexes = selectionModel->selectedRows(); QModelIndex index; ui->lwCustomers->setUpdatesEnabled(false); foreach (index, indexes) { int row = index.row(); qDebug() << "CustomersForm::slDeleteCustomer() called on" << row; pModel->removeRows(row, 1, QModelIndex()); } ui->lwCustomers->setUpdatesEnabled(true); }
void CustomersForm::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } }
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: crossly от Август 04, 2010, 11:36
а можно вопрос.... для чего этот огород с TCustomer и моделью... может можно было обойтись QSqlQueryModel или QSqlTableModel ??
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 04, 2010, 11:42
а можно вопрос.... для чего этот огород с TCustomer и моделью... может можно было обойтись QSqlQueryModel или QSqlTableModel ??
Можно, дело в том, что потом планируеться на две базы работать. Одна не принадлежит моему приложению, и её структура, мягко говоря не подходит для работы с QSqlTableModel.
Название: Re: [QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 09, 2010, 11:15
Стало еще забавнее, сегфалт при вызове size Program received signal SIGSEGV, Segmentation fault. 0x004dbd0e in QListData::isEmpty (this=0xbaadf015) at ../../Qt/4.7.0-beta2/include/QtCore/../../src/corelib/tools/qlist.h:95 95 inline bool isEmpty() const { return d->end == d->begin; } (gdb) x 0xbaadf015 0xbaadf015: Cannot access memory at address 0xbaadf015 (gdb) bt #0 0x004dbd0e in QListData::isEmpty (this=0xbaadf015) at ../../Qt/4.7.0-beta2/include/QtCore/../../src/corelib/tools/qlist.h:95 #1 0x004dad5d in QList<TMCustomer*>::isEmpty (this=0xbaadf015) at ../../Qt/4.7.0-beta2/include/QtCore/../../src/corelib/tools/qlist.h:139 #2 0x00444b8f in CustomersForm::slItemSelected (this=0xc759a78, index=...) at ..\TrM.plasticity\forms\customersform.cpp:179 #3 0x00455ee1 in CustomersForm::qt_metacall (this=0xc759a78, _c=QMetaObject::InvokeMetaMethod, _id=4, _a=0x2290f8) at moc\moc_customersform.cpp:134 #4 0x6a226f52 in QMetaObject::metacall (object=0xc759a78, cl=QMetaObject::InvokeMetaMethod, idx=40, argv=0x2290f8) at kernel\qmetaobject.cpp:237 #5 0x6a23b003 in QMetaObject::activate (sender=0xc75e330, m=0x18353a4, local_signal_index=1, argv=0x2290f8) at kernel\qobject.cpp:3272 #6 0x0146829e in QAbstractItemView::clicked (this=0xc75e330, _t1=...) at tmp/moc/debug_shared/moc_qabstractitemview.cpp:331 #7 0x0145af1c in QAbstractItemView::mouseReleaseEvent (this=0xc75e330, event=0x229ee4) at itemviews\qabstractitemview.cpp:1789 #8 0x014772bf in QListView::mouseReleaseEvent (this=0xc75e330, e=0x229ee4) at itemviews\qlistview.cpp:796 #9 0x00f0c80f in QWidget::event (this=0xc75e330, event=0x229ee4) at kernel\qwidget.cpp:8157 #10 0x0131391e in QFrame::event (this=0xc75e330, e=0x229ee4) at widgets\qframe.cpp:557 #11 0x013b7735 in QAbstractScrollArea::viewportEvent (this=0xc75e330, e=0x229ee4) at widgets\qabstractscrollarea.cpp:1043 #12 0x014597a4 in QAbstractItemView::viewportEvent (this=0xc75e330, event=0x229ee4) at itemviews\qabstractitemview.cpp:1619 #13 0x01672dcb in QAbstractScrollAreaPrivate::viewportEvent (this=0xc7799e8, event=0x229ee4) at widgets/qabstractscrollarea_p.h:100 #14 0x01671190 in QAbstractScrollAreaFilter::eventFilter (this=0xc753f48, o=0xc6c8330, e=0x229ee4) at widgets/qabstractscrollarea_p.h:116 #15 0x6a2216ed in QCoreApplicationPrivate::sendThroughObjectEventFilters ( this=0x3e5ed0, receiver=0xc6c8330, event=0x229ee4) at kernel\qcoreapplication.cpp:847 #16 0x00ebd951 in QApplicationPrivate::notify_helper (this=0x3e5ed0, receiver=0xc6c8330, e=0x229ee4) at kernel\qapplication.cpp:4385 #17 0x00ebb631 in QApplication::notify (this=0x22ff20, receiver=0xc6c8330, e=0x229ee4) at kernel\qapplication.cpp:3952 #18 0x6a22141e in QCoreApplication::notifyInternal (this=0x22ff20, receiver=0xc6c8330, event=0x229ee4) at kernel\qcoreapplication.cpp:732 #19 0x0163114a in QCoreApplication::sendSpontaneousEvent (receiver=0xc6c8330, event=0x229ee4) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:218 #20 0x00eb9913 in QApplicationPrivate::sendMouseEvent (receiver=0xc6c8330, event=0x229ee4, alienWidget=0xc6c8330, nativeWidget=0xc759a78, buttonDown=0x18d92bc, lastMouseReceiver=..., spontaneous=true) at kernel\qapplication.cpp:3049 #21 0x00f2d85c in QETWidget::translateMouseEvent (this=0xc759a78, msg=...) at kernel\qapplication_win.cpp:3300 #22 0x00f278ad in QtWndProc@16 (hwnd=0x1b0836, message=514, wParam=0, lParam=2818240) at kernel\qapplication_win.cpp:1657 #23 0x7e368734 in USER32!GetDC () from C:\WINDOWS\system32\user32.dll #24 0x00000000 in ?? () (gdb) x 0xbaadf015 0xbaadf015: Cannot access memory at address 0xbaadf015 (gdb)
Название: Re: [РЕШЕНО][QAbstractTableModel] segfault при вызове переопределенного removeRows
Отправлено: Maquefel от Август 17, 2010, 09:01
В функции переопределил член класса pModel, отсюда нулевой указатель.
|