Russian Qt Forum

Qt => Model-View (MV) => Тема начата: PavelVX от Ноябрь 24, 2010, 12:29



Название: делегаты, непонятное поведение
Отправлено: PavelVX от Ноябрь 24, 2010, 12:29
Я только начал осваивать Qt. Взял пример и начал его щупать, перекраивать и наткнулся на странности.
Пример из инета, коннектимся к PostgreSQL:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QTextCodec *codec = QTextCodec::codecForName("CP1251");
    QTextCodec::setCodecForTr(codec);
    QTextCodec::setCodecForCStrings(codec);

    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setDatabaseName("test.dsn");
    db.setUserName("user");
    db.setPassword("");
    if (!db.open()) {
        QMessageBox msgBox;
        msgBox.setText(db.lastError().text());
        QStringList drivers = QSqlDatabase::drivers();
        msgBox.exec();
    }
    QSqlRelationalTableModel * albumsRelation = new QSqlRelationalTableModel(0);
    albumsRelation->setTable("public.albums");
//        albumsRelation->setRelation(1, QSqlRelation("public.polu1", "\"KODPL\"", "\"NAIM\""));
    albumsRelation->setRelation(1, QSqlRelation("public.\"vw_polu1\"", "KODPL", "NAIM"));
    albumsRelation->select();
    albumsRelation->setEditStrategy(QSqlTableModel::OnRowChange);

    QTableView * view = new QTableView(0);
    view->setModel(albumsRelation);
    view->setColumnHidden(0, true);
    view->setWindowTitle("Ti test");
    QSqlRelationalDelegate * delegate = new QSqlRelationalDelegate(view);
    view->setItemDelegate(delegate);
    view->show();

}
1.     albumsRelation->setRelation(1, QSqlRelation("public.\"vw_polu1\"", "KODPL", "NAIM")); - в дальнейшем, у этого делегата можно выбрать только из списка значение, перетягивая скроллинг, нельзя сделать выбор начав печатать.
2.  А теперь самое интресное/непонятное: у меня в таблицах очень много полей в разном регистре. Постгре их различает. То  есть NAIM != naim. Но если создавать отношение так:   albumsRelation->setRelation(1, QSqlRelation("public.polu1", "\"KODPL\"", "\"NAIM\""));, то оно вообще не создастся. Поэтому пошел на изврат и создал view. Дак вот: если у вью сделать все поля в разном регистре, то отношение не работает, если KODPL сделать в нижнем регистре, а NAIM  в верхнем, то не сохраняет значение. Если все сделать в нижнем регистре. то все сохраняет. Это глюк или фича? И как это обойти?


Название: Re: делегаты, непонятное поведение
Отправлено: crossly от Ноябрь 24, 2010, 13:27
скорее фитча.... написать свой делегат который будет соответствовать вашим требования... QODBC здесь не лучший вариант... для Postgre есть драйвер


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Ноябрь 24, 2010, 13:35
Если я правильно понял, то под винду дрова для постгри надо компилить самому. Это пока проблема. В дальнейшем может и займусь этим. Пока надо с самим Qt разобраться, понять, подходит он для наших задач или нет.


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Ноябрь 26, 2010, 11:56
А как эту фичу обойти-то??? Получается, что придется постоянно писать вьюхи что ли? И не получится напряму цеплять таблицы, если названия полей таблицы в верхнем регистре?


Название: Re: делегаты, непонятное поведение
Отправлено: crossly от Ноябрь 26, 2010, 12:20
Цитировать
написать свой делегат который будет соответствовать вашим требованиям...


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Декабрь 06, 2010, 11:06
доброго времени суток!
Почти разобрался с делегатом на основе QComboBox. Но помогите, пожалуйста, в следующем моменте:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QSqlRelationalTableModel * albumsRelation = new QSqlRelationalTableModel(0);
    albumsRelation->setTable("public.albums");
    albumsRelation->setRelation(1, QSqlRelation("public.polu1", "\"KODPL\"", "\"NAIM\""));
    albumsRelation->select();
    albumsRelation->setEditStrategy(QSqlTableModel::OnRowChange);

    ui->TableView->setModel(albumsRelation);

    ComboBoxDelegate * comboDelegate = new ComboBoxDelegate(this);

    ui->TableView->setItemDelegateForColumn( 1, comboDelegate );

}

void ComboBoxDelegate::setEditorData(QWidget *editor,
                                     const QModelIndex &index) const
 {
     QComboBox *comboBox = static_cast<QComboBox*>(editor);
     int value = index.model()->data(index, Qt::EditRole).toInt(); //тут первая проблема
     comboBox->setCurrentIndex(value);  //тут вторая проблема
 };
Тут я запутался капитально :(.
1. Как мне правильно получить значение ключа(kodpl) в value? Оно берется текстовым из релатион походу(naim)?
2. Как мне правильно спозиционировать значение при открытии делегата?


Название: Re: делегаты, непонятное поведение
Отправлено: shirushizo от Декабрь 06, 2010, 18:18
Тут я запутался капитально :(.
1. Как мне правильно получить значение ключа(kodpl) в value? Оно берется текстовым из релатион походу(naim)?
2. Как мне правильно спозиционировать значение при открытии делегата?

Решение обоих проблем:
Код:
QComboBox *comboBox = static_cast<QComboBox*>(editor); //для наследников QObject советуют использовать qobject_cast
QString value = index.model()->data(index, Qt::EditRole).toString();
comboBox->setCurrentIndex(combo->findText(value));


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Декабрь 07, 2010, 12:07
Если я правильно понял, то:

QComboBox *comboBox = static_cast<QComboBox*>(editor); //для наследников QObject советуют использовать qobject_cast
QString value = index.model()->data(index, Qt::EditRole).toString(); //получил текстовое значение ячейки
comboBox->setCurrentIndex(combo->findText(value)); //установил текущую позицию как надо

//тогда получается, что для установки нового значения в model нужно сделать так:
void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                    const QModelIndex &index) const
 {
     QComboBox *comboBox = qobject_cast<QComboBox*>(editor);

     model->setData(index, comboBox->currentText(), Qt::EditRole);

 };
//как-то странно это. возвращать текст, а не значение. Или после МС Аксеса просто непривычно


Название: Re: делегаты, непонятное поведение
Отправлено: shirushizo от Декабрь 07, 2010, 18:27
Можешь посмотреть как реализовано в QSqlRelationalDelegate. Установка значения там реализована через методы
Код:
QSqlTableModel  QSqlRelationalTableModel::relationModel(int column)
QSqlRelation QSqlRelationalTableModel::relation(int column)

Находятся %QtDir%/qt/src/sql/models/qsqlrelationaldelegate.h

Еще кто-то на форуме свой делаегат предлагал, там в зависимости от типа поля - разные редакторы.


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Декабрь 08, 2010, 11:11
Не получается каменный цветок! Ну не лезет никак :(.
Придется пост наверное продублировать и в MCV.
%QtDir%/qt/src/sql/models/qsqlrelationaldelegate.h - его я разбирал, и вставлять пытался. Но не получаю нужного значения.
Если у меня в модели комбобокса 2 колонки, видимаю вторая колонка, как мне получить соответствующее значение из первой колонки?
Может кто-нить пример привести?

ComboBoxDelegate::ComboBoxDelegate(QObject *parent)
{
    DelegateModel = new QSqlQueryModel;
    DelegateModel->setQuery("select \"KODPL\", \"NAIM\" from public.polu1 order by \"NAIM\"");
};

QWidget *ComboBoxDelegate::createEditor(QWidget *parent,
     const QStyleOptionViewItem & option ,
     const QModelIndex & index ) const
 {
     QComboBox *editor = new QComboBox(parent);
     editor->setModel(DelegateModel);
     editor->setModelColumn(1); //показывать текст
     return editor;
 };

void ComboBoxDelegate::setEditorData(QWidget *editor,
                                     const QModelIndex &index) const
 {
     QComboBox *comboBox = qobject_cast<QComboBox*>(editor); //для наследников QObject советуют использовать qobject_cast
     QString value = index.model()->data(index, Qt::EditRole).toString();
     comboBox->setCurrentIndex(comboBox->findText(value));
 };

void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                    const QModelIndex &index) const
 {
     QComboBox *comboBox = qobject_cast<QComboBox*>(editor);

//     model->setData(index, comboBox->currentText(), Qt::EditRole);
     model->setData(index, comboBox->currentIndex(), Qt::EditRole);
/*тут и начинаются проблемы!
   Не могу прописать значения никак. В model нужно положить значение из первой колонки комбобокса. Иначе облом. что правильно. Но как его получить-то???
*/

 };

void ComboBoxDelegate::updateEditorGeometry(QWidget *editor,
     const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
 {
     editor->setGeometry(option.rect);
 };


Название: Re: делегаты, непонятное поведение
Отправлено: asvil от Декабрь 08, 2010, 12:23
Код:
ComboBox->model()->index(ComboBox->currentIndex(), *НОМЕР_ПЕРВОЙ_КОЛОНКИ*).data();
Я так понял вы не знаете как достучаться до модели которая установлена в комбинированной коробке?


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Декабрь 08, 2010, 13:26
Филоненко Михаил, shirushizo, огромное, огромное спасибо!!! :)
Вроде все заработало как надо.
Теперь буду делать GUI + механику там. попутно разбираясь в QT.
Но вообще это как-то странно, после МС Аксеса данный метод кажется варварским :).


Название: Re: делегаты, непонятное поведение
Отправлено: asvil от Декабрь 08, 2010, 15:28
Я переводил, если это можно так назвать, приложение с аксеса в postgresql, qt и в целом впечатления положительные стали только после того, как написал некоторую аксесо-подобную прослойку (модели, представления, qt script вместо vba).


Название: Re: делегаты, непонятное поведение
Отправлено: PavelVX от Декабрь 09, 2010, 06:37
Михаил, у меня именно такая же цель. Связку MS SQL Server + MS Access перевожу на PostgreSQL + Qt. Сервер уже перевел, заодно сбросив туда почти все пересчеты. Теперь надо переводить GUI. Правда я еще не тестил Qt GUI под линухом. Хочется сделать проект, который будет компилиться и использоваться и под вин и лиль платформой, с последующим полным переходом на линь.