Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: как запросить у модели инф об элементе при переопределении метода data модели
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Модель/Представление
Steklova Olga
Привет! :wink2:
В моей модели переопределены две роли элементов. При переопределении одной роли элемента модели мне надо использовать информацию о другой роли этого элемента.
А именно, для одной из колонок модели цвет текста элемента модели должен быть красным, если значение соотв. поля в соотв. записи таблицы БД равно 1.
К тому же, отображение значения этого поля тоже должно быть переопределено (если значение соотв. поля в соотв. записи таблицы БД равно 1, то вместо 1 надо отобразить ВАЖНЫЙ, иначе надо отобразить ОБЫЧНЫЙ).

В справке сказано B), что мы можем запросить у модели информацию об элементе,
передав ей модельный индекс, соответствующий элементу,
и задав роль для получения данных желаемого типа:
QVariant value = model->data(index, role);

Но мне нужно сделать это при переопределении метода data модели.

Вот мой код:
MyModel_msg_list::MyModel_msg_list(QObject *parent) :
    QSqlRelationalTableModel(parent)
{
}

QVariant MyModel_msg_list::data(
        const QModelIndex &index,
        int role) const {

    QVariant value = QSqlRelationalTableModel::data(index, role);

    //можно тут так сделать?
    QVariant valueForDisplayRole = QSqlRelationalTableModel::data(index, Qt::DisplayRole); //?
    //или так? (что то же самое)
    //QVariant valueForDisplayRole = QSqlRelationalTableModel::data(index); //?

    switch (role) {

    case Qt::DisplayRole:
        if (index.column() == T_MSG_ColNmb_MSG_PRIOR_CODE)
            return value.toInt() == 1 ? "ВАЖНЫЙ" : "ОБЫЧНЫЙ";
        return value;

    case Qt::ForegroundRole:
        if ((index.column() == T_MSG_ColNmb_MSG_PRIOR_CODE) &&

            //можно тут так сделать?
            (valueForDisplayRole.toInt() == 1)) //"ВАЖНЫЙ"

            return qVariantFromValue(QColor(Qt::red));
        return value;

    } //switch (role)

    return value;
}

А вот что я не понимаю: :unknown:
1. Метод data, который я переопределяю, вызывается для каждой из ролей, которые вообще существуют для модели?
2. Порядок вызова метода data для ролей одного и того же элемента модели - непредсказуем?
3. При переопределении метода data
можно писать:
QVariant value = QSqlRelationalTableModel::data(index, role);
но можно ли писать так:
QVariant valueForDisplayRole = QSqlRelationalTableModel::data(index, Qt::DisplayRole); //?
или так (что то же самое):
QVariant valueForDisplayRole = QSqlRelationalTableModel::data(index); //?
4. Можно ли при переопределении роли Qt::ForegroundRole проверять равенство (valueForDisplayRole.toInt() == 1) ?
Совсем глупый вопрос: на это не влияет то, что при переопределении роли case Qt::DisplayRole я заменила отображение 1 на "ВАЖНЫЙ"?

Спасибо за внимание :D
Litkevich Yuriy
Цитата(Steklova Olga @ 3.4.2012, 21:04) *
Метод data, который я переопределяю, вызывается для каждой из ролей, которые вообще существуют для модели?
существует только один метод data, один из аргументов которого - роль.
этот метод вызывается для роли, которая интересует вызывающего (объекта).
Если этим объектом является представление, то:
1) для отображения данных представление вызывает соответствующий метод делегата, а тот в свою очередь Модель::data (..., Qt::DisplayRole)
2) для отображения данных при редактировании элемента представление вызывает соответствующий метод делегата, а тот в свою очередь Модель::data (..., Qt::EditRole)
3) если указатель мыши зависнет над элементом (делегатом) на некоторое время, то представление вызывает Модель::data (..., Qt::ToolTipRole).

Цитата(Steklova Olga @ 3.4.2012, 21:04) *
2. Порядок вызова метода data для ролей одного и того же элемента модели - непредсказуем?
мой ответ выше должен ответить тебе и на этот вопрос.

Цитата(Steklova Olga @ 3.4.2012, 21:04) *
3. При переопределении метода data
...
но можно ли писать так:
что именно смущает?

Цитата(Steklova Olga @ 3.4.2012, 21:04) *
4. Можно ли при переопределении роли Qt::ForegroundRole проверять равенство (valueForDisplayRole.toInt() == 1) ?
Если valueForDisplayRole действительно всегда будет ЦЕЛОЕ, тогда можно.

Цитата(Steklova Olga @ 3.4.2012, 21:04) *
Совсем глупый вопрос: на это не влияет то, что при переопределении роли case Qt::DisplayRole я заменила отображение 1 на "ВАЖНЫЙ"?
нет, не влияет. Т.к. "1" возвращает метод data базового класса ( value = QSqlRelationalTableModel::data(index, role); ) и
проверку условия ты делаешь с данными, которые возвращает тот же метод ( valueForDisplayRole = QSqlRelationalTableModel::data(index, Qt::DisplayRole) ), а не метод твоего класса - MyModel_msg_list::data (который возвращает уже строку).

П.С.
так:
Цитата(Steklova Olga @ 3.4.2012, 21:04) *
return value.toInt() == 1 ? "ВАЖНЫЙ" : "ОБЫЧНЫЙ"; // Где value - QVariant
лучше не делать, т.к. это строка из char-ов. Лучше сразу привести к QString, например:
return value.toInt() == 1 ? QString("ВАЖНЫЙ") : QString("ОБЫЧНЫЙ");


