Russian Qt Forum

Qt => Model-View (MV) => Тема начата: explorer.85 от Август 02, 2011, 13:16



Название: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 13:16
Всем привет! Вообще нечасто создаю темы на форумах стараюсь до всего дойти,
сам но тут проблема решения (правильного решения) которой не вижу уже дня 2.
И так профессионалы, представляю проблему подробно (она тут в других ветках освещалась
но толи я дурак, то ли не совсем с того ракурса в котором она возникла у меня).
Начнем.
 
Есть 2 сущности(класса или структуры как угодно)
задача (Task) и
проект (Project)

Есть два списка QVector<Task> tasks - это список с задачами
и
QVector>Project> projects - это список с проектами
причем у задачи есть  поле Task::ProjectID и у проекта есть поле Project::ProjectID
эти поля нужны так как проект может включать в себя задачи из списка задач.

Есть функция QVector <Task> tasksAtProject(int id) //вернуть все задачи с id проекта

Есть класс:

Код:
class Storage
{
public:
    Storage() {
        tasks = DataBaseApi::SelectAllTasks();
        projects = DataBaseApi::SelectAllProjects();
    };
    //вернуть все задачи с id проекта
    QVector <Task> tasksAtProject(int id)
.........
private:
    QVector <Task> tasks;
    QVector <Project> projects;
};
Он читает из базы данных задачи и проекты, хранит их в себе и предоставляет эти данные моделям.
Моделей 2 штуки
№1 Иерархическая модель проектов (class ProjectModel : public QAbstractItemModel) + QTreeView:
проект1
  задача1
  задача2   
проект2
  задача3

№2 Модель списка задач        (class TaskModel : public QAbstractItemModel)  + QTableview:
задача1
задача2
задача3

(для справки во всех моделях columncount ==1, все данные из структур Task и Project передаются с помощью ролей
и отображаются самописными делегатами)

Вот....
Еще к каждой модели привязана QSortFilterProxyModel для фильтрации данных.

Теперь скажу что меня не устраивает:
При добавлении или редактировании данных в модели с проектами или с задачами (например вставка строки(новой задачи)) не обновляется модель и представление с задачами,
 
Код:
beginInsertRows(QModelIndex(), ind, ind);
    Task tsk;
    storage_ptr->tasks.prepend(tsk);
    endInsertRows();
или
emit dataChanged();

я понимаю из за чего это я вставляю новую задачу в вектор с задачами и оповещаю об этом только модель и представление №1

Начал пробовать пойти по другому пути оставил модель №1 так как она содержит в себе все данные (и задачи и проекты) и создал свою производную от QAbstractProxyModel
(источник данных для которой модель #1)   взамен модели #2. Но тут столкнулся с двумя проблемами
1. Терзают сомнения правильный ли это путь
2. Немогу ф функции mapToSource преобразовать иерархическую модель #1 к модели списка (то есть пускать в прокси модель только задачи а проекты не пускать)

Какие бы советы хотелось бы услышать?
1. Правильным путем я сделал все или нет?
2. Какие есть еще варианты?

Вобщем если кто нибудь дочитал до конца большое спасибо, а если еще и посоветуете что нибудь полезное то вообще огрмнющщее.
Сам я в тупике....


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 13:29
Чтобы совсем все было понятно приведу даже картинки
http://www.imagepost.ru/?v=projectsandtasks.png
слева QTreeView которую обеспечивает данными иерархическая модель №1
справа QTableView которую обеспечивает данными модель списка №2 (правильно говорить модель таблицы а не списка но так как у меня там 1 столбец то для меня она модель списка:)

Повторюсь, о проблемах
1. добавляем или редактируем задачу в модели №1 данные в модели №2 не обновляются
2. А правильно ли это что у меня 2 модели? или может быть лучше оставить модель #1 и сделать проксю к ней для списка задач, но тут проблема как преобразовать иерархическую модель в модель списка


Название: Re: Большая проблема, может быть даже философская
Отправлено: m_ax от Август 02, 2011, 13:52
Мне кажется в данном случае должна быть одна модель. Та что с проектами, поскольку, как я понял, она содержит в себе данные и для задач.
Зачем тогда дублировать данные?  

Хотя, подозреваю, что я чёта не так понял..


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 14:04
да все правильно вторая модель дублирует данные с задачами, просто я не знаю как преобразовать данные из иерархической модели с проектами в модель списка, меня хватило только вот на это:


Код:
QModelIndex TaskProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
//возвращаем индексы всех задач из второго проекта  ( sourceModel()->index(1,0) )
return sourceModel()->index(proxyIndex.row(), 0,sourceModel()->index(1,0));
}
QModelIndex TaskProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    return createIndex(row, column);
}

