crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Несколько источников данных + одно представление
Анна
  опции профиля:
сообщение 26.3.2013, 12:16
Сообщение #1


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Задача:
Есть несколько тоднотипных структур с массивами данных. Данные из массива текущей структуры отображаются во вьювере.

Допустим, один массив во вьювере отображается с 0-го по 5-й элементы, и выбран 3-й элемент, а второй массив отображается с 12-го по 17-й (например, ползователь прокрутил список) и выбран 12-й.
Хочется, чтобы при переключении текущей структуры положение вьюпорта и выбранного элемента соответственно менялось.

Кто должен отвечать за хранение "настроек отображения" для каждой структуры? Вроде бы проще всего отдать всё это на откуп вьюверу. Но не уверена.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 26.3.2013, 12:32
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


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

Лучше завести свой контроллер отображения для каждой структуры.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 26.3.2013, 15:26
Сообщение #3


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Мысли вслух:
А если появится второй, третий вьювер... Я их регистрирую в контроллере, и для каждого запоминаю, как именно в нём отображались данные.
Тогда всё будет работать так:
1.Структура стала текущей.
2.Контроллер текущей структуры выполняет действия:
- захватывает на себя сигналы от вьювера "изменился текущий элемент" и от его скроллеров "бегунок переместился"
- "раздаёт пинки" всем, зарегистрированным у него вьюверам -"отобрази с такого-то по такой-то"...
...
Почти универсально для таблицы и списка...

С деревом, где можно свернуть/развернуть элементы такое реализовать проблематично.
-----------------------------------
не бейте меня. Я стараюсь мыслить системно... Гы-гы-гы...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 26.3.2013, 16:30
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


В контроллере дерева можно хранить дерево свернутых/развернутых узлов например (первое что приходит в голову).

Вообще если не заморачиваться сильно (и при разумном количестве структур) можно положить все виды на QStackedWidget и просто выбирать нужный (тогда и сохранять ничего не надо будет).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 26.3.2013, 18:09
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


каждый вьюер должен иметь список ссылок на отображаемые им элементы + список описаний того, что сейчас отображено

то есть, это некий мап

std::map<указатель_на_объект, структура_описания_свойств_отображения_объекта>
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Анна
  опции профиля:
сообщение 27.3.2013, 10:21
Сообщение #6


Активный участник
***

Группа: Участник
Сообщений: 276
Регистрация: 22.5.2008
Из: Зеленоград
Пользователь №: 181

Спасибо сказали: 30 раз(а)




Репутация:   4  


Алексей1153, а что вы подразумеваете под "указатель_на_объект" ?
у вьювера уже есть модель...
Я думала, что можно одной и той же модели в качестве источника данных подсовывать разные структуры. Таким извращением не занималась, пока что. Это чисто теоретические изыскания.
Однажды столкнулась с тем, что вювер как-то неадекватно повёл себя при смене модели "на ходу". Отсюда и растут ноги моих рассуждений.

структура1\ / (вьювер2)
структура2--- модель --- вьювер1
структура3/ ...

Сдаётся мне, всё это фигня и извращение.

Немножко поразмышляла.
Думаю, нужен симбиоз ваших двух предложений:

сделать std::map<пара_указателей_источник_данных_вьювер, труктура_описания_свойств_отображения_объекта>,
но не во вьювере, а в контроллере, который будет наблюдать за вьювером, и фиксировать его действия.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 27.3.2013, 10:22
Сообщение #7


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата
Однажды столкнулась с тем, что вювер как-то неадекватно повёл себя при смене модели "на ходу"


Вот это поворот! А не вспомните случайно подробности?
Вью вроде бы все делает как надо
(в фолде исходники qt 4.8 )
Раскрывающийся текст
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
}


Сообщение отредактировал lanz - 27.3.2013, 10:23
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 27.3.2013, 13:16
Сообщение #8


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Анна, указатель - это буквально указатель )

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

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:
//методы работы с массивами - создание объектов, удаление, доступ
};

первичен объект, для него может быть несколько вьюеров, для вьюера сопоставлена структура настроек

Оцени, насколько это будет тебе удобно



смена модели вроде работает, только надо не забывать явно отцепить предыдущую, удалить её и потом прицепить новую, затем reset()

вот в деструкторах встречал падЁж, если явно не отцепить модель. Сильно тогда не вникал, почему так, просто сделал ручное удаление модели перед разрушением таблицы

Сообщение отредактировал Алексей1153 - 27.3.2013, 13:18
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 27.3.2013, 13:38
Сообщение #9


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата
И отсюда вытекает более правильное, на мой взгляд решение:


Ну, Анна по моему то же самое предлагает:
Цитата
сделать std::map<пара_указателей_источник_данных_вьювер, труктура_описания_свойств_отображения_объекта>,
но не во вьювере, а в контроллере, который будет наблюдать за вьювером, и фиксировать его действия.


Цитата
смена модели вроде работает, только надо не забывать явно отцепить предыдущую, удалить её и потом прицепить новую, затем reset()

Как так? Вон в исходниках делается reset(), слоты сигналы только перецепляются и все.
Если вью не является родителем модели, то она и не должна его удалять, не?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 27.3.2013, 13:43
Сообщение #10


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


lanz,
Цитата(lanz @ 27.3.2013, 16:38) *
Если вью не является родителем модели, то она и не должна его удалять, не?


там дело же такое - создали на куче модель, присоединили к объекту и забыли. По идее, должна удалять, но на деле там что-то не так происходит, сначала объект удаляется, потом модель лезет по кривой памяти. У меня как-то так и происходило. Поэтому я в деструкторе модель отцеплял, тогда не падало
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 20.4.2024, 2:40