П.П.С.
Запись на русском явно вызовет проблему в будущем, приводи все русскоязычные литералы к QString с корректным преобразованием кодировки.
Впринципе дурацкий, но быстрый способ: файл с исходником в кодировке UTF-8, тогда код выглядит так:
return value.toInt() == 1 ? tr::Utf8("ВАЖНЫЙ") : tr::Utf8("ОБЫЧНЫЙ");
Лучше использовать QTextCodec

Если кодировка исходника в UTF8 и не нужно, чтобы литералы попадали в перевод, можно использовать другую готовую функцию:
QString::fromUtf8(...)
Steklova Olga
Большое спасибо, Litkevich Yuriy :)

Ответы на вопросы 1 и 2 поняла.

По вопросам 3 и 4 меня смущало следующее.
Правильно ли я понимаю, что в методе data наследуемой модели, независимо от того, для какой роли он сейчас был вызван, можно запросить у базовой модели данные не только для этой роли, а вообще для любой роли?
Можно рассчитывать на то, что в базовой модели всегда определены данные для любой роли?

Насчет операторов:
QVariant value = QSqlRelationalTableModel::data(index, role);
QVariant valueForDisplayRole = QSqlRelationalTableModel::data(index, Qt::DisplayRole);
первый из них списала из примера создания наследуемой модели,
второй, скажу честно, списала из него, даже не поняв, что обращаюсь к базовой модели, а не к наследуемой.
Пока Вы не разжевали, у меня была просто каша в понимании того, что я написала.
Надо будет мне разобраться с наследованием...

Насчет кодировок.
Я пишу проект не одна.
Строки на экране должны отображаться только по-русски, перевода пока не предполагается.
Кодировка исходников - Windows-1251.
Кодировка моей БД Firebird 2.1 - WIN1251.
Сейчас запускаем наш проект в Windows. Потом, возможно, будем запускать его в Linux.
Мы используем QTextCodec так:
#define RUSCODEC "CP1251" 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName(RUSCODEC));
    ...
}

Лучше делать кодировку исходников и БД одинаковыми, чтобы не было доп. проблем?

Цитата
так:
return value.toInt() == 1 ? "ВАЖНЫЙ" : "ОБЫЧНЫЙ"; // Где value - QVariant
лучше не делать, т.к. это строка из char-ов. Лучше сразу привести к QString, например:
return value.toInt() == 1 ? QString("ВАЖНЫЙ") : QString("ОБЫЧНЫЙ");

А если оставить так как у меня, чем это плохо?
Или, в соответствии с кодировкой моего проекта, лучше делать так:
return value.toInt() == 0 ? QString::fromAscii("ОПЕРАТОР") : QString::fromAscii("КОМАНДИР БРК");

Litkevich Yuriy
Цитата(Steklova Olga @ 3.4.2012, 23:33) *
Правильно ли я понимаю, что в методе data наследуемой модели, независимо от того, для какой роли он сейчас был вызван, можно запросить у базовой модели данные не только для этой роли, а вообще для любой роли?
ну да. Ты же можешь передать в метод базового класса любое значение аргумента.


Цитата(Steklova Olga @ 3.4.2012, 23:33) *
Можно рассчитывать на то, что в базовой модели всегда определены данные для любой роли?
нет, к сожалению троли поленились. Если заглянешь в исходники то увидишь, что кроме Qt::DisplayRole и Qt::EditRole ничего не обрабатывается.

Цитата(Steklova Olga @ 3.4.2012, 23:33) *
Или, в соответствии с кодировкой моего проекта, лучше делать так:
вместо fromAscii нужно fromLocal8bit.
а так как ты устнавливаешь кодек для Си-строк равный локали, то можно просто QString("ВАЖНЫЙ"), т.к. Си-строки преобразуются именно с помощью кодека для Си-строк.
Steklova Olga
Юрий, извините, но я не поняла следующее.
Я задала первый вопрос:
Цитата(Steklova Olga @ 3.4.2012 @ 23:33)
Правильно ли я понимаю, что в методе data наследуемой модели, независимо от того, для какой роли он сейчас был вызван, можно запросить у базовой модели данные не только для этой роли, а вообще для любой роли?
Вы ответили:
Цитата(Litkevich Yuriy @ 4.4.2012 @ 11:22)
ну да. Ты же можешь передать в метод базового класса любое значение аргумента.

Затем я задала второй вопрос:
Цитата(Steklova Olga @ 3.4.2012 @ 23:33)
Можно рассчитывать на то, что в базовой модели всегда определены данные для любой роли?
Вы ответили:
Цитата(Litkevich Yuriy @ 4.4.2012 @ 11:22)
нет, к сожалению троли поленились. Если заглянешь в исходники то увидишь, что кроме Qt::DisplayRole и Qt::EditRole ничего не обрабатывается.

Где не обрабатывается? Когда? В какую папку, в какой файл, в какой метод заглянуть, чтобы это увидеть? Чем отличается обработка ролей Qt::DisplayRole и Qt::EditRole от других?
А то ведь я в этих вопросах спрашивала одно и то же, но разными словами, а получила два противоположных ответа: "да" и "нет". Почему на второй вопрос ответ "нет"?
В методе data наследуемой модели, если он сейчас был вызван для какой-то роли ROLE кроме Qt::DisplayRole и Qt::EditRole, нельзя запросить у базовой модели данные для ролей кроме ROLE? Так что-ли? Хотя, вряд ли... Видимо, Вы, отвечая на второй вопрос, имели в виду совсем другое.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.