QModelIndex TaskProxyModel::parent(const QModelIndex &child) const
{
    return QModelIndex();
}
//вычисляем количество строк нижнего уровня (с задачами) в иерархической модели
int TaskProxyModel::rowCount(const QModelIndex &parent) const
{
    int rows = 0;
    for ( int i = 0; i < sourceModel()->rowCount(QModelIndex()); i++)
    {
        for ( int j = 0; j < sourceModel()->rowCount(sourceModel()->index(i,0)); j++)
        {
                rows++;
        }

    }
    return rows;
}

int TaskProxyModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}
QVariant TaskProxyModel::data(const QModelIndex &index, int role) const
{
   return sourceModel()->data(mapToSource(index), role);
}

Вобщем я не знаю как функцией mapToSource вернуть индексы всех задач, в результате работы этого кода у меня получается вот что:
если модель проектов
проект 1
   задача 1
проект 2
   задача 2
   задача 3
   задача 4
то на выходе из TaskProxyModel в представление QTableview получается
задача 2
задача 3
задача 4
ПУСТАЯСТРОКА

так как количество строк с задачами в исходной модели я вычисляю верно их 4
а самих индексов задач передаю только 3 штуки.
Может я просто не силен в алгоритмах? Где копать? что то в функции mapToSource хитрое нужно дописать?
или может как то по особому нужно сделать иерархическую модель №1. Она у меня сделана кстати по примерам из доков стандартно
,Или даже проще в ней жестко задано 2 уровня индексов,
верхний проекты нижний задачи вкратце
Код:
QModelIndex ProjectModel::index(int row, int column, const QModelIndex &parent)
            const
{
    if (!hasIndex(row, column, parent))
            return QModelIndex();
    if (!parent.isValid())
    { // Первый уровень
            return createIndex(row, column, -1); // Родитель с индексом -1
    }else if (parent.internalId() == -1)
    {// Второй уровень
            return createIndex(row, column, parent.row()); // номер строки родителя.
    }
    return QModelIndex();
}


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


Название: Re: Большая проблема, может быть даже философская
Отправлено: m_ax от Август 02, 2011, 14:29
Тогда, как вариант, пишите свой класс (адаптер, так сказать), который содержит список проектов.
А указатель на этот класс передавайте в ваши модели. Можно в этом адапторе повесить сигнал dataChanged(параметры по-вкусу) который будет имитеть при изменении данных.
В конструкторе моделей соединяете сие сигнал со слотом где вызываете сигнал соответствующей модели dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight).
Примерно так..

 


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 14:53
m_ax: хороший совет спасибо.
Помоему вы меня правильно поняли.

То есть что получается, оповещать представления по идеологии qt нужно в трех случаях (insertrows)вставка (removerows)удаление (datachanged)изменение
сейчас у меня это делается в каждой из двух моделей особняком т.е. вставили данные в модель №1 вызвался №1::insertrows, вставили данные в модель №2 вызвался
 №2::insertrows. Соответственно отсюда и проблема представление №2 необновляется если мы изменили модель №1.

Я попробую сделать так как вы посоветовали.

