Задача:
Есть несколько тоднотипных структур с массивами данных. Данные из массива текущей структуры отображаются во вьювере.
Допустим, один массив во вьювере отображается с 0-го по 5-й элементы, и выбран 3-й элемент, а второй массив отображается с 12-го по 17-й (например, ползователь прокрутил список) и выбран 12-й.
Хочется, чтобы при переключении текущей структуры положение вьюпорта и выбранного элемента соответственно менялось.
Кто должен отвечать за хранение "настроек отображения" для каждой структуры? Вроде бы проще всего отдать всё это на откуп вьюверу. Но не уверена.
Мне кажется лучше отделить этот код от кода отображения и засунуть его в контроллер - т.е. в то место, где происходит переключение между различными структурами, поскольку вид один, а заводить в нем список структур с ссответствующей инфой по отображению каждой - сильно связывает структуры и вид.
Лучше завести свой контроллер отображения для каждой структуры.
Мысли вслух:
А если появится второй, третий вьювер... Я их регистрирую в контроллере, и для каждого запоминаю, как именно в нём отображались данные.
Тогда всё будет работать так:
1.Структура стала текущей.
2.Контроллер текущей структуры выполняет действия:
- захватывает на себя сигналы от вьювера "изменился текущий элемент" и от его скроллеров "бегунок переместился"
- "раздаёт пинки" всем, зарегистрированным у него вьюверам -"отобрази с такого-то по такой-то"...
...
Почти универсально для таблицы и списка...
С деревом, где можно свернуть/развернуть элементы такое реализовать проблематично.
-----------------------------------
не бейте меня. Я стараюсь мыслить системно... Гы-гы-гы...
В контроллере дерева можно хранить дерево свернутых/развернутых узлов например (первое что приходит в голову).
Вообще если не заморачиваться сильно (и при разумном количестве структур) можно положить все виды на QStackedWidget и просто выбирать нужный (тогда и сохранять ничего не надо будет).
каждый вьюер должен иметь список ссылок на отображаемые им элементы + список описаний того, что сейчас отображено
то есть, это некий мап
std::map<указатель_на_объект, структура_описания_свойств_отображения_объекта>
Алексей1153, а что вы подразумеваете под "указатель_на_объект" ?
у вьювера уже есть модель...
Я думала, что можно одной и той же модели в качестве источника данных подсовывать разные структуры. Таким извращением не занималась, пока что. Это чисто теоретические изыскания.
Однажды столкнулась с тем, что вювер как-то неадекватно повёл себя при смене модели "на ходу". Отсюда и растут ноги моих рассуждений.
структура1\ / (вьювер2)
структура2--- модель --- вьювер1
структура3/ ...
Сдаётся мне, всё это фигня и извращение.
Немножко поразмышляла.
Думаю, нужен симбиоз ваших двух предложений:
сделать std::map<пара_указателей_источник_данных_вьювер, труктура_описания_свойств_отображения_объекта>,
но не во вьювере, а в контроллере, который будет наблюдать за вьювером, и фиксировать его действия.
void QAbstractItemView::setModel(QAbstractItemModel *model)
{
Q_D(QAbstractItemView);
if (model == d->model)
return;
if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
disconnect(d->model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(dataChanged(QModelIndex,QModelIndex)));
disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
this, SLOT(_q_headerDataChanged()));
disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(rowsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
this, SLOT(_q_columnsInserted(QModelIndex,int,int)));
disconnect(d->model, SIGNAL(modelReset()), this, SLOT(reset()));
disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
}
d->model = (model ? model : QAbstractItemModelPrivate::staticEmptyModel());
// These asserts do basic sanity checking of the model
Q_ASSERT_X(d->model->index(0,0) == d->model->index(0,0),
"QAbstractItemView::setModel",
"A model should return the exact same index "
"(including its internal id/pointer) when asked for it twice in a row.");
Q_ASSERT_X(!d->model->index(0,0).parent().isValid(),
"QAbstractItemView::setModel",
"The parent of a top level index should be invalid");
if (d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
connect(d->model, SIGNAL(destroyed()),
this, SLOT(_q_modelDestroyed()));
connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(dataChanged(QModelIndex,QModelIndex)));
connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
this, SLOT(_q_headerDataChanged()));
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(rowsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)),
this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
connect(d->model, SIGNAL(columnsInserted(QModelIndex,int,int)),
this, SLOT(_q_columnsInserted(QModelIndex,int,int)));
connect(d->model, SIGNAL(modelReset()), this, SLOT(reset()));
connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
}
QItemSelectionModel *selection_model = new QItemSelectionModel(d->model, this);
connect(d->model, SIGNAL(destroyed()), selection_model, SLOT(deleteLater()));
setSelectionModel(selection_model);
reset(); // kill editors, set new root and do layout
}
Анна, указатель - это буквально указатель )
поскольку список текущих настроек отображений объектов не может принадлежать самим объектам (будет конфликт), то этот список должен быть у вьюера. Причём важно своевременно синхронизировать список при удалении/добавлении наблюдаемых объектов. Либо при доступе проверять, есть ли такой указатель в штатном кутешном списке вьюера.
И отсюда вытекает более правильное, на мой взгляд решение: менеджер объектов и вьюеров. У него есть список объектов, список вьюеров и список настроек
class manager
{
//структура настроек отображения
struct s_options
{
};
typedef std::map<object_id, object_pointer > td_obj_list;
typedef std::map<viewer_id, viewer_pointer> > td_view_list;
typedef std::map<object_id, std::map<viewer_id, s_options> > td_obj_view_list;
td_obj_list m_obj_list;//список объектов
td_view_list m_view_list;//список вьюеров
td_obj_view_list m_obj_view_list;//ассоциация
public:
//методы работы с массивами - создание объектов, удаление, доступ
};
lanz,
Не не не, вьюха не может удалять модель, а если она одна на несколько вьюх? Тут что то не связанное с привязкой (мы ведь про setModel() говорим?).
lanz, ну да. Тогда согласен ) Просто у меня был несложный случай - одна модель и одно представление
Анна, setModel(0)
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)