Russian Qt Forum
Март 28, 2024, 12:16 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Голосование
Вопрос: Нужен ли Вам QSqlTreeView
Нужен очень
Ну пригодился бы
Не нужен, фигня это
А что это такое ?

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: QSqlTreeViewModel всем миром.  (Прочитано 31413 раз)
crossly
Гость
« Ответ #15 : Март 31, 2007, 18:19 »

ну рабяты.... вещь интересная... но для для своих целей я уже её реализовал...
Записан
Tonal
Гость
« Ответ #16 : Март 31, 2007, 19:51 »

Цитата: "-=QT=-"
ORM — (англ. Object-relational mapping) технология в программировании, которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая (как результат) «виртуальную объектную базу данных». Существуют как коммерческие, так и бесплатные реализации этой технологии.
А чем наша идея отличается от вышенаписанного?

Тем, с чем ты при написании кода оперируешь.
В случае ОРМ-а в коде ты оперируешь с объектами предметной области и их множествами (списками, деревьями, графами...).
В случае с SQL-моделями, оперируешь SQL-запросами, а объекты как бы и не появляются вовсе.

С объектами и их множествами какие надо модели пишутся легко.
Код явно можно разделить на собственно бизнес процессы, работу с сохранением/восстановлением, отображение.
И т.д. и т.п. Берём любую агитку по ООП и проникаемся. ;-)
Записан
SABROG
Гость
« Ответ #17 : Апрель 01, 2007, 23:50 »

И все-таки модель выходит зависимой от структуры таблицы. А раз так я предлагаю добавить еще одну колонку - Type, и сделать ее varcharом. Тогда можно будет отличать ветки и способ их обработки через тип. Например следующая таблица:

Код:

1       0       "TypeRoot"        "Магазин"     "Кристалл"
2       1       "TypeGoods"       "Товары"      ""
3       2       "TypeBeer"        "Пиво"        ""
4       3       "TypeMark"        "Балтика№9"   "22рубля"
5       3       "TypeMark"        "Балтика№3"   "20рублей"


Берем название каждого типа и регестрируем его в программе:

Код:

qRegisterMetaType<MyTypeClassOrStructure>(QLatin1String("MyTypeFromBase").latin1());


Присваиваем каждой ячейке свой тип:

Код:

                            MyTypeStruc *mt = new MyTypeStruc;
                                                mt->id = BeerBarcode;
                                                mt->str = "Note";
                                                QStandardItem *item = new QStandardItem();
                                                item->setData(Text,Qt::DisplayRole);
                                                QVariant gh;
                                                gh.setValue(*mt);
                                                item->setData(gh,Qt::UserRole);
                                                model->setData(index, gh );



Можно проделегировать каждую ячейку под свой тип:

Код:

QWidget *TypeDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem & option ,
    const QModelIndex & index ) const
{
        QVariant originalValue = index.model()->data(index, Qt::UserRole);
            else if ( originalValue.canConvert<MyTypeStruc>() )
            {
            QPushButton *button = new QPushButton(parent);
            button->setMaximumWidth(16);
            button->setText("...");
            connect(button, SIGNAL(activated(int)), this, SLOT(emitCommitData()));
            return button;
            }
}


В итоге мы будем точно знать какие данные в каких ячейках, как их обрабатывать какой интерфейс к каким данным предоставлять. Например если это BLOB поле с определенным типом, скажем Video, Audio, Picture, то мы сможем к каждому из таких типов привязать свою кнопочку с интерфейсом, который будет это обрабатывать.

добавлено спустя 6 минут:

 Только что-то мне подсказывает, что мы в итоге придем к Value Browserу
http://www.qt-apps.org/content/show.php/Value+Browser?content=50717
Записан
-=QT=-
Гость
« Ответ #18 : Апрель 02, 2007, 08:45 »

Изучаю все вышесказанное, курю маны. Спасибо за ссылку, очень интересный материал.
Записан
Вячеслав
Гость
« Ответ #19 : Апрель 02, 2007, 15:45 »

2 -=QT=- вопросец однако
Код:

        query.prepare( QString("SELECT %1 FROM %2 WHERE %3 = %4")
                       .arg(QSqlTreeViewModel::primaryFieldName)
                       .arg(QSqlTreeViewModel::tableName)
                       .arg(QSqlTreeViewModel::parentFieldName)
                       .arg(id) );

А нафига каждый раз-то prepare дергать ? при прямом форматировании проще в exec сразу все сунуть ....
Записан
-=QT=-
Гость
« Ответ #20 : Апрель 03, 2007, 07:44 »

Цитата: "Вячеслав"
2 -=QT=- вопросец однако
Код:

        query.prepare( QString("SELECT %1 FROM %2 WHERE %3 = %4")
                       .arg(QSqlTreeViewModel::primaryFieldName)
                       .arg(QSqlTreeViewModel::tableName)
                       .arg(QSqlTreeViewModel::parentFieldName)
                       .arg(id) );