Но все таки остаются вопросы 1 я наверное вынесу в отдельную тему
1. Как преобразовать через прокси иерархическую модель из двух уровней в модель списка которая  содержит все элементы из нижнего уровня иерархической модели?

2. Какой путь все таки лучше мой текущий 2 модели и 2 представления или 1 модель 1 прокси модель и 2 представления




Название: Re: Большая проблема, может быть даже философская
Отправлено: m_ax от Август 02, 2011, 15:09
Адаптер предоставляет интерфейс для радактирования ваших данных, а так же для получения списка всех проектов, списка всех задач в конкретном проекте (это уж как вы организуете архитектуру адаптера).
В нём также можете объявить сигнал, срабатывающий при изменении данных, через интерфейс адаптера.
Создаёте две модели: одну от QAbstractListModel, вторую от QAbstractItemModel, обе будут внутри содержать указатель на адаптер.
В методах setData вызываете соответствующие функции адаптера. Никаких сигналов типа dataChanged здесь явно не вызываете. Это будет делать адаптер.
Просто в конструкторе соедините его сигнал (адаптора) с соответствующем слотом (в котором один раз будет происходить обновление модели) и всё.
У вас будут обновляться сразу две модели при изменении какой-либо одной.     

Вобщем, бог в помощь)


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 15:12
еще раз спасибо очень понятно все обьяснили, буду делать, о том получилось или нет скоро напишу


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 15:33
И все таки еще кое-что спрошу.
1. Значит я выбрал правильную архитектуру для своей задачи, 2 модели + 2 представления + один адаптер?? Просто получается дублирование задач в этих двух моделях.  
Или это же опять вопрос философский есть несколько путей в том числе и этот и они все правильные??

2. Я еще не сказал кое что, есть еще одна задача группировать задачи по какому либо полю.
Например у задачи есть поле важность от 0 до 5. И мне нужно сгруппировать задачи по важности. Я думаю сделать это так: создать еще одну иерархическую модель + еще один QTreeView и подцепить их к нашему адаптору из адаптора буду брать задачи для нижнего уровня  модели и список групп для верхнего уровня модели например QVector<int> groups {1,2,3,4,5} .
Вы бы сделали так же?
Таким образом получается еще одно дублирование списка задач и 3 модели + 3 представления + адаптер. (честно говоря меня до сего момента смущала во всем этом подходе гемморой синхронизации между моделями, но если воспользоваться вашим советом то можно делать хоть 10 моделей и представлений, а адаптер то останеться один и останется в них только вызывать функции адаптера )
Ну как сказать дублирование сам я эти списки загружаю в память один раз в класс адаптер. Что делают с ними эти 3 кутешные модели я не знаю, можно это считать дублированием или нет?

Ну соответственно придерживаясь такого понимания модели представления, получается что сама НАСТОЯЩАЯ модель данных это наш класс адаптер а кутешные модели лишь средство доставки данных из нашей модели в кутешные стандарные представления??

m_ax: Ответьте еще разок пжалста успокойте мой разум, если на все вопросы ответите Да, то я буду считать что неплохо разобрался с mvc в qt))


Название: Re: Большая проблема, может быть даже философская
Отправлено: m_ax от Август 02, 2011, 15:58
Мне не совсем понятно:
Представление для задач - отображает все задачи или только задачи для одного проекта?
Если все задачи, то при добавлении задачи получается не однозначность? в смысле не определено к какому именно проекту будет добавлена задача.


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 16:04
m_ax: и еще фатальную нестыковку обнаружил в методе с адаптером, а уж было обрадовался.
Например я редактирую данные в модели №1 вызываю метод адаптера Adapter::editTask(int task_id, QModelindex index)  - где task_id идентификатор по которому я найду задачу в своей векторе а
index - индекс строки модели которую мы редактируем.
В методе Adapter::editTask мы по логике должны испустить свой сигнал myDataChanged(QModelindex index) который в свою очередь присоединен к соответствующим сигналам моделей но если в ту модель которую мы редактируем придет правильный QModelindex, то в другую модель придет  QModelindex от чужой модели и соответственно будет ошибка.



