- 1. tablemodel.h
- 2. tablemodel.cpp
- 3. Підсумок
В уроці роботи з QSqlTableModel було детально розглянуто відображення таблиці даних з бази даних SQL . Але у зв'язку з питанням від одного з читачів, роблю невелике доповнення до цього прикладу.
Питання полягало в тому, як зафарбувати весь рядок в залежності від значення в одній з колонок. числа. У зв'язку з цим як піддослідні рядки були обрані рядки, де псевдовипадкове число дорівнює 41.
Для цього необхідно успадковуватися від класу QSqlTableModel і перевизначити метод QSqlTableModel::data(). Після чого використовувати як модель даних новий клас спадкоємець.
tablemodel.h
#ifndef TABLEMODEL_H #define TABLEMODEL_H #include <QObject> #include <QSqlTableModel> class TableModel : public QSqlTableModel { Q_OBJECT public: explicit TableModel(QObject *parent = 0); QVariant data(const QModelIndex &idx, int role) const; signals: public slots: }; #endif // TABLEMODEL_H
tablemodel.cpp
Зазначу, що в початковому прикладі стовпець 0 не відображається в таблиці, тому вибираємо отримання даних з 3 колонки, а не з колонки 2. Отримання даних проводиться викликом методу базового класу.
#include "tablemodel.h" #include <QColor> TableModel::TableModel(QObject *parent) : QSqlTableModel(parent) { } QVariant TableModel::data(const QModelIndex &idx, int role) const { if(role == Qt::BackgroundColorRole){ if(QSqlTableModel::data(this->index(idx.row(), 3)).toInt() == 41){ return QColor(Qt::red); } } else if(role == Qt::DisplayRole){ return QSqlTableModel::data(idx); } return QVariant(); }
Підсумок
В результаті вийшов додаток, в якому відображається таблиця, в якій зафарбовані червоним кольором рядки, де є псевдовипадкове число, що дорівнює 41. Причому подібний підхід справедливий для всіх класів, успадкованих відповідно від QAbstractItemModel. Тобто для QSqlQueryModel , QSqlRelationalTableModel і т.д.
Архів з прикладом уроку з під ОС Ubuntu - уважно перевіряйте, яким шляхом створюється файл бази даних у класі DataBase.
Как передать переменную в класс наследник?
А чутка подробнее ситуацию можете описать? Я не понял формулировки вопроса.
Я хочу из БД дергать значения цветов из профиля пользователя. Как мне передать user_id?
То есть хотите подкрасить строку в таблице по цвету из профиля пользователя?
Да именно так. Но как передать id пользователя не знаю.
Теоретически можно воспользоваться QSqlQuery, чтобы выдернуть данные из профиля прямо в методе data. А сам id можно дёрнуть через метод data, как взято значение в колонке через QSqlTableModel::data(this->index(idx.row(), 3)).toInt()
Так id пользователя нет в данной таблице.
Ну я откуда знал, что у Вас нет этого id в таблице. И это разговор идёт про таблицу с профилями пользователей? Как тогда Вы делаете соответствие между пользователями и их данными, то есть цветами и т.д?
Суть такая, есть таблица, в ней меняются статусы и соответственно цвет строк. В профиле пользователя настраивается эти цвета. Код не работает. В том то и проблема. Пользователь проходит аутентификацию и я получаю его id., а вот как мне передать это id. Сигналы и слоты в данном случае не подходят, я просто не знаю(((
Так, хорошо. статусы меняются. То есть записываете состояние статуса в определённую таблицу... Но там же должен быть внешний ключ на пользователя? Если его нет, то сделайте внешний ключ на пользователя и тогда сможете без проблем дёргать статус и по нему прилагать нужный цвет. Обычно в таких случаях всегда в таблице профилей имеется внешний ключ на пользователя. Реляционные базы данных так и работают.
В профиле пользователя настраивается только интерфейс. В одной таблице работают несколько пользователей и все хотят что бы у них статусы били разными цветами(как раз настраивается в профиле). Я записывал данные в файл настроек
Ну понятно тогда. Сделайте тогда некую таблицу профилей вместо файла настроек, в которой будет храниться набор цветов для каждого варианта статуса. В таблице нужно создать несколько колонок, например четыре колонки для четырёх вариантов статуса. И обязательно внешний ключ на id пользователя. Когда пользователь аутентифицируется, то тогда можно будет дёрнуть через QSqlQuery, например, цвет статуса из таблицы профилей.
Можно как-то объявить переменную QString доступную из разных классов(форм или файлов .cpp)?
Ну можно сделать статическую переменную в заголовочном классе TableModel и как раз эта переменная и будет достаточной для того, чтобы она была видна во всех формах и классах, но это будет не очень хорошее решение как по мне.
Статусы ремонта. "Ждем запчасти", "Без ремонта" и т.д. Я объявляю public: static QString id_user;
Спасибо большое. Все разобрался))) Все оказалось как всегда просто.
Почему-то при встраивании кода в урок 008, при редактировании строки, значения в виджетах пропадают и при сохранении изменений ничего не меняется. Где вызывается функция date?
Нашел ошибку. В функии data() в конце вместо QVariant(), вернул QSqlTableModel::data(idx,role). И все заработало!
Вопрос- с переопределенным методом data и нашим классом- наследником- как удалять строки из модели?
метод model->removeRow(index.row());
не работает.
Для QSqlTableModel концептуально верным подходом являтся удаление запросом к базе данных.
del
Это как понять? Т.е. не через модель удалять, а через запрос к базе? А в чем тогда правильность? Если правильней с моделью работать, а не с базой в обход модели? Или я не так понял.
А. Да вы правы. Я немного попутал модель эту QSqlTableModel с QSqlQueryModel. У них есть разница, что QSqlQueryModel является read only, а поэтому функционал по удалению нужно дописывать.
Я думаю, всё дело в том, что или стратегия удаления не совсем верно настроена, либо там происходит какая-то ошибка.
Выведите в qDebug резальтат lastError() из модели. Там может быть по факту что угодно.
QSqlError("", "", "")
Причем, если я использую Ваш подход- наследованный класс
то не удаляет, как только делаю родной класс:
То удаляет и ошибка:
QSqlError("", "", "")
такая же.
После работы гляну проект. Пока нет мыслей.
ок, буду ждать. Это странно, т.к. мы не переопределяли метод удаления.
Ну вот поэтому я и нахожусь в замешательстве. Вообще не должно было быть такого поведения. Разве что каким-то образом повлиял запрос в конструкторе, может быть не закрылась транзакция или что-то ещё, леший его знает.
Вот еще странность- не может сделать запись в уже имеющейся ячейке.
А в оригинальном пишет, но с глюком.
Да, метод data всё-таки влиял, я переписал его так и заработало удаление
Далее ваш код для удаления переписал иначе
Это будет более эффективно
Спасибо, завтра првоерю. А
Тоже заработало?
Ну в моём примере, который в статье сработало так
Поскольку model->index(1, 0) - это индекс колонки id, которая скрыта, поэтому без дополнительных настроек таблицы вы не увидите результата
не работает. Вылетает с ошибкой.
У меня работает. Исправлял в проекте, который приложен к статье.
А что происходит в вашем коде, с учётом места вызова этого кода, я знать не могу ;)
Дебажьте и добавляйте условия, которые обезопасят вызов кода
Здравствуйте.
В Вашем примере в строке QSqlTableModel::data(this->index(idx.row(), 3))
3 - это индекс столбца. А есть ли возможность в данном случае как-то использовать имя столбца?
Добрый день. Нет, данный метод оперирует целочисленными значениями, которые являются индексами столбца и строки, для создания объекта QModelIndex, по которому уже метод data возвращает значение в ячейке.
Если ваш вопрос касается читаемости кода, то в таком случае правильным решением будет создать enum для столбцов, который будет отображать фактическое имя столбца.
Спасибо за ответ. Нет, дело не в читаемости кода, в разных таблицах у меня есть столбцы с одинаковым именем, но с разными индексами. Хотел сделать решение по имени столбца для всех таблиц сразу.
В этом случае вижу только какой-нибудь костыль в стиле перебора по всем индексам в заголовке с помощью методу headerData .
То есть пройтись в for цикле пока не будет совпадения названия столбца, запомнить индекс, а потом уже использовать его в методе data. Но опять же, headerData по умолчанию возвращает название колонки, но если делать перевод и переназывать колонки, то это решение покажет свою костыльность во всей красе. Так что это скорее только усложнит поддержку приложения.