А нафига каждый раз-то prepare дергать ? при прямом форматировании проще в exec сразу все сунуть ....


Привычка...

добавлено спустя 6 минут:

 Непонимаю я ничего в этом тривью .... А-а-а-а-а-а-а-а-а-а-а-.......
Ну бросте какой нить пример хоть кусок а.НепонимающийНепонимающий
А то я когонибуть невинного порву на кучу медвежат уууууууюююююю.....
Ну не может быть в это ничего сложного но меня переклинило.....
HELP HELP
Записан
Georgest
Гость
« Ответ #21 : Апрель 08, 2007, 21:28 »

Цитировать
Непонимаю я ничего в этом тривью .... А-а-а-а-а-а-а-а-а-а-а-.......
Ну бросте какой нить пример хоть кусок а.НепонимающийНепонимающий
А то я когонибуть невинного порву на кучу медвежат уууууууюююююю.....
Ну не может быть в это ничего сложного но меня переклинило.....
HELP HELP


В Qt есть модель QDirModel, которая стыкуется с QTreeView.
Надо понимать, что хороший QSqlTreeModel можно слизать с этого самого QDirModel (файл src/gui/itemviews/qdirmodel.h и .cpp).
Ключевые методы: rowCount, columnCount, data, setData, headerData,
hasChildren, flags.
Записан
Вячеслав
Гость
« Ответ #22 : Апрель 08, 2007, 22:37 »

Цитата: "-=QT=-"
Цитата: "Вячеслав"
2 -=QT=- вопросец однако
Код:

        query.prepare( QString("SELECT %1 FROM %2 WHERE %3 = %4")
                       .arg(QSqlTreeViewModel::primaryFieldName)
                       .arg(QSqlTreeViewModel::tableName)
                       .arg(QSqlTreeViewModel::parentFieldName)
                       .arg(id) );

А нафига каждый раз-то prepare дергать ? при прямом форматировании проще в exec сразу все сунуть ....


Привычка...

Несколько фиговая привычка - если сделан prepare - то правильнее и быстрее прокинуть параметры через bind .... А какие грабли с treeview-то ?
Записан
-=QT=-
Гость
« Ответ #23 : Апрель 09, 2007, 11:25 »

Цитировать
Несколько фиговая привычка - если сделан prepare - то правильнее и быстрее прокинуть параметры через bind .... А какие грабли с treeview-то ?

Возможно что и плохая я с SQL серверами раньше не работал. Только изучаю, спасибо за подсказку. А с тривью проблема - не понимаю что нужно наследовать и какие методы и свойства необходимо наследовать для правильного использования. Спасибо (Georgest) поизучаю его подсказку.
Записан
-=QT=-
Гость
« Ответ #24 : Апрель 12, 2007, 13:07 »

В общем поматырился я неделю, а может и более и перепрыгнул с QTreeView на QTreeWidget & QTreeWidgetItem.
Все рисуется как нужно, вот только как будет работать с большими обьемами не знаю еще. По крайней мере буду вводить ограничения по каким то условиям. Смотрел код, который в QT по sqlmodel  sqltablemodel там такого понапихано в ообщем еще осталось желание, но нет пока времени, так что все еще в переди.
Модель которую я получил выводила итемы в тривью но без иерархии, а потом еще вопросы связывания с БД и т.п. все в сыром виде, как закончу или получу промежуточную рабочую версию обязательно опубликую.
Записан
SABROG
Гость
« Ответ #25 : Апрель 13, 2007, 17:22 »

А че ты матырился ? Вот так работать с modelью можно:

Код:

        QStandardItemModel *model = new QStandardItemModel;
        model->setColumnCount(2);

        model->setHeaderData(0, Qt::Horizontal, tr("Key"));
        model->setHeaderData(1, Qt::Horizontal, tr("Value"));

        TreeView1->setModel(model);

        QStandardItem *Root1 = new QStandardItem("Root1");
        QVariant itemData = 1; // для теста присвоим значение 1
        Root1->setData(itemData, Qt::UserRole); // и установим его в итем
        model->setItem(0,0,Root1); // первая строка, первая колонка

        QStandardItem *ChdRoot1 = new QStandardItem("Child of Root1"); // создадим дочерний элемент
        itemData = 2;
        ChdRoot1->setData(itemData, Qt::UserRole);
        Root1->setChild(0,0,ChdRoot1); // установим ребенка в первую строку, первую колонку родительского элемента (не глобальной модели!)

        QStandardItem *ChdValue1 = new QStandardItem("Value of Child");
        itemData = 3;
        ChdValue1->setData(itemData, Qt::UserRole);
        Root1->setChild(0,1,ChdValue1); // установим ребенка во вторую колонку, первой строки для родителя