Название: Re: Большая проблема, может быть даже философская
Отправлено: UNION labs от Август 02, 2011, 16:08
Здравствуйте.
А каким образом у вас создаются модели?
что-то вроде вот этого:

Код:
class Storage
{
public:
.........
    ProjectModel getProjectModel() const;
    TaskModel getTaskModel() const;
.........
};

Если да, то может просто следует уведомлять класс Storage когда обновляется одна из моделей, а он в свою очередь будет обновлять вторую?

P.S. Это еще про случай, когда не было адаптера...


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 16:15
m_ax: к вашему предыдущему посту, ну вообще идея такова пользователю доступны два представления (два окошка в интерфейсе) "проекты - treeview" и "задачи - listview". В первое он может добавить проект а так же к проекту добавить задачу. во второе может добавить только задачи но в нем так же отображаются и те задачи которые были добавлены в окошке "проекты"
Изначальное состояние системы QVector<Task> tasks - ничего не содержит, QVector<Project> projects содержить в себе один проект (пользователь не может его отредактировать и он его не видит но в него попадают все задачи которые он создает в представлении со списком, как бы такой системный проект "Без проекта")


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 16:24
:UNION labs только наоборот класс Storage это и есть адаптор просто к моменту открытия темы я не знал такого умного слова да он у меня им и не был наверное. Да что говорить вот реализация
Код:
Storage::Storage() {
    tasks = DataBaseApi::SelectAllTasks();
    projects = DataBaseApi::SelectAllProjects();
    contacts = DataBaseApi::SelectAllContacts();

};

//вернуть все задачи с id проекта
QVector <Task> Storage::tasksAtProject(int id)
{
    QVector <Task> _tasks;
    for (int i =0; i<tasks.size(); i++)
    {
        if (tasks.at(i).ProjectID == id)
            _tasks.push_back(tasks.at(i));
    }

    return _tasks;

}
//отредактировать задачу в списке задач
void Storage::replaceTask(Task tsk)
{
    for (int i =0; i<tasks.size(); i++)
    {
        if (tasks.at(i).TaskID == tsk.TaskID)
            tasks.replace(i,tsk);
    }
}
//заменить проект в списке проектов
void Storage::replaceProject(Project prj)
{
    for (int i =0; i<projects.size(); i++)
    {
        if (projects.at(i).ProjectID == prj.ProjectID)
            projects.replace(i,prj);
    }
}

экземпляр сего создается в самом начале вычитыват из бд задачи и проекты в конструкторе, а дальше создаются модели в них передается указатель на данное чудо, и они с ним работают
только вот в чем вопрос то был правильна ли сама архитектура такая? И вот нестыковка вышла если в методе replaceTask вызвать сигнал для изменения моделей то непонятно как получит индекс изменяемых данных во второй модели?

:UNION как я вас понимаю все происходящее вы предлагаете в принципе тоже что и m_ax


Название: Re: Большая проблема, может быть даже философская
Отправлено: m_ax от Август 02, 2011, 16:32
m_ax: и еще фатальную нестыковку обнаружил в методе с адаптером, а уж было обрадовался.
Например я редактирую данные в модели №1 вызываю метод адаптера Adapter::editTask(int task_id, QModelindex index)  - где task_id идентификатор по которому я найду задачу в своей векторе а
index - индекс строки модели которую мы редактируем.
В методе Adapter::editTask мы по логике должны испустить свой сигнал myDataChanged(QModelindex index) который в свою очередь присоединен к соответствующим сигналам моделей но если в ту модель которую мы редактируем придет правильный QModelindex, то в другую модель придет  QModelindex от чужой модели и соответственно будет ошибка.


