crossplatform.ru

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

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Очень интересная проблема проектирования, Надеюсь на помощь гуру
explorer85
  опции профиля:
сообщение 3.8.2011, 19:12
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 18.3.2011
Пользователь №: 2517

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




Репутация:   0  


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

Есть две сущности
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??????

PS: Сразу скажу я эту проблему решил но на свой взгляд криво, и не уверен в правильности решения, и некоторые вещи у меня не работают.
PPS: Если кому интересно выложу здесь свои свои решения у меня их 2 одно реализовано криво другое не реализовано есь только идея.
PPPS: Очень надеюсь на помощь людей которые считают себя реально прокаченными в MVC ...и вообще всех homosapiens))
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
explorer85
  опции профиля:
сообщение 3.8.2011, 20:04
Сообщение #2


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 18.3.2011
Пользователь №: 2517

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




Репутация:   0  


И так мое первое решение реализованное.

//класс хранилище данных берет данные из базы данных и предоставляет их моделям
class Storage : public QObject
{
    Q_OBJECT
public:
    Storage();
    //добавить задачу
    void addTask(Task tsk);
    //удалить задачу
    void removeTask();
    //вернуть все задачи с id проекта
    QVector <Task> tasksAtProject(int id);
    //вернуть все задачи с принадлежащие группе
    QVector <Task> tasksAtGroup(int n);
    //заменить задачу в списке задач
    void replaceTask(Task tsk);
    //заменить проект в списке проектов
    void replaceProject(Project prj);
private:
   QVector <Task> tasks;
    QVector <Project> projects;
};


Создается экземпляр данного класса.

После этого создаютя две модели производные от QAbstractItemModel, в эти модели передается указатель
на экземпляр Storage
Модель #1: строится по правилам модели списка (использует только tasks) и отображает их на QListView
Модель #2: строится по правилам модели дерева (использует projects - верхний уровень родители, tasks - нижний уровень дети) и отображает их на QTreeView)
В кажой модели по одному столбцу все данные из структур Task и Project передаются юзерролями, и обрабатываются кастомными делегатами.

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

ПРОБЛЕМА!!!
Данные в моделях и представлениях не синхронизируются между собой!!!
НАПРИМЕР!!!
Добавляем в виде №2 (дерево) строку(задачу) : делаем в модели №2

begininsertrows()
storage_ptr->addTask(Task tsk);
endinsertrows()


данные добавляются в QVector <Task> tasks;
модель №2 уведомляется о том что данные добавились

а вот модель и представление №1 НИЧЕГО ОБ ЭТОМ НЕ ЗНАЮТ
ПОЭТОМУ ПРИ ПЕРЕХОДЕ К ВИДУ №2 мне приходится делать reset() что неправильно я думаю но другого выхода не вижу

вот схема моего варианта, там еще 2 прокси модели для сортировки данных


А вот схема моего второго варианта, если вкратце то мы исползуем не 2 независимые модели, а модель дерева как основную потому что в ней есть все данные и задачи и проекты,
а для представления задач списком используем прокси модель, но тут тоже проблема я не знаю как из модели дерева через прокси сделать модель списка и вообще возможно ли это?
Вобщем друзья выручайте желательно конкретными советами и с аргументированной критикой моих решений или наоборот! Всем зараннее большое спасибо!!!

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.8.2011, 7:28
Сообщение #3


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

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

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




Репутация:   34  


explorer85, привет!

за работу с моделью подсказать ничего не могу, а насчёт организации хранения данных, я бы вот так сделал
Раскрывающийся текст
#include <map>

struct Project
{
    int ProjectID; //ключ

    ........
};

struct Task
{
    int TaskID;     //составной ключ
    int ProjectID;  //
    
    .......
};


//таблица проектов
typedef std::map<int /*ProjectID*/, Project> td_projectList;

//таблица задач
typedef std::map<int /*ProjectID*/, std::map<int /*TaskID*/, Task> > td_taskList;

//библиотека проектов
class CProjectLibrary
{
private:
    td_projectList m_projectList;
    td_taskList m_taskList;

    //счётчик изменений
    int m_ChangeCounter;

public:
    ......

    int GetChangeCounter()const
    {
        return m_ChangeCounter;
    }

};


суть в следующем: у CProjectLibrary должны быть открытые функции, которые позволяют работать с закрытыми списками. При внесении одного или группы изменений каждая такая функция увеличивает счётчик изменений. Теперь, любой отображающий данные виджет может глянуть - не отличается ли значение счётчика от последнего использованного ? Если отличается, то перерисоваться.

Ну и не забывай про синхронизацию внутри CProjectLibrary, если присутствует многопоточнсть

Сообщение отредактировал Алексей1153 - 4.8.2011, 7:29
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
explorer85
  опции профиля:
сообщение 4.8.2011, 9:34
Сообщение #4


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 18.3.2011
Пользователь №: 2517

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




Репутация:   0  


Алексей1153, спасибо за совет да с мапами пологичней и побыстрей. А насчет счтечика... дело в том что проекты и задачи отображаютя исключительно но через модели на представлениях и я их пробовал уведомлять сигналом , ну по аналогии с вашим счетчиком, но столкнулся с проблемой описанной в конце способа №1.
Эх неужели никто всерьез не работал с моделями??? перечитал эту ветку за год похожие проблемы вроде встречались.... Неужели все в отпусках и на каникулах........
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.8.2011, 10:06
Сообщение #5


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

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

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




Репутация:   34  


explorer85, мне тут вот что непонятно: массивы инкапсулированы. Если наружу не выдавать на них ссылок или указателей, то менять содержимое смогут только открытые функции CProjectLibrary. А это означает, что любое изменение можно отследить всегда.

Если же пресловутая модель (я не сталкивался ещё пока) не позволяет работать с таким классом совместно, то у меня возникают сомнения насчёт нужности этой самой модели в данном случае.


PS нэгодующая модэль : http://i9.photobucket.com/albums/a55/peppe...models/l152.jpg

Сообщение отредактировал Алексей1153 - 4.8.2011, 10:09
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
explorer85
  опции профиля:
сообщение 4.8.2011, 10:24
Сообщение #6


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 18.3.2011
Пользователь №: 2517

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




Репутация:   0  


Цитата(Алексей1153 @ 4.8.2011, 11:06) *
explorer85, мне тут вот что непонятно: массивы инкапсулированы. Если наружу не выдавать на них ссылок или указателей, то менять содержимое смогут только открытые функции CProjectLibrary. А это означает, что любое изменение можно отследить всегда.


Все правильно, любое изменение можно отследить так как данные в массивах изменяются только с помощью открытых функции CProjectLibrary. Но проблема то не в этом!!!
Еще раз повторюсь есть задача отображать эти данные в двух разных видах указанным способом...(в первом посте я все понятно обьяснил? может просто недопонимание какое то есть)
Я нашел решение которое привел во 2 посте. Проблема в том что я не могу понять правильно ли я сделал применительно к философии mvc в qt или нет, и хочу спросить как бы вы решили эту проблему? :rolleyes:

Я ужасно извиняюсь, ну просто мне кажется что для понимания моей проблемы, нужен человек который имеет опыт написания собствеееных моделей производных от QAbstractItemModel и прокси QAbstractProxyModel

Вот я конечно может быть много прошу но мне нужны как бы два ответа 1 теоретический, о правильности выбранной мной концепции 2 практический применительно этой концепции к конкретным классам QAbstract***Model в Qt

Цитата(Алексей1153 @ 4.8.2011, 11:06) *
Если же пресловутая модель (я не сталкивался ещё пока) не позволяет работать с таким классом совместно, то у меня возникают сомнения насчёт нужности этой самой модели в данном случае.

В том то и дело что я не могу врубиться как организовать правильную работу со этим своим классом MVC фреймворка Qt!!!

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.8.2011, 10:27
Сообщение #7


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

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

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




Репутация:   34  


explorer85, да, видимо я что-то не понимаю. Послежу :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
explorer85
  опции профиля:
сообщение 4.8.2011, 10:32
Сообщение #8


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 18.3.2011
Пользователь №: 2517

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




Репутация:   0  


В том то и дело что я не могу врубиться как организовать правильную работу между своим классом и стандартными интерфейсами QAbstract**Model MVC фреймворка Qt!!! Не понимаю правильно я их настроил для работы (создал два подкласса QAbstractItemModel в них передал указатели на свой класс с данными итд, ну начинаю повторяться уже)


Алексей1153 Ну вообще проблема ясно сформулирована? чтобы мне знать а то может быть и другие люди не поймут? :mellow:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 4.8.2011, 10:48
Сообщение #9


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

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

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




Репутация:   34  


проблема описана очень ясно и крупно:

Цитата
ПРОБЛЕМА!!!
Данные в моделях и представлениях не синхронизируются между собой!!!
<...>
данные добавляются в QVector <Task> tasks;
модель №2 уведомляется о том что данные добавились

а вот модель и представление №1 НИЧЕГО ОБ ЭТОМ НЕ ЗНАЮТ



по сути у тебя аналог окна виндового Explorer (дерево папок слева, содержимое папки - справа) только не для файловой системы, а для дерева проектов

Ты упоминаешь, что передаёшь указатель на экземпляр своего класса. При изменениях меняется счётчик. Уведомлений, конечно же, никаких не произойдёт, их надо инициировать. Я бы сделал проверку по таймеру (скажем, раз в секунду) счётчика, и при его изменении обновлял бы представление, которое не в фокусе (тут спорный вопрос - наверное, вместе со счётчиком полезно запоминать инициатора изменений, чтобы его не обновлять)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
explorer85
  опции профиля:
сообщение 4.8.2011, 11:23
Сообщение #10


Студент
*

Группа: Новичок
Сообщений: 12
Регистрация: 18.3.2011
Пользователь №: 2517

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




Репутация:   0  


Цитата(Алексей1153 @ 4.8.2011, 11:48) *
по сути у тебя аналог окна виндового Explorer (дерево папок слева, содержимое папки - справа) только не для файловой системы, а для дерева проектов

Да попал в точку. Щас потыркал проводник та же концепция. Ну только разве что эти два вида у меня доступны не одновременно. А так тоже самое слева проекты, справа задачи)) и если обратил внимание то и модель фильтрации и сортировки для каждого вида тоже своя. Ведь в проводнике если справа в списке сортировать элементы то влевом они остаются в том порядке каком и были. ну это так философия. Хотя интересно как там сделано))

Цитата(Алексей1153 @ 4.8.2011, 11:48) *
Ты упоминаешь, что передаёшь указатель на экземпляр своего класса. При изменениях меняется счётчик. Уведомлений, конечно же, никаких не произойдёт, их надо инициировать. Я бы сделал проверку по таймеру (скажем, раз в секунду) счётчика, и при его изменении обновлял бы представление, которое не в фокусе (тут спорный вопрос - наверное, вместе со счётчиком полезно запоминать инициатора изменений, чтобы его не обновлять)

Да тут все проще зачем таймер если есть сигналы и слоты :rolleyes: Просто я говорил проблема с индексами что нельзя корректно уведомить второе представление об изменениях в первом так как модельные индексы у них разные потому что они связаны с двумя моделями..................

И еще один ньюанс... не хотел пугать просто... Допустим мне захотелось сделать группировку списка задач по каким либо признакам... например по важности (в структуре Task есть такое поле importance) от (0 - 5)
какое я щас вижу решение? делать еще одну связку модель + представление + делегат, передавать модели указатель на Storage с данными .........ну итд. То есть получается некислое дублирование кода, рост сложности кода проекта ну итд со всеми вытекающими.... И я так наверное и сделаю если никто ничего не посоветует выдающегося.... Эх где вы победители школьных олимпиад, эйнштейны, знатоки qt :rolleyes:

Извиняюсь за флуд... но мне почему то кажется что если бы эту тему увидел парень из troolteh котроый писал MVC фреймворк он бы сказал "Не парься брат делай void QAbstractItemModel::reset () для второй модели" :rolleyes:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 28.3.2024, 11:31