Перетаскивание между различными представлениями разнородной иерархии данных

У меня есть иерархическая структура данных, которая должна быть визуализирована в нескольких представлениях Qt (или виджетах). Иерархия данных состоит из разнородных типов элементов, таких как:

House
 |- Floor
 |   |- Room
 |   |   |- Window
 |   |   |- ...
 |   |- Room
 |   |   |- ...
 |- ...

Все элементы (Дом, Этаж, Комната, ...) имеют атрибуты, которые можно отобразить. Обратите внимание, что это упрощенный пример. Иерархия рисуется различными представлениями. Например. просто идентификатор комнаты в списке для шаблонов (QListView/Widget), настраиваемый вид (иерархия подклассов QWidget для каждого элемента), подробный вид для редактирования свойств, например. пол (подкласс QWidget или QWizard).

Также возможно перетаскивать элементы между несколькими экземплярами. Например. перемещение комнат на разные этажи. Можно объявить конкретный этаж в качестве шаблона и перетащить этаж из списка шаблонов, например. пользовательский вид (где состоит дом).

Qt использует архитектуру Model/View для разделения данных. , модель и вид. Поскольку у меня совершенно разные типы представлений, я предполагаю, что для каждого представления требуется соответствующая модель. В случае с моим пользовательским представлением иерархии каждый элемент имеет собственную визуализацию, поэтому иерархия существует (но не должна существовать) трижды: иерархия данных, иерархия модели и иерархия представления. Это становится очень грязным, потому что каждая иерархия должна обновляться, если элемент перетаскивается, удаляется или копируется. Лучшим подходом будет Presentation-Abstraction-Control узор. Однако PAC неприменим, так как родитель QWidget должен быть установлен для встраивания дочерних элементов в их родительское представление. Следовательно, QWidget не может ссылаться на агент, отвечающий за моделирование иерархии.

Мне кажется, что Qt очень хорошо представляет списки, таблицы и деревья однородных типов данных (например, строк). В моем случае каждый элемент имеет индивидуальный набор атрибутов, которые нельзя просто выразить в виде таблицы. В этом обсуждении не рекомендуется вставлять квадратный колышек в круглое отверстие. Это означает, что не нужно форсировать какой-либо дизайн в табличном представлении.

Суть моей задачи заключается в том, чтобы объединить в одной концепции дизайна следующие функции: Визуализация иерархических данных с разным уровнем детализации. Поддержка перетаскивания между представлениями, которое копирует данные и создает соответствующие компоненты модели/представления. Поддержка перетаскивания в представлении, которое влияет на иерархию данных, модели и представления (которую я хотел бы избежать трехкратной реализации). Я не могу предоставить одну модель дома со всеми его подкомпонентами, так как этажи и комнаты слишком сложны. Я считаю неудобным управлять тремя (или более) иерархиями для одного действия перетаскивания, удаления или копирования.

Есть ли передовая практика, шаблон проектирования или, может быть, другой подход к моей проблеме? Решается ли эта проблема с помощью Qt?

Я благодарен за каждое предложение.


person Marian    schedule 16.04.2013    source источник


Ответы (1)


У меня была похожая проблема некоторое время с моей иерархической структурой. Все в архитектуре модели-представления-делегата Qt зависит от того, как вы организуете свои данные и насколько сложными вы хотите стать. Для очень простых приложений имеет смысл реализовывать элементы на основе подхода, редактируя отображение элементов на уровне просмотра. Это становится очень грязным очень быстро.

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

В начале работы мне показалось полезным наследовать объекты QStandardItem и создавать подклассы QStandardItemModel, так как QStandardItem уже настроена иерархия родитель-потомок и настроена индексация. для меня. Мне нравится увеличивать Qt::UserRole и присваивать значение enum каждому из моих пользовательских типов данных. Например:

enum FloorProperties
{
    DAT_CARPETING = Qt::UserRole +100,
    DAT_AREA = Qt::UserRole +101,
    DAT_FLOORNUM = Qt::UserRole +102
}

Даже если вы не хотите связывать сохраненное значение с каждой ролью данных (используя удобный QStandardItem::setData()), вы можете настроить QStandardItemModel::data(), чтобы вернуть вычисленное значение, сохраненное значение, что угодно. Настройка модели позволяет рассматривать каждый элемент как объект, а не как отдельную ячейку в таблице/списке.

Стандартные представления должны дать вам большую часть того, что вам нужно на общей основе. Настройте отображение для определенных типов данных (этажи, окна, целые числа, строки и т. д.) с помощью делегатов. Надеюсь, это имеет смысл.

person Phlucious    schedule 16.04.2013
comment
Я упустил тот факт, что QStandardItem в отличие от QObject можно клонировать. Использование UserRole тоже кажется очень Qty. Мне нужно обдумать ваше предложение, но пока это, кажется, то, что я ищу. Я вернусь к тебе. - person Marian; 17.04.2013