Да нет, адаптер это класс унаследованный от QObject (чтоб можно было сигналы прикручивать), что то вроде:
Код
C++ (Qt)
class Storage : public QObject
{
Q_OBJECT
public:
   Storage() {...}
   addProject(const Project &pr) {
       container.push_back(pt);
       emit dataChanged();
   }
   addTask(int idProject, const Task &task) {
      ...
       emit dataChanged();
   }
   const QVector<Project> &projects() const;
   const QVector<Task> &allTask() const;
   const QVector<Task> &task(int idProject) const;
   ну и так далее
private:
   QVector<Project> container;
};
 
Адаптер не должен знать ни о каких QModelIndex и всё что связано с моделями


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 17:04
max да у меня так как вы написали сейчас все только вот смотрите
что я делаю с вашим сигналом dataChanged только у меня он TaskEdited

Код:
ProjectModel::ProjectModel(Storage *storage, QObject *parent)
    : QAbstractItemModel(parent)
{
    storage_ptr = storage;
    QObject::connect(storage_ptr, SIGNAL(taskEdited()),
                         this, SLOT( dataEdited() ));
}

void ProjectModel::dataEdited()
{
   emit dataChanged(this->index(0,0,QModelIndex()),this->index(rowCount(QModelIndex),0,QModelIndex()));
}

TaskModel::TaskModel(Storage *storage, QObject *parent) :  QAbstractItemModel(parent)
{
    storage_ptr = storage;
    QObject::connect(storage_ptr, SIGNAL(taskEdited()),
                         this, SLOT( dataEdited() ));
}
void TaskModel::dataEdited()
{
   emit dataChanged(this->index(0,0,QModelIndex()),this->index( rowCount(QModelIndex),0,QModelIndex()));
}

это для редактирования.....

для вставки аналогичная схема только с begininsertrows endinsertrows.....

То есть в модели сигналом emit dataChanged(this->index(0,0,QModelIndex()),this->index( rowCount(QModelIndex),0,QModelIndex())); приходится указывать не конкретный индекс для обновления
а весь диапазон индексом модели я правильно вас понял? А это не то же самое что reset()? извиняюсь за может быть дилетантские вопросы конечно...


Название: Re: Большая проблема, может быть даже философская
Отправлено: UNION labs от Август 02, 2011, 17:49
Вот какие мысли по теме родились:
1. Изначально назрела правильная архитектура -> одна модель (класс storage) и два представления (дерево проектов+задач и список задач).
2. Реализовать такую архитектуру средствами model/view фреймворка от Qt сложно (если вообще возможно (избегая дублирования данных и роста сложности кода проекта)... затраты наверняка не окупятся).
  - Как вариант можно реализовать наследника ListView который будет показывать элементы второго уровня дерева
3. По-моему для таких ситуаций целесообразней использовать ItemWidget'ы чем ItemView'ы, т.е. используя классическую схему mvc/mvp а не от Qt.


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 18:09
UNION labs: наследника от ListView реализовать..... на такое не способен, и я думаю вряди ктонибудь такими делами на этом форуме вообще занимается (ну я имею ввиду свои вьюхи делает). Наверное создать свое представление из QAbstractItemView но это тоже сложно. А можно ссылку где тролли пишут про itemWidget.  Я первым делом тоже о них подумал но помоему гибкости больше с mvc.

Цитировать
2. Реализовать такую архитектуру средствами model/view фреймворка от Qt сложно (если вообще возможно (избегая дублирования данных и роста сложности кода проекта)... затраты наверняка не окупятся).
а что делать приходится и в целом даже местами нравится что получается, хотя не знаю я с mvc больше нигде кроме qt не работал, может гдето это круче реализовано.

Вообще пессимистичный у вас пост получился >:( я все таки верю в Qt :)


Название: Re: Большая проблема, может быть даже философская
Отправлено: UNION labs от Август 02, 2011, 18:15
http://qt.nokia.com/learning/education/course-materials

