Russian Qt Forum

Qt => Базы данных => Тема начата: linuxoid от Август 09, 2007, 12:45



Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 09, 2007, 12:45
как с помощью QSqlTableModel и QTableView открыть для редатактирования табличцу в которой данные совмещены из 3-х разных табличек одной и той же базы данных:?: Использую Qt 4.2.3,linux,MySQL

для просмотра использую QSqlQueryModel со следующей командой:
select cities.city_name,  articles.article_name, sales.kol_vo, sales.dat_real FROM `sales`, `cities`, `articles` WHERE  sales.sit_key = cities.id_key_city AND sales.art_key = id_key_art ORDER BY  sales.dat_real DESC , cities.city_name
тока нужно ещё чтобы я мог редактировать ячейки!помогите пожалуйста!


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 09, 2007, 13:52
http://www.mechta34.com/it/qt4/

И да пребудет с вами сила.  8)  :wink:


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 09, 2007, 14:04
да там я уже всё перечитал!как мне сделать чтобы открылась таблица в которой совмещены данные из трёх таблиц одной БД и была возможность изменять ячейки в открывшейся таблице??? :?:

и вообще возможно работать с несколькими таблицами в QSqlTableModel???


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 09, 2007, 14:11
Код:
The QSqlRelationalTableModel class provides an editable data model for a single database table, with foreign key support.


И подключаем сколько нужно таблиц.
Только вот быстродействие от такого решения не самое оптимальное ИМХО. :(  :(

Код:
/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** Licensees holding a valid Qt License Agreement may use this file in
** accordance with the rights, responsibilities and obligations
** contained therein.  Please consult your licensing agreement or
** contact sales@trolltech.com if any conditions of this licensing
** agreement are not clear to you.
**
** Further information about Qt licensing is available at:
** http://www.trolltech.com/products/qt/licensing.html or by
** contacting info@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include <QtGui>
#include <QtSql>

#include "../connection.h"

void initializeModel(QSqlRelationalTableModel *model)
{
    model->setTable("employee");

    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->setRelation(2, QSqlRelation("city", "id", "name"));
    model->setRelation(3, QSqlRelation("country", "id", "name"));

    model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
    model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
    model->setHeaderData(2, Qt::Horizontal, QObject::tr("City"));
    model->setHeaderData(3, Qt::Horizontal, QObject::tr("Country"));

    model->select();
}

QTableView *createView(const QString &title, QSqlTableModel *model)
{
    QTableView *view = new QTableView;
    view->setModel(model);
    view->setItemDelegate(new QSqlRelationalDelegate(view));
    view->setWindowTitle(title);
    return view;
}

void createRelationalTables()
{
    QSqlQuery query;
    query.exec("create table employee(id int primary key, name varchar(20), city int, country int)");
    query.exec("insert into employee values(1, 'Espen', 5000, 47)");
    query.exec("insert into employee values(2, 'Harald', 80000, 49)");
    query.exec("insert into employee values(3, 'Sam', 100, 1)");

    query.exec("create table city(id int, name varchar(20))");
    query.exec("insert into city values(100, 'San Jose')");
    query.exec("insert into city values(5000, 'Oslo')");
    query.exec("insert into city values(80000, 'Munich')");

    query.exec("create table country(id int, name varchar(20))");
    query.exec("insert into country values(1, 'USA')");
    query.exec("insert into country values(47, 'Norway')");
    query.exec("insert into country values(49, 'Germany')");
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    if (!createConnection())
        return 1;
    createRelationalTables();

    QSqlRelationalTableModel model;

    initializeModel(&model);

    QTableView *view = createView(QObject::tr("Relational Table Model"), &model);
    view->show();

    return app.exec();
}


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 09, 2007, 14:56
слушай,relation это добавлять в ячейки выпадающий список с данными из других таблиц.
а мне надо чтобы отображал столбики из разных таблиц и я их мог редактировать!
  :!:  :!:


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 09, 2007, 15:21
Соррии... Я еще к этой проблеме не дошел она пока впереди. Но сдается мне что
отображение отображением а редактирование нужно делать в отдельном диалоге.
И связывание релейшеном таблиц как в фокспро тут наверно нет.
Помочь может наверное только редактируемое представление на уровне сервера.

добавлено спустя 39 секунд:

 или написание своей модели ....


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 09, 2007, 15:23
каким способом воспользоваться и если можно представьте код для редактирования следующих данных:
(следующий код я использовал для отображеня информации, а надо чтобы я мог редактировать отображённую таблицу)
QSqlQueryModel *model = new QSqlQueryModel();
   model->setQuery("select cities.city_name,  articles.article_name, sales.kol_vo, sales.dat_real FROM `sales`, `cities`, `articles` WHERE  sales.sit_key = cities.id_key_city AND sales.art_key = id_key_art ORDER BY  sales.dat_real DESC , cities.city_name");
   
    model->setHeaderData(4, Qt::Horizontal, QString::fromLocal8Bit("время\nобновл."));
    model->setHeaderData(3, Qt::Horizontal, QString::fromLocal8Bit("дата\nреализации"));
     tableView->setModel(model);
     tableView->resizeRowsToContents();
    tableView->resizeColumnsToContents();
    tableView->show();


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 09, 2007, 15:37
Первое я думаю переопределить setData в модели

вот кусок кода, только для QTreeViewModel c таблицами пока не работал еще.

добавлено спустя 38 секунд:

 bool MyTreeModel::setData(const QModelIndex &index,
                     const QVariant &value, int role)
{
   QSqlDatabase db=QSqlDatabase::database();
   db.transaction();
   QSqlQuery q,q1;
   QStandardItem *i=this->itemFromIndex(index);
   i->setText(value.toString());
   q1.exec("select * from divisions where id="+i->data().toString());
   if(q1.size()!=-1){
      
      q.prepare("update divisions set name=? where id=?");
      q.addBindValue(value);
      q.addBindValue(i->data());
      
   }else{
      q.prepare("insert into divisions (id_p,name) values(?,?)");
      q.addBindValue(i->parent()->data());
      q.addBindValue(value);
   }
   if(!q.exec())
   {
      QMessageBox::critical(0,"",q.lastError().text());
      db.rollback();
      return false;
   }
   if(q1.size()==-1){
      q.prepare("select id from divisions where id_p=? and name=?");
      q.addBindValue(i->parent()->data());
      q.addBindValue(value);
      if(!q.exec())
      {
         QMessageBox::critical(0,"",q.lastError().text());
         db.rollback();
         return false;
      }else{
         q.next();
         i->setData(q.value(0));
      }
   }
   db.commit();
   return true;    
}


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 09, 2007, 15:58
а можешь с комментариями написать? а то я чё то не улавливаю хода мысли.


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: WW от Август 09, 2007, 16:26
Основная мысль - наследуешься от QSqlQueryModel и переопределяешь setData. в QSqlQueryModel там просто стоит return false


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: Sergey B. от Август 09, 2007, 16:55
Цитата: "WW"
Основная мысль - наследуешься от QSqlQueryModel и переопределяешь setData. в QSqlQueryModel там просто стоит return false


Т.е.  под каждую таблицу, писать свою модель, я правильно понял?
(с переопределённым методом setData())
:(

Я в своих программах ловлю currentModelIndex(), и с помощью него беру значение в модели, потом передаю это значение диалогу для редактирования и в том диалоге на кнопку "Save", вешаю
"UPDATE моя_таблица SET данные=значение WHERE параметр=значение"


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 08:42
скинуте пожалуйста код с использованием currentIndex и перенаправлением в диалог с возможностью редактирования!!0


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: WW от Август 10, 2007, 09:28
Цитата: "Sergey B."
Т.е.  под каждую таблицу, писать свою модель, я правильно понял?
(с переопределённым методом setData())
:(

Я в своих программах ловлю currentModelIndex(), и с помощью него беру значение в модели, потом передаю это значение диалогу для редактирования и в том диалоге на кнопку "Save", вешаю
"UPDATE моя_таблица SET данные=значение WHERE параметр=значение"

Под таблицу юзается QSqlTableModel, где все это уже есть. А человеку нужно обновлять сджойненные таблицы. даже если перехватывать currentIndex, то не факт, что в БД сможешь обновить. Через одбц, например, не получиться, т.к. он умеет обновлять только одну таблицу одновременно. (тут могут быть др. мнения.) а написав свой setData, будешь иметь полный контроль всего и вся. А если что-то универсальное для всех случ. жизни - Дельфи с Билдером в руки. там уже все написано.


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 09:44
а можно ли использовать Qt::ItemIsEditable в QSqlQueryModel?если можно то как?


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: WW от Август 10, 2007, 10:18
Цитата: "linuxoid"
а можно ли использовать Qt::ItemIsEditable в QSqlQueryModel?если можно то как?

Еще раз глаголю: отнаследуйся от QSqlQueryModel и можно будет использовать все.


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 10:21
можешь написать примерный код?


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 10, 2007, 11:05
Смотрел сегодня 4.3.1
Там есть пример "Master Detail" в группе SQL там описывается работа с QSqlRelationalTableModel и добавление и удалением данных,
я думаю что прикрутить туда изменение можно тоже.


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 12:53
написал свою модель с помощью setData но почему то не применяются изменения!Помогите!что здесь не так?вот часть кода:



bool MyModel::setData(const QModelIndex &index,const QVariant &value,int /* role */) {
   if (index.column() < 0 || index.column() > 3)
      return false;
   QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
   int id = QSqlQueryModel::data(primaryKeyIndex).toInt();
   bool ok;
   QSqlQuery query;
if (index.column() == 0) {
   query.prepare("update cities set city_name = ? where id = ?");
   query.addBindValue(value.toString());
   query.addBindValue(id);
}else if(index.column() == 1) {
   query.prepare("update articles set article_name = ? where id = ?");
   query.addBindValue(value.toString());
   query.addBindValue(id);
}else if(index.column() == 2) {
   query.prepare("update sales set kol_vo = ? where id = ?");
   query.addBindValue(value.toInt());
   query.addBindValue(id);
}else if(index.column() == 3) {
   query.prepare("update sales set dat_real = ? where id = ?");
   query.addBindValue(value.toDate());
   query.addBindValue(id);
}
   ok = query.exec();
   refresh();
   return ok;
}


void MyModel::refresh() {
   setQuery("select cities.city_name,  articles.article_name, sales.kol_vo, sales.dat_real FROM `sales`, `cities`, `articles` WHERE  sales.sit_key = cities.id_key_city AND sales.art_key = id_key_art ORDER BY  sales.dat_real DESC , cities.city_name");
}


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 10, 2007, 13:14
А использование Qt::EditRole есть ? в data() ---  :roll:
и я бы добавил - db.transaction(); - db.rollback();  - db.commit();

Код:
	if(!q.exec())
{
QMessageBox::critical(0,"",q.lastError().text());
db.rollback();
return false;
}


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 13:37
всё уже почти получилось,вот тока напиши пожалуйста какой-нибудь код(для моего примера или нет не важно) как использовать  Qt::EditRole db.transaction(); - db.rollback(); - db.commit();

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

 вот моя data опиши или покажи код с Qt::EditRole пожалуйста

QVariant MyModel::data(
                  const QModelIndex &index,
                  int role) const {
                     
         QVariant value = QSqlQueryModel::data(index, role);   
         switch (role) {   
            
      case Qt::DisplayRole:      
      case Qt::EditRole:         
                  
                  if (index.column() == 3 && role == Qt::EditRole)   
                     return value.toDate().toString("dd.MM.yyyy");
                              
                        }
   return value;
}


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 10, 2007, 13:54
Код:
QVariant MyModel::data(const QModelIndex &index, int role) const 
{
QVariant value = QSqlQueryModel::data(index, role);
switch (role)
  {
    case Qt::DisplayRole:
    case Qt::EditRole:

    if (index.column() == 3 && role == Qt::DisplayRole)
              return value.toDate().toString("dd.MM.yyyy");
  }
return value;
}


Так должно работать....


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 14:08
всё равно не применяет изменения!

а в setData:
query.prepare("update cities set city_name = ? where id = ?");

id чё указывает может надо id призязанный к определённой таблице указать?

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

 точно!я добавил
 if(!q.exec())
   {
      QMessageBox::critical(0,"",q.lastError().text());
      db.rollback();
      return false;
   }
и ошибка вылетела Unknown column 'id' in 'where clause' QMYSQL3: Unable to prepare statement
как мне описать id?


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 10, 2007, 14:36
может так :
query.prepare("update cities c set c.city_name = ? where c.id = ?");


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 14:42
пишет:
Unknown column 'с.id' in 'where clause' QMYSQL3: Unable to prepare statement

у меня кстати в таблице cities не id а id_key_city может надо поставить его?


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 10, 2007, 15:10
:mrgreen:  АГА  :mrgreen:  :mrgreen:  :mrgreen:  :mrgreen:


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 10, 2007, 15:50
bool MyModel::setData(const QModelIndex &index,const QVariant &value,int /* role */) {
if (index.column() < 0 || index.column() > 3)
return false;
QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
int id = QSqlQueryModel::data(primaryKeyIndex).toInt();
bool ok;
QSqlQuery query;
if (index.column() == 0) {
query.prepare("update cities set city_name = ? where id = ?");
query.addBindValue(value.toString());
query.addBindValue(id);


пожалуйста напиши построчный коммент!


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 10, 2007, 21:13
Цитата: "linuxoid"
bool MyModel::setData(const QModelIndex &index,const QVariant &value,int /* role */) {
if (index.column() < 0 || index.column() > 3)
return false;
///// Типа не попали в вилку и отвали
QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
int id = QSqlQueryModel::data(primaryKeyIndex).toInt();
bool ok;
/// типа получил ID кортежа (в чем я очень сомневаюсь id ??? QSqlQueryModel откуда берется)

QSqlQuery query;
/// Если индекс колонки  0 то выплняем запрос к таблице cities
if (index.column() == 0 ) {
query.prepare("update cities set city_name = ? where id = ?");
query.addBindValue(value.toString());
query.addBindValue(id);


пожалуйста напиши построчный коммент!


Ну что пришло на ум "в пятницу вечером после 2л. пива"


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 11, 2007, 20:31
Ну что получилось ?  (Суббота после шашлыка и ящика пива).


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 13, 2007, 08:56
не получается!нужно чтобы менялось значение выбранной ячейки,а

в таблице cities city_name имеет уникальный номер id_key_city
if (index.column() == 0 ) {
query.prepare("update cities set city_name = 'Абакан' where id_key_city = 1");
так вот такая запись меняет все ячейки с именем Абакан в редактируемой таблице на значение, которое я вписываю в ячейку,а мне надо чтобы оно меняло только в одной выбранной ячейке.
Есть какие мысли по этому поводу?


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: -=QT=- от Август 13, 2007, 09:41
model->setQuery("select cities.city_name, articles.article_name, sales.kol_vo, sales.dat_real FROM `sales`, `cities`, `articles` WHERE sales.sit_key = cities.id_key_city AND sales.art_key = id_key_art ORDER BY sales.dat_real DESC , cities.city_name");

Значит : sales.sit_key = cities.id_key_city Для то го чтобы изменить данные в таблице нужно знать этот id_key_city или sales.sit_key и использовать его в :
Код:
query.prepare("update cities set city_name = 'Абакан' where id_key_city = 1");


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 13, 2007, 10:06
как мне взять данные:на каком столбике и строке стоит курсор(т.е. ячейка с №строки и №столбца над которой производится редактирование в данный момент в таблице редактирования)???


Название: Срочно Помогите с QSqlTableModel!Пожалуйста
Отправлено: linuxoid от Август 14, 2007, 11:01
как сделать на двойное нажатие ячейки в tableView открытие нового диалого в котором будет выпадающий список QComboBox в котором надо сделать названия городов из таблицы cities и при выборе города из списка будет выполняться sql запрос???!!!Очень надо!помогите плз!!
 :!:  :?:  :!:  :cry:
да кстати двойное нажатие при использовании QSqlQueryModel