Update copyright headers
[qt:qt.git] / demos / sqlbrowser / browser.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "browser.h"
43 #include "qsqlconnectiondialog.h"
44
45 #include <QtGui>
46 #include <QtSql>
47
48 Browser::Browser(QWidget *parent)
49     : QWidget(parent)
50 {
51     setupUi(this);
52
53     table->addAction(insertRowAction);
54     table->addAction(deleteRowAction);
55
56     if (QSqlDatabase::drivers().isEmpty())
57         QMessageBox::information(this, tr("No database drivers found"),
58                                  tr("This demo requires at least one Qt database driver. "
59                                     "Please check the documentation how to build the "
60                                     "Qt SQL plugins."));
61
62     emit statusMessage(tr("Ready."));
63 }
64
65 Browser::~Browser()
66 {
67 }
68
69 void Browser::exec()
70 {
71     QSqlQueryModel *model = new QSqlQueryModel(table);
72     model->setQuery(QSqlQuery(sqlEdit->toPlainText(), connectionWidget->currentDatabase()));
73     table->setModel(model);
74
75     if (model->lastError().type() != QSqlError::NoError)
76         emit statusMessage(model->lastError().text());
77     else if (model->query().isSelect())
78         emit statusMessage(tr("Query OK."));
79     else
80         emit statusMessage(tr("Query OK, number of affected rows: %1").arg(
81                            model->query().numRowsAffected()));
82
83     updateActions();
84 }
85
86 QSqlError Browser::addConnection(const QString &driver, const QString &dbName, const QString &host,
87                             const QString &user, const QString &passwd, int port)
88 {
89     static int cCount = 0;
90
91     QSqlError err;
92     QSqlDatabase db = QSqlDatabase::addDatabase(driver, QString("Browser%1").arg(++cCount));
93     db.setDatabaseName(dbName);
94     db.setHostName(host);
95     db.setPort(port);
96     if (!db.open(user, passwd)) {
97         err = db.lastError();
98         db = QSqlDatabase();
99         QSqlDatabase::removeDatabase(QString("Browser%1").arg(cCount));
100     }
101     connectionWidget->refresh();
102
103     return err;
104 }
105
106 void Browser::addConnection()
107 {
108     QSqlConnectionDialog dialog(this);
109     if (dialog.exec() != QDialog::Accepted)
110         return;
111
112     if (dialog.useInMemoryDatabase()) {
113         QSqlDatabase::database("in_mem_db", false).close();
114         QSqlDatabase::removeDatabase("in_mem_db");
115         QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "in_mem_db");
116         db.setDatabaseName(":memory:");
117         if (!db.open())
118             QMessageBox::warning(this, tr("Unable to open database"), tr("An error occurred while "
119                                                                          "opening the connection: ") + db.lastError().text());
120         QSqlQuery q("", db);
121         q.exec("drop table Movies");
122         q.exec("drop table Names");
123         q.exec("create table Movies (id integer primary key, Title varchar, Director varchar, Rating number)");
124         q.exec("insert into Movies values (0, 'Metropolis', 'Fritz Lang', '8.4')");
125         q.exec("insert into Movies values (1, 'Nosferatu, eine Symphonie des Grauens', 'F.W. Murnau', '8.1')");
126         q.exec("insert into Movies values (2, 'Bis ans Ende der Welt', 'Wim Wenders', '6.5')");
127         q.exec("insert into Movies values (3, 'Hardware', 'Richard Stanley', '5.2')");
128         q.exec("insert into Movies values (4, 'Mitchell', 'Andrew V. McLaglen', '2.1')");
129         q.exec("create table Names (id integer primary key, Firstname varchar, Lastname varchar, City varchar)");
130         q.exec("insert into Names values (0, 'Sala', 'Palmer', 'Morristown')");
131         q.exec("insert into Names values (1, 'Christopher', 'Walker', 'Morristown')");
132         q.exec("insert into Names values (2, 'Donald', 'Duck', 'Andeby')");
133         q.exec("insert into Names values (3, 'Buck', 'Rogers', 'Paris')");
134         q.exec("insert into Names values (4, 'Sherlock', 'Holmes', 'London')");
135         connectionWidget->refresh();
136     } else {
137         QSqlError err = addConnection(dialog.driverName(), dialog.databaseName(), dialog.hostName(),
138                            dialog.userName(), dialog.password(), dialog.port());
139         if (err.type() != QSqlError::NoError)
140             QMessageBox::warning(this, tr("Unable to open database"), tr("An error occurred while "
141                                        "opening the connection: ") + err.text());
142     }
143 }
144
145 void Browser::showTable(const QString &t)
146 {
147     QSqlTableModel *model = new QSqlTableModel(table, connectionWidget->currentDatabase());
148     model->setEditStrategy(QSqlTableModel::OnRowChange);
149     model->setTable(connectionWidget->currentDatabase().driver()->escapeIdentifier(t, QSqlDriver::TableName));
150     model->select();
151     if (model->lastError().type() != QSqlError::NoError)
152         emit statusMessage(model->lastError().text());
153     table->setModel(model);
154     table->setEditTriggers(QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed);
155
156     connect(table->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
157             this, SLOT(currentChanged()));
158     updateActions();
159 }
160
161 void Browser::showMetaData(const QString &t)
162 {
163     QSqlRecord rec = connectionWidget->currentDatabase().record(t);
164     QStandardItemModel *model = new QStandardItemModel(table);
165
166     model->insertRows(0, rec.count());
167     model->insertColumns(0, 7);
168
169     model->setHeaderData(0, Qt::Horizontal, "Fieldname");
170     model->setHeaderData(1, Qt::Horizontal, "Type");
171     model->setHeaderData(2, Qt::Horizontal, "Length");
172     model->setHeaderData(3, Qt::Horizontal, "Precision");
173     model->setHeaderData(4, Qt::Horizontal, "Required");
174     model->setHeaderData(5, Qt::Horizontal, "AutoValue");
175     model->setHeaderData(6, Qt::Horizontal, "DefaultValue");
176
177
178     for (int i = 0; i < rec.count(); ++i) {
179         QSqlField fld = rec.field(i);
180         model->setData(model->index(i, 0), fld.name());
181         model->setData(model->index(i, 1), fld.typeID() == -1
182                 ? QString(QVariant::typeToName(fld.type()))
183                 : QString("%1 (%2)").arg(QVariant::typeToName(fld.type())).arg(fld.typeID()));
184         model->setData(model->index(i, 2), fld.length());
185         model->setData(model->index(i, 3), fld.precision());
186         model->setData(model->index(i, 4), fld.requiredStatus() == -1 ? QVariant("?")
187                 : QVariant(bool(fld.requiredStatus())));
188         model->setData(model->index(i, 5), fld.isAutoValue());
189         model->setData(model->index(i, 6), fld.defaultValue());
190     }
191
192     table->setModel(model);
193     table->setEditTriggers(QAbstractItemView::NoEditTriggers);
194
195     updateActions();
196 }
197
198 void Browser::insertRow()
199 {
200     QSqlTableModel *model = qobject_cast<QSqlTableModel *>(table->model());
201     if (!model)
202         return;
203
204     QModelIndex insertIndex = table->currentIndex();
205     int row = insertIndex.row() == -1 ? 0 : insertIndex.row();
206     model->insertRow(row);
207     insertIndex = model->index(row, 0);
208     table->setCurrentIndex(insertIndex);
209     table->edit(insertIndex);
210 }
211
212 void Browser::deleteRow()
213 {
214     QSqlTableModel *model = qobject_cast<QSqlTableModel *>(table->model());
215     if (!model)
216         return;
217
218     model->setEditStrategy(QSqlTableModel::OnManualSubmit);
219
220     QModelIndexList currentSelection = table->selectionModel()->selectedIndexes();
221     for (int i = 0; i < currentSelection.count(); ++i) {
222         if (currentSelection.at(i).column() != 0)
223             continue;
224         model->removeRow(currentSelection.at(i).row());
225     }
226
227     model->submitAll();
228     model->setEditStrategy(QSqlTableModel::OnRowChange);
229
230     updateActions();
231 }
232
233 void Browser::updateActions()
234 {
235     bool enableIns = qobject_cast<QSqlTableModel *>(table->model());
236     bool enableDel = enableIns && table->currentIndex().isValid();
237
238     insertRowAction->setEnabled(enableIns);
239     deleteRowAction->setEnabled(enableDel);
240 }
241
242 void Browser::about()
243 {
244     QMessageBox::about(this, tr("About"), tr("The SQL Browser demonstration "
245         "shows how a data browser can be used to visualize the results of SQL"
246         "statements on a live database"));
247 }