20 слайд

"Sometimes separating the model from the view is too complex"


Название: Re: Большая проблема, может быть даже философская
Отправлено: Igors от Август 02, 2011, 18:16
Никогда не пользовался MVC (не нужно) и помочь здесь не смогу. Но задачи такого плана встречаются в моей практике часто. По поводу "правильно ли 2 модели" - безусловно правильно.

Представим себе что нет MVC, базы - надо просто это сделать на контейнерах (напр STL). Стопудово задачи храним в отдельном контейнере (вот и модель). Хотя бы потому что возможен вариант когда задача не входит ни в 1 из проектов. О каком "дублировании" данных идет речь? Если я правильно понял, проект хранит ID задач - какое же это дублирование? Да, 2 структуры данных должны быть синхронизированы, но это возникает в любой задаче "выше травы".

Так что смелее  и не позволяйте себя запугать высокопарным фуфлом типа "правильнвя архитектура"  :)


Название: Re: Большая проблема, может быть даже философская
Отправлено: UNION labs от Август 02, 2011, 18:18
Вообще пессимистичный у вас пост получился >:( я все таки верю в Qt :)

:) я же не говорю, что это не реально в принципе реализовать, я говорю о целесообразности затрат (затраченное время/результат).


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 02, 2011, 18:45
Igors: спасибо, ага почти правильно 2 вектора в одном задачи в другом проекты у каждой задачи есть id проекта к которому она принадлежит, да это и есть моя собственная модель данных, ну плюс обертка из класса storage и методов для доступа к этим данным.Это все отлично. То что сам пишешь всегда понимаешь. А вот дальше когда настраиваешь взаимодействие своей модели Storage и Qt-шных я же свою модель Storage не могу напрямую к QTreeView например прикрутить, потому что у меня нет интерфейса для этого. А есть qabstractitemmodel котороый как раз и позволяет любую модель которую я нафантазирую типа моего Storage, прикрутить к уже реализованной в Qt вьюхе. И все хорошо и все мне нравится но вот есть некоторые моменты которые не понятны.
На данный момент сделал как посоветовыал max но осталась проблема
Цитировать
То есть в модели сигналом emit dataChanged(this->index(0,0,QModelIndex()),this->index( rowCount(QModelIndex),0,QModelIndex())); приходится указывать не конкретный индекс для обновления
а весь диапазон индексом модели я правильно вас понял? А это не то же самое что reset()? извиняюсь за может быть дилетантские вопросы конечно...
Как то это неправильно.. или я неправильно сам понял max-a

UNION labs: А что делать фреймворк не выбирают :) в моем случае, а самому писать модели представления и контроллеры , вообще нереально.


Название: Re: Большая проблема, может быть даже философская
Отправлено: m_ax от Август 03, 2011, 11:24
Цитировать
Как то это неправильно.. или я неправильно сам понял max-a
Если данные меняются в адапторе минуя представление, то да предётся вызывать reset для модели.
И похоже, что это придётся делать всегда, поскольку обе модели ничего друг о друге не знают.

А как Storage у вас реализован?


Название: Re: Большая проблема, может быть даже философская
Отправлено: developer от Август 03, 2011, 13:24
Попробуй так.
Есть дерево.
        pid      type       name
id 1   0        project    SuperPr
id 2   1        task        Task1
id 3   1        task        Task2
id 4   1        task        Task3
id 5   0        project    SuperPr1
id 6   5        task        Task4

Ето была структура, дерево виглядит так

id 1, pid 0 SuperPr
id 2, pid 1   |__Task1
id 3, pid 1   |__Task2
id 4, pid 1   |__Task3
id 5, pid 0 SuperPr1
id 6, pid 5   |__Task4

