Модель и представление таблицы БД (файл examples-qt/db02/db02.h)
1 #include <QSqlQueryModel>
2 #include <QTableView>
3 4 class MyModel : public QSqlQueryModel { 5 Q_OBJECT 6 public: 7 MyModel(QObject *parent = 0);
8 Qt::ItemFlags flags(const QModelIndex &index) const; 9 QVariant data(const QModelIndex &index, 10 int role = Qt::DisplayRole) const; 11 bool setData(const QModelIndex &index, 12 const QVariant &value, int role);
13 private: 14 void refresh();
15 }; 16 17 class MyView : public QTableView { 18 Q_OBJECT 19 public: 20 MyView(QWidget *parent = 0);
21 private: 22 virtual void resizeEvent(QResizeEvent *event);
23 };
1 // Таблица базы данных: пользовательская модель и представление 2 3 #include <QtGui>
4 #include <QtSql>
5 6 #include "db02.h" 7 8 MyModel::MyModel(QObject *parent) 9 : QSqlQueryModel(parent) { 10 refresh();
11 } 12 13 Qt::ItemFlags MyModel::flags( 14 const QModelIndex &index) const { 15 16 Qt::ItemFlags flags = QSqlQueryModel::flags(index);
17 if (index.column() >
= 1 && index.column() < 4) 18 flags |= Qt::ItemIsEditable; 19 if (index.column() == 4) 20 flags |= Qt::ItemIsUserCheckable; 21 return flags; 22 } 23 24 QVariant MyModel::data( 25 const QModelIndex &index, 26 int role) const { 27 28 QVariant value = QSqlQueryModel::data(index, role);
29 30 switch (role) { 31 32 case Qt::DisplayRole: // Данные для отображения 33 case Qt::EditRole: // Данные для редактирования 34 if (index.column() == 0) 35 return value.toString().prepend(tr("№"));
36 else if (index.column() == 2 && role == Qt::DisplayRole) 37 return value.toDate().toString("dd.MM.yyyy");
38 else if (index.column() == 3 && role == Qt::DisplayRole) 39 return tr("%1") 40 .arg(value.toDouble(), 0, 'f', 2);
41 else if (index.column() == 4) 42 return value.toInt() != 0 ? tr("Да") : tr("Нет");
43 else 44 return value; 45 46 case Qt::TextColorRole: // Цвет текста 47 if(index.column() == 1) 48 return qVariantFromValue(QColor(Qt::blue));
49 else 50 return value; 51 52 case Qt::TextAlignmentRole: // Выравнивание 53 if(index.column() == 3) 54 return int(Qt::AlignRight | Qt::AlignVCenter);
55 else if(index.column() == 2 index.column() == 4) 56 return int(Qt::AlignHCenter | Qt::AlignVCenter);
57 else 58 return int(Qt::AlignLeft | Qt::AlignVCenter);
59 60 case Qt::FontRole: // Шрифт 61 if(index.column() == 1) { 62 QFont font = QFont("Helvetica", 10, QFont::Bold);
63 return qVariantFromValue(font);
64 }else 65 return value; 66 67 case Qt::BackgroundColorRole: { // Цвет фона 68 int a = (index.row() % 2) ? 14 : 0; 69 if(index.column() == 0) 70 return qVariantFromValue(QColor(220,240-a,230-a));
71 else if(index.column() == 4) 72 return qVariantFromValue(QColor(200,220-a,255-a));
73 else 74 return value; 75 } 76 case Qt::CheckStateRole: // Галочка 77 if (index.column() == 4) 78 return (QSqlQueryModel::data(index).toInt() != 0) ? 79 Qt::Checked : Qt::Unchecked; 80 else 81 return value; 82 83 case Qt::SizeHintRole: // Размер ячейки 84 if (index.column() == 0) 85 return QSize(70, 10);
86 if (index.column() == 4) 87 return QSize(60, 10);
88 else 89 return QSize(110, 10);
90 } 91 return value; 92 } 93 94 bool MyModel::setData( 95 const QModelIndex &index, 96 const QVariant &value, 97 int /* role */) { 98 if (index.column() < 1 index.column() >
4) 99 return false; 100 101 QModelIndex primaryKeyIndex = QSqlQueryModel::index( 102 index.row(), 0);
103 int id = QSqlQueryModel::data(primaryKeyIndex).toInt();
104 105 //clear();
// Если надо полностью перерисовать таблицу. 106 107 bool ok; 108 QSqlQuery query; 109 if (index.column() == 1) { 110 query.prepare("update employee set name = ? where id = ?");
111 query.addBindValue(value.toString());
112 query.addBindValue(id);
113 }else if(index.column() == 2) { 114 query.prepare("update employee set born = ? where id = ?");
115 query.addBindValue(value.toDate());
116 query.addBindValue(id);
117 }else if(index.column() == 3) { 118 query.prepare("update employee set salary = ? where id = ?");
119 query.addBindValue(value.toDouble());
120 query.addBindValue(id);
121 }else if(index.column() == 4) { 122 query.prepare("update employee set married = ? where id = ?");
123 query.addBindValue(value.toInt());
124 query.addBindValue(id);
125 } 126 ok = query.exec();
127 refresh();
128 return ok; 129 } 130 131 void MyModel::refresh() { 132 setQuery("select * from employee");
133 134 setHeaderData(0, Qt::Horizontal, 135 tr("Табельн.\nномер"));
136 setHeaderData(1, Qt::Horizontal, 137 tr("Имя"));
138 setHeaderData(2, Qt::Horizontal, 139 tr("День рождения"));
140 setHeaderData(3, Qt::Horizontal, 141 tr("Зарплата"));
142 setHeaderData(4, Qt::Horizontal, 143 tr("Женат/\nзамужем"));
144 } 145 146 //------------------------------------ 147 MyView::MyView(QWidget *parent) 148 : QTableView(parent) { 149 150 } 151 152 void MyView::resizeEvent(QResizeEvent *event) { 153 resizeRowsToContents();
154 resizeColumnsToContents();
155 QTableView::resizeEvent(event);
156 } 157 158 //------------------------------------ 159 int main(int argc, char *argv[]) { 160 161 QApplication app(argc, argv);
162 163 QTextCodec *codec = QTextCodec::codecForName("CP1251");
164 QTextCodec::setCodecForTr(codec);
165 QTextCodec::setCodecForCStrings(codec);
166 167 QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
168 db.setDatabaseName("db1");
169 db.setUserName("root");
170 db.setPassword("password");
171 db.open();
172 173 // QSqlQuery q; 174 // Для корректного отображения кириллицы, возможно, 175 // придётся установить кодировку: 176 //q.exec(QObject::tr("SET NAMES 'cp1251'"));
177 178 MyModel *model = new MyModel();
179 180 MyView *view = new MyView();
181 view->
setModel(model);
182 183 view->
setAlternatingRowColors(true);
184 view->
resizeRowsToContents();
185 view->
resizeColumnsToContents();
186 view->
show();
187 188 return app.exec();
189 }
Для своей модели мы использовали базовый класс QSqlQueryModel, работающий с произвольным набором SQL-запросов для чтения и записи данных в БД. Но за всё приходится платить: нам пришлось подробно расписывать реализацию методов data и setData. В данном случае мы имели дело с единственной таблицей базы данных, поэтому можно было в качестве базового класса взять QSqlTableModel.
Проверьте, как работает эта программа. Намного лучше, чем предыдущая, не правда ли? Размеры ячеек теперь не "прыгают" при редактировании, а при щелчке левой кнопкой мыши по элементу QCheckBox в ячейках последнего столбца автоматически изменяется текстовая метка "Да/Нет". Но ввести трёхзначную зарплату всё ещё не получается. Мы исправим данный недостаток в следующем разделе.