Записан
-=QT=-
Гость
« Ответ #26 : Апрель 16, 2007, 14:15 »

Для отображения вот ....
Код:
void SqlTreeModel::refreshAllString(int id, QStandardItem *parent)
{
    QSqlQuery q;
    if (id==-1)
        id = 0;
    q.exec(QString("SELECT * FROM %1 WHERE %2=%3").arg(tableName).arg(parentFieldName).arg(id));

    while ( q.next())
    {
        QStandardItem *item = new QStandardItem(q.value(2).toString());
        QList<QStandardItem *> itemColumn;
        itemColumn << item;
        if (q.record().count()>2)
        {
            for (int i=3; i<q.record().count(); ++i)
            {
                QStandardItem *columnItem = new QStandardItem(q.value(i).toString());
                itemColumn << columnItem;
            }
        }
        parent->appendRow(itemColumn);
        refreshAllString(q.value(q.record().indexOf(primaryFieldName)).toInt(), item);
    }
}
Потом нужно еще реализовывать редактирование и все такое ....

добавлено спустя 4 минуты:

 Но хочется сделать от абстрактной модели данных.
-------------------
Код
C++ (Qt)
#ifndef TREEMODEL_H
#define TREEMODEL_H
 
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
 
class TreeItem;
 
class TreeModel : public QAbstractItemModel
{
   Q_OBJECT
 
public:
   TreeModel(const QString &table, QObject *parent = 0);
   ~TreeModel();
 
   QVariant data(const QModelIndex &index, int role) const;
   Qt::ItemFlags flags(const QModelIndex &index) const;
   QVariant headerData(int section, Qt::Orientation orientation,
                       int role = Qt::DisplayRole) const;
   QModelIndex index(int row, int column,
                     const QModelIndex &parent = QModelIndex()) const;
   QModelIndex parent(const QModelIndex &index) const;
   int rowCount(const QModelIndex &parent = QModelIndex()) const;
   int columnCount(const QModelIndex &parent = QModelIndex()) const;
 
   QString  primaryFieldName;
   QString  parentFieldName;
   QString  tableName;
 
private:
   //void setupModelData();
   void init(int id = 0,  TreeItem *parent = 0);
   void setupFieldName(const QString &table, const QString  primaryFieldName = "ID", const QString  parentFieldName = "P_ID");
 
 
   TreeItem *rootItem;
};
 
#endif
-------------------
#include <QtGui>
#include <QtSql>
 
#include "treeitem.h"
#include "treemodel.h"
 
#define DEFAULT_PRIMARY_FIELD_NAME    "ID"
#define DEFAULT_PARENT_FIELD_NAME    "P_ID"
 
TreeModel::TreeModel(const QString &table, QObject *parent)
       : QAbstractItemModel(parent)
{
   setupFieldName(table);
  // setupModelData();
}
//
TreeModel::~TreeModel()
{
   delete rootItem;
}
//
int TreeModel::columnCount(const QModelIndex &parent) const
{
   if (parent.isValid())
       return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
   else
       return rootItem->columnCount();
}
//
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
   if (!index.isValid())
       return QVariant();
 
   if (role != Qt::DisplayRole)
       return QVariant();
 
   TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
 
   return item->data(index.column());
}
//
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
   if (!index.isValid())
       return Qt::ItemIsEnabled;
 
   return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
//
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
                              int role) const
{
   if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
       return rootItem->data(section);
 
   return QVariant();
}
//
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
const
{
   TreeItem *parentItem;
 
   if (!parent.isValid())
       parentItem = rootItem;
   else
       parentItem = static_cast<TreeItem*>(parent.internalPointer());
 
   TreeItem *childItem = parentItem->child(row);
   if (childItem)
       return createIndex(row, column, childItem);
   else
       return QModelIndex();
}
//
QModelIndex TreeModel::parent(const QModelIndex &index) const
{
   if (!index.isValid())
       return QModelIndex();
 
   TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
   TreeItem *parentItem = childItem->parent();
 
   if (parentItem == rootItem)
       return QModelIndex();
 
   return createIndex(parentItem->row(), 0, parentItem);
}
//
int TreeModel::rowCount(const QModelIndex &parent) const
{
   TreeItem *parentItem;
 
   if (!parent.isValid())
       parentItem = rootItem;
   else
       parentItem = static_cast<TreeItem*>(parent.internalPointer());
 
   return parentItem->childCount();
}
// Это матырства моего мозга
//----------------------------------------------------------------------
/*void TreeModel::setupModelData()
{
   QList<QVariant> rootData;
   rootData << "Field 1"<< "Field 2"<< "Field 3"<< "Field 4";
   rootItem = new TreeItem(rootData);
   init(0, rootItem);
 
}
//
void init(int id, TreeItem *parent)
{
   QList<TreeItem*> parents;
   parents << parent;
 
   QSqlQuery q;
   q.exec(QString("SELECT * FROM %1 WHERE %2=%3").arg(tableName).arg(parentFieldName).arg(id));
   while ( q.next())
   {
       QList<QVariant> columnData;
       if (q.record().count()>0)
       {
           for (int column=2; column<q.record().count(); column++)
           {
               columnData << q.value(column);
           }
       }
       parents.last()->appendChild(new TreeItem(columnData, parents.last()));
       init(q.value(q.record().indexOf(primaryFieldName)).toInt(), parents);
   }
}*/