Как видиш, мы работаем только с одной моделью. Каждый елемент имеет уникальный идентификатор - ID, поле PID нужно для дереваб есло оно 0 значит ето корень, если не ноль значит ето подкорень.
Теперь тебе нужно только правильно переписать что-то вроде refresh(bool) метода. Если нам нужно дерево - тогда строим дерево по приведеной више структуре з учетом всех PID, если нужни только задачи, значить фильтруем по TYPE=task и выводим просто список





Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 03, 2011, 13:47
developer: пока я пытаюсь осмыслить..... то есть я так понимаю реализовываь вы все это предлагаете  средствами QAbstractItemModel. то есть у нас будет один экземпляр самописного подкласса QAbstractItemModel подключенный одновременно к двум представлениям treeview и tableview? Данные в нем будут организваны по предложенной вами схеме, и будет метод refresh котроый будет менять эту модель превращая ее из списка в дерево и обратно?      
Но тогда придется подключать к этой модели вьюхи попеременно, потому что эта наша модель одновременно не может же находится в двух состояниях и обеспечивать две разные (QTreeView и QTAbleView) вьюхи данными.

Интересна практическая часть приментиельно к моделям Qt


Название: Re: Большая проблема, может быть даже философская
Отправлено: developer от Август 03, 2011, 14:37
Не совсем.

Тебе будет нужно что-то вроде:
1. QVector<MyItem*> items; где MyItem - ето структура типа

class MyItem{
char type;//1- Task, 2 - Project
int id;
int pid;
QString name;
}

2. Лучше использовать QTreeWidget. Поскольку он создаеться из QTreeWidgetItem'ов. А они подходят под задачу лучше всего. Поскольку есть возможность задавать парента
QTreeWidgetItem ( QTreeWidget * parent, int type = Type );

3. Теперь когда используеш refresh(bool) - если true тогда делаем дерево, иначе не делаем дерево, а просто добавляем итемы (как будто все они корневые).

 


Название: Re: Большая проблема, может быть даже философская
Отправлено: explorer.85 от Август 03, 2011, 19:01
ВНИМАНИЕ!!! Формулирую впрос еще раз БОЛЕЕ ПОНЯТНЫМ языком

ЗАДАДЧА.
Исходные данные:

Есть две сущности
1. Задача
Код:
struct Task
{
    int TaskID;
    int ProjectID;
    QString Name;
    QString Notes;
    int Importance;
.......
};
2. Проект

Код:
struct Project
{
    int ProjectID;
    QString Name;
    QString Notes;
........
};

Эти сущности можно добавлять в  списки

QVector <Task> tasks;
QVector <Project> projects;

Причем
при добавлении Задачи в tasks мы указываем ей ProjectID что указывает
на ее принадлежность к проекту с таким же ProjectID

при добавлении Проекта в projects мы указываем ему ProjectID.

Таким образом получается иерархическая связь на верхнем уровне проекты
на нижнем уровне задачи.
У одного проекта может быть несколько задач.
Задача одновременно может находится только в одном проекте.
НУ вобщем я думаю понятно двухуровневое дерево получается
проекты родители, задачи дети.
-----------------------------------------------------------
Необходимо реализовать GUI для работы  со списками этих сущностей.
-----------------------------------------------------------
Реализовать интерфейс ввода необходимо следующим образом, в двух видах:
1. Двухуровневое дерево проектов и задач.
Проект1
  Задача 1
  Задача 2
Проект2
  Задача 3
Без проекта
  Задача 4

Здесь можно добавить проект, удалить проект, отредактировать проект
Здесь можно добавить задачу к проекту, удалить задачу из проекта, отредактировать задачу.
Проект "Без проекта" отредактировать и удалить нельзя (он создается приложением автоматически
чтобы было куда добавлять задачи во втором виде)


2. Список задач.
 Задача 1
 Задача 2
 Задача 3
 Задача 4

Здесь можно добавить задачу, отредактировать задачу, удалить задачу
При создании задачи в этом виде она попадает в проект "Без проекта"


Вопрос как это сделать с помощью mvc фреймворка qt