LINUX.ORG.RU

[Qt] Множественное наследование QAbstractItemView

 


0

0

Пишу некий плагин для designer, который должен отображать заданную модель в QColumnView, QTreeView, QListView и QTableView.

Мне позарез нужен сигнал изменения выделения списка. По умолчанию ни один из классов иерархии не предоставляет такого. Единственный способ переопределить виртуальный protected метод selectionChanged класса QAbstractItemView, от которого наследуются перечисленные виджеты.

В любом случае придется создавать свои виджеты и наследоваться от перечисленных. Но в каждом переопределять названный метод - бред, ибо код генерации сигнала одинаковый.

Поэтому я решил описать свой класс, который наследуется от QAbstractItemView, и уже от него наследовать свои виджеты, в совокупности со стандартными виджетами отображения модели.

Казалось бы: все просто и логично.

На этой картинке отображена предполагаемая иерархия классов: http://img692.imageshack.us/img692/1063/classes.png

Но возникла проблемы с множественным наследованием. Возникает два экземпляра QAbstractItemView. Эта проблема может быть решена с помощью использования виртуальных базовых классов, но что-то у меня не получается.

Как я понял, при описании классов, которые содержат общий базовый, последний должен наследоваться с использованием ключевого слова «virtual».

То есть при описании класса QColumnView он должен наследоваться от QAbstractItemView с упоминанием virtual, так же, как и при наследовании AbstractItemView от QAbstractItemView.

Только вот в реализацию классов Qt мне не залезть, а то, что я описываю у себя - недостаточно.

Я описываю так: class AbstractItemView: virtual public QAbstractItemView... class ColumnView: public QColumnView, public AbstractItemView...

При компиляции возникают такие ошибки:

1>.\filesbrowserwidget.cpp(9) : error C2259: 'ColumnView' : cannot instantiate abstract class
1>        due to following members:
1>        'QRect QAbstractItemView::visualRect(const QModelIndex &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(196) : see declaration of 'QAbstractItemView::visualRect'
1>        'void QAbstractItemView::scrollTo(const QModelIndex &,QAbstractItemView::ScrollHint)' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(197) : see declaration of 'QAbstractItemView::scrollTo'
1>        'QModelIndex QAbstractItemView::indexAt(const QPoint &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(198) : see declaration of 'QAbstractItemView::indexAt'
1>        'QModelIndex QAbstractItemView::moveCursor(QAbstractItemView::CursorAction,Qt::KeyboardModifiers)' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(275) : see declaration of 'QAbstractItemView::moveCursor'
1>        'int QAbstractItemView::horizontalOffset(void) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(278) : see declaration of 'QAbstractItemView::horizontalOffset'
1>        'int QAbstractItemView::verticalOffset(void) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(279) : see declaration of 'QAbstractItemView::verticalOffset'
1>        'bool QAbstractItemView::isIndexHidden(const QModelIndex &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(281) : see declaration of 'QAbstractItemView::isIndexHidden'
1>        'void QAbstractItemView::setSelection(const QRect &,QItemSelectionModel::SelectionFlags)' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(283) : see declaration of 'QAbstractItemView::setSelection'
1>        'QRegion QAbstractItemView::visualRegionForSelection(const QItemSelection &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(284) : see declaration of 'QAbstractItemView::visualRegionForSelection'
1>.\filesbrowserwidget.cpp(10) : error C2385: ambiguous access of 'setModel'
1>        could be the 'setModel' in base 'QColumnView'
1>        or could be the 'setModel' in base 'QAbstractItemView'
1>.\filesbrowserwidget.cpp(10) : error C3861: 'setModel': identifier not found
1>.\filesbrowserwidget.cpp(11) : error C2594: 'argument' : ambiguous conversions from 'ColumnView *' to 'QWidget *'
1>.\filesbrowserwidget.cpp(13) : error C2259: 'ListView' : cannot instantiate abstract class
1>        due to following members:
1>        'QRect QAbstractItemView::visualRect(const QModelIndex &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(196) : see declaration of 'QAbstractItemView::visualRect'
1>        'void QAbstractItemView::scrollTo(const QModelIndex &,QAbstractItemView::ScrollHint)' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(197) : see declaration of 'QAbstractItemView::scrollTo'
1>        'QModelIndex QAbstractItemView::indexAt(const QPoint &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(198) : see declaration of 'QAbstractItemView::indexAt'
1>        'QModelIndex QAbstractItemView::moveCursor(QAbstractItemView::CursorAction,Qt::KeyboardModifiers)' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(275) : see declaration of 'QAbstractItemView::moveCursor'
1>        'int QAbstractItemView::horizontalOffset(void) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(278) : see declaration of 'QAbstractItemView::horizontalOffset'
1>        'int QAbstractItemView::verticalOffset(void) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(279) : see declaration of 'QAbstractItemView::verticalOffset'
1>        'bool QAbstractItemView::isIndexHidden(const QModelIndex &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(281) : see declaration of 'QAbstractItemView::isIndexHidden'
1>        'void QAbstractItemView::setSelection(const QRect &,QItemSelectionModel::SelectionFlags)' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(283) : see declaration of 'QAbstractItemView::setSelection'
1>        'QRegion QAbstractItemView::visualRegionForSelection(const QItemSelection &) const' : is abstract
1>        c:\development\qt\4.5.0\include\qtgui\../../src/gui/itemviews/qabstractitemview.h(284) : see declaration of 'QAbstractItemView::visualRegionForSelection'
1>.\filesbrowserwidget.cpp(14) : error C2385: ambiguous access of 'setModel'
1>        could be the 'setModel' in base 'QAbstractItemView'
1>        or could be the 'setModel' in base 'QAbstractItemView'
1>.\filesbrowserwidget.cpp(14) : error C3861: 'setModel': identifier not found
1>.\filesbrowserwidget.cpp(15) : error C2594: 'argument' : ambiguous conversions from 'ListView *' to 'QWidget *'

Вопрос в следующем: возможна ли реализация моего подхода и как вообще выкрутиться из ситуации, кроме как переопределения защищенных виртуальных слотов для каждого виджета и написания для них одинакового кода?

Не обращайте внимание на то, что компилируется с помощью MSVS. Я сейчас на работе, а линукса под рукой нет.

dogmeat-fall
() автор топика

>Мне позарез нужен сигнал изменения выделения списка. По умолчанию ни один из классов иерархии не предоставляет такого.

Насколько я понял из картинки, нужно переопределить методы QAbstractItemView::currentChanged () и QAbstractItemView::selectionChanged (). Насчет второго метода не знаю, но согласно http://qt.nokia.com/doc/4.5/qabstractitemview.html#currentChanged первый метод генерит событие dataChanged ().

>...и как вообще выкрутиться из ситуации, кроме как переопределения защищенных виртуальных слотов для каждого виджета и написания для них одинакового кода?

Могу предложить следующий костыль. Во-первых для каждого из классов QColumnView, QListView, QTableView, QTreeView написать обёртку, реализующую нужный функционал. Причем, если методы идентичны, можно забубухать шаблон и "заtypedefить" его от перечисленных выше классов.

Во-вторых. Если сборка кода происходит через qmake, то можно изменить процедуру самой компиляции - подменить uic на свою обёртку. Где твоя обертка будет заменять классы QColumnView, QListView, QTableView, QTreeView на нужные тебе. Правда в этом случае придеться не забыть и про заголовочные файлы.

Как вариация второго шага - помучить цели компиляции (PRE_TARGETDEPS), но я не думаю что из-за изменения целей что-то выйдет.

ale ★★
()
Ответ на: комментарий от UVV

Мне тут дали ответ:

чета я не понял че он хочет. если нужено поймат сигнал о смене выделения то нафига методы protected то переопределять. чем не устраивает QItemSelectionModel()::selectionChanged() и другие сигналы модели выделения. я ими пользуюсь везде. получить модель выделения для View можно с помощью его public метода selectionModel();

а ошибки там потому при компиляции что выращенные классы из QAbstarctItemView НЕ ИМЕЮТ реализации нескольких абстрактных (pure virtual) методов QAbstarctItemView. т.е. ВСЕ потомки QAbstarctItemView ОБЯЗАНЫ содержать реализацию pure virtual методов QAbstarctItemView иначе невозможно создать экземпляр такого класса

помни тока что selectionModel() возвращает не NULL только если ты ручками сделал setSelectionModel() или задал просто модель setModel(). во втором случае рождается стандартная модель выделения, по умолчанию. т.е. selectionModel() возвразщет валидное значение только после установки модели

множественное наследование вообще-то признак херовой организыции классов. по талмуду. ну типа как использование оператора goto. некошерно :)

Так что все гораздо проще =) В очередной раз убедился в крутости Qt.

dogmeat-fall
() автор топика

Ололо!

man QItemSelectionModel

anonymous
()
Ответ на: комментарий от dogmeat-fall

На заметку.

Случается, хочешь сделать что-то хитрое и крутость кутей уже не спасает, а множественное наследование не прокатывает по обозначенной вами причине. Тогда проблема решается с помощью примерно такого шаблона:

//NOTE: T is some Q...View class
template<typename T>
class myMegaView:public T{
//some shared code
};

А свои виджеты наследуете так:

class myWidget:public myMegaView<QTreeView>{

};

staseg ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.