//
void TreeModel::setupFieldName(const QString &table, const QString  primaryFieldN, const QString  parentFieldN )
{
   tableName.clear();
   primaryFieldName.clear();
   parentFieldName.clear();
 
   tableName.append(table);
   primaryFieldName.append(primaryFieldN);
   parentFieldName.append(parentFieldN);
 
}
//
-----------------------------------------------------
Ну в общем что-то такое наверно...
« Последнее редактирование: Июль 23, 2009, 15:26 от pastor » Записан
CroCIV
Гость
« Ответ #27 : Июль 23, 2009, 15:04 »

прикольно... щас покурю...
Задумал себе сделать тривью в которую можно было бы, например, БД КЛАДР (разумеется с соответствующей доработкой таблиц в данном случае) забадяжить, чтоб вложенность была потенциально не ограничена, чтоб дерево формировалось "на лету", т.е. по запросу пользователя (юзер ткнул на сущность "Россия", поформировался запрос по регионам россии первого уровня, обработался, результаты на ходу добавились/обновились к ветке "Россия", ветвь раскрылась, ткнул по Кировской области, ... то же самое ... , открылись субъекты Кировской области и т.д.).
Согласитесь такая компонента актуальна и применибельна много где...
Жаль что на работе мало времени этим заниматься, придется фантазии реализовывать в выходные дни.
Кто заинтересован в такой штуке поднимите руки, т.к. тут кроме коддинга есть нюанс. Коли это универсальная компонента необходимо разработать формат команды, разобрав которую наш тривью понел: 1. каки таблицы участвуют в построении дерева, в какой зависимости они находятся 2. какие поля таблиц необходимо использовать как связь с родительским эл.том, а какие поля необходимо отображать .. ну и еще че нибудь.
Записан
oxotnik
Гость
« Ответ #28 : Июль 23, 2009, 15:29 »

составлял TreeWiget таким образом:
из БД делал запрос:

Код
C++ (Qt)
void CDataBase::GetData(map<int, pair<int, QString> > &nodesData)
{
if (!database->isOpen())
return ;
QSqlQueryModel model;
model.setQuery("SELECT * FROM [nodes] ORDER BY node_id");
// ВАЖНО: обязательна сортировка по ID - узла, т.к. после будет один линейный проход
// и для каждого последующего узла выше в таблице должен существовать родитель
for (long i = 0; i < model.rowCount(); i++)
nodesData[model.data(model.index(i, 0)).toInt()] =
make_pair(model.data(model.index(i, 1)).toInt(), model.data(model.index(i, 2)).toString());
}

прорисовка узлов:

Код
C++ (Qt)
void MainWindow::CreateTreeView (void)
{
map<int, pair<int, QString> >nodesData;
base->GetData(nodesData);
treeView = ui->treeWidget;
map <int, pair<int, QString> >::iterator iIter;
map<int, QTreeWidgetItem* >treeItems;
treeView->blockSignals(true);
for (iIter = nodesData.begin(); iIter != nodesData.end(); iIter++)
{
int k = iIter->first;
QTreeWidgetItem *item;
if (iIter->second.first == 0) // root node
{
item = new QTreeWidgetItem(treeView);
item->setText(0, iIter->second.second);
}
else
{
item = new QTreeWidgetItem(treeItems[iIter->second.first]);
item->setText(0, iIter->second.second);
}
item->setData(1, 1, iIter->first);
treeItems[k] = item;
}
treeView->blockSignals(false);
}
скорость очень зависит от драйвера БД
Через ADO в VCL 100 000 узлов рисуются ~2.5 минуты
тот же самый алгоритм в дотнете рисует < 30 сек те же 100 000 узлов
Скорость в QT не проверял, но думаю будет сравнима с VCL

Под QTreeView его можно переписать подобным образом, но с учетом модели, где узлы заменятся на Q*ItemModel для которого есть все возможности указывать родителя и детей.
Записан
miha-ha
Гость
« Ответ #29 : Август 07, 2009, 08:16 »

Нет необходимости загружать все данные сразу!
Их необходимо загружать по мере надобности!
При разворачивании ветки получить из БД всех потомков и показать и т.д. тогда не нужно будут ждать и 30 сек.
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.132 секунд. Запросов: 22.