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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: делегаты, непонятное поведение  (Прочитано 6692 раз)
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  в верхнем, то не сохраняет значение. Если все сделать в нижнем регистре. то все сохраняет. Это глюк или фича? И как это обойти?
Записан
crossly
Гость
« Ответ #1 : Ноябрь 24, 2010, 13:27 »

скорее фитча.... написать свой делегат который будет соответствовать вашим требования... QODBC здесь не лучший вариант... для Postgre есть драйвер
Записан
PavelVX
Гость
« Ответ #2 : Ноябрь 24, 2010, 13:35 »

Если я правильно понял, то под винду дрова для постгри надо компилить самому. Это пока проблема. В дальнейшем может и займусь этим. Пока надо с самим Qt разобраться, понять, подходит он для наших задач или нет.
Записан
PavelVX
Гость
« Ответ #3 : Ноябрь 26, 2010, 11:56 »

А как эту фичу обойти-то??? Получается, что придется постоянно писать вьюхи что ли? И не получится напряму цеплять таблицы, если названия полей таблицы в верхнем регистре?
Записан
crossly
Гость
« Ответ #4 : Ноябрь 26, 2010, 12:20 »

Цитировать
написать свой делегат который будет соответствовать вашим требованиям...
Записан
PavelVX
Гость
« Ответ #5 : Декабрь 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. Как мне правильно спозиционировать значение при открытии делегата?
Записан
shirushizo
Гость
« Ответ #6 : Декабрь 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));
Записан
PavelVX
Гость
« Ответ #7 : Декабрь 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);

 };
//как-то странно это. возвращать текст, а не значение. Или после МС Аксеса просто непривычно
« Последнее редактирование: Декабрь 07, 2010, 12:15 от PavelVX » Записан
shirushizo
Гость
« Ответ #8 : Декабрь 07, 2010, 18:27 »

Можешь посмотреть как реализовано в QSqlRelationalDelegate. Установка значения там реализована через методы
Код:
QSqlTableModel  QSqlRelationalTableModel::relationModel(int column)
QSqlRelation QSqlRelationalTableModel::relation(int column)

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

Еще кто-то на форуме свой делаегат предлагал, там в зависимости от типа поля - разные редакторы.
Записан
PavelVX
Гость
« Ответ #9 : Декабрь 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);
 };
Записан
asvil
Гость
« Ответ #10 : Декабрь 08, 2010, 12:23 »

Код:
ComboBox->model()->index(ComboBox->currentIndex(), *НОМЕР_ПЕРВОЙ_КОЛОНКИ*).data();
Я так понял вы не знаете как достучаться до модели которая установлена в комбинированной коробке?
Записан
PavelVX
Гость
« Ответ #11 : Декабрь 08, 2010, 13:26 »

Филоненко Михаил, shirushizo, огромное, огромное спасибо!!! Улыбающийся
Вроде все заработало как надо.
Теперь буду делать GUI + механику там. попутно разбираясь в QT.
Но вообще это как-то странно, после МС Аксеса данный метод кажется варварским Улыбающийся.
Записан
asvil
Гость
« Ответ #12 : Декабрь 08, 2010, 15:28 »

Я переводил, если это можно так назвать, приложение с аксеса в postgresql, qt и в целом впечатления положительные стали только после того, как написал некоторую аксесо-подобную прослойку (модели, представления, qt script вместо vba).
Записан
PavelVX
Гость
« Ответ #13 : Декабрь 09, 2010, 06:37 »

Михаил, у меня именно такая же цель. Связку MS SQL Server + MS Access перевожу на PostgreSQL + Qt. Сервер уже перевел, заодно сбросив туда почти все пересчеты. Теперь надо переводить GUI. Правда я еще не тестил Qt GUI под линухом. Хочется сделать проект, который будет компилиться и использоваться и под вин и лиль платформой, с последующим полным переходом на линь.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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