diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /examples/sql/masterdetail | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'examples/sql/masterdetail')
-rw-r--r-- | examples/sql/masterdetail/albumdetails.xml | 98 | ||||
-rw-r--r-- | examples/sql/masterdetail/database.h | 97 | ||||
-rw-r--r-- | examples/sql/masterdetail/dialog.cpp | 283 | ||||
-rw-r--r-- | examples/sql/masterdetail/dialog.h | 83 | ||||
-rw-r--r-- | examples/sql/masterdetail/images/icon.png | bin | 0 -> 30095 bytes | |||
-rw-r--r-- | examples/sql/masterdetail/images/image.png | bin | 0 -> 166692 bytes | |||
-rw-r--r-- | examples/sql/masterdetail/main.cpp | 60 | ||||
-rw-r--r-- | examples/sql/masterdetail/mainwindow.cpp | 430 | ||||
-rw-r--r-- | examples/sql/masterdetail/mainwindow.h | 104 | ||||
-rw-r--r-- | examples/sql/masterdetail/masterdetail.pro | 16 | ||||
-rw-r--r-- | examples/sql/masterdetail/masterdetail.qrc | 6 |
11 files changed, 1177 insertions, 0 deletions
diff --git a/examples/sql/masterdetail/albumdetails.xml b/examples/sql/masterdetail/albumdetails.xml new file mode 100644 index 0000000..aacbdac --- /dev/null +++ b/examples/sql/masterdetail/albumdetails.xml @@ -0,0 +1,98 @@ + <archive> + <album id="1" > + <track number="01" >Humming one of your songs</track> + <track number="02" >Are they saying goodbye</track> + <track number="03" >On off</track> + <track number="04" >I shot my heart</track> + <track number="05" >Drowning in Those Eyes</track> + <track number="06" >So you did it again</track> + <track number="07" >One more time</track> + <track number="08" >Headphone silence</track> + <track number="09" >What I want</track> + <track number="10" >Sleeping by the Fyris River</track> + <track number="11" >Wooden Body</track> + <track number="12" >Humming one of your songs (encore)</track> + </album> + <album id="2" > + <track number="01" >To let myself go</track> + <track number="02" >Rubber and Soul</track> + <track number="03" >Balloon ranger</track> + <track number="04" >My lover will go</track> + <track number="05" >Temporary dive</track> + <track number="06" >Laid in earth</track> + <track number="07" >This voice</track> + <track number="08" >Where friend rhymes with end</track> + <track number="09" >Song No.6 feat Ron Sexsmith</track> + <track number="10" >The Fight Song</track> + </album> + <album id="3" > + <track number="01" >From Grace</track> + <track number="02" >All's not last</track> + <track number="03" >That Great October Sound</track> + <track number="04" >Life Here Is Gold</track> + <track number="05" >Tomorrow Stays The Same</track> + <track number="06" >Postulate</track> + <track number="07" >Adelaide</track> + <track number="08" >John Wayne</track> + <track number="09" >Love's Lost</track> + <track number="10" >Dreamweaver</track> + <track number="11" >Outro</track> + </album> + <album id="4" > + <track number="01" >Rain down on me</track> + <track number="02" >Cecilia</track> + <track number="03" >Make a mess of yourself</track> + <track number="04" >Pale green eyes</track> + <track number="05" >Either way I'm gone</track> + <track number="06" >Honey</track> + <track number="07" >Rise in shame</track> + <track number="08" >Stray dogs</track> + <track number="09" >The willow</track> + <track number="10" >Stay home</track> + <track number="11" >Outro</track> + </album> + <album id="5" > + </album> + <album id="6" > + <track number="01" >Kontroll på kontinentet</track> + <track number="02" >Ompa til du dør</track> + <track number="03" >Bøn fra helvete</track> + <track number="04" >170</track> + <track number="05" >Rullett</track> + <track number="06" >Dr. Mowinckel</track> + <track number="07" >Fra sjåfør til passasjer</track> + <track number="08" >Resistansen</track> + <track number="09" >Dekk bord</track> + <track number="10" >Bak et halleluja</track> + <track number="11" >Bris</track> + <track number="12" >Mr. Kaizer, hans Constanze og meg</track> + </album> + <album id="7" > + <track number="01" >Di grind</track> + <track number="02" >Hevnervals</track> + <track number="03" >Evig pint</track> + <track number="04" >De involverte</track> + <track number="05" >Djevelens orkester</track> + <track number="06" >Container</track> + <track number="07" >Naade</track> + <track number="08" >Min kvite russer</track> + <track number="09" >Veterans klage</track> + <track number="10" >Til depotet</track> + <track number="11" >Salt og pepper</track> + <track number="12" >Drøm Hardt (Requiem Part I)</track> + </album> + <album id="8" > + <track number="01" >KGB</track> + <track number="02" >Maestro</track> + <track number="03" >Knekker deg til sist</track> + <track number="04" >Senor Flamingos Adieu</track> + <track number="05" >Blitzregn baby</track> + <track number="06" >Dieter Meyers Inst.</track> + <track number="07" >Christiania</track> + <track number="08" >Delikatessen</track> + <track number="09" >Jævel av en tango</track> + <track number="10" >Papa har lov</track> + <track number="11" >Auksjon (i Dieter Meyers hall)</track> + <track number="12" >På ditt skift</track> + </album> + </archive> diff --git a/examples/sql/masterdetail/database.h b/examples/sql/masterdetail/database.h new file mode 100644 index 0000000..a760e41 --- /dev/null +++ b/examples/sql/masterdetail/database.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DATABASE_H +#define DATABASE_H + +#include <QMessageBox> +#include <QSqlDatabase> +#include <QSqlError> +#include <QSqlQuery> + +static bool createConnection() +{ + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); + db.setDatabaseName(":memory:"); + if (!db.open()) { + QMessageBox::critical(0, qApp->tr("Cannot open database"), + qApp->tr("Unable to establish a database connection.\n" + "This example needs SQLite support. Please read " + "the Qt SQL driver documentation for information how " + "to build it.\n\n" + "Click Cancel to exit."), QMessageBox::Cancel); + return false; + } + + QSqlQuery query; + + query.exec("create table artists (id int primary key, " + "artist varchar(40), " + "albumcount int)"); + + query.exec("insert into artists values(0, '<all>', 0)"); + query.exec("insert into artists values(1, 'Ane Brun', 2)"); + query.exec("insert into artists values(2, 'Thomas Dybdahl', 3)"); + query.exec("insert into artists values(3, 'Kaizers Orchestra', 3)"); + + query.exec("create table albums (albumid int primary key, " + "title varchar(50), " + "artistid int, " + "year int)"); + + query.exec("insert into albums values(1, 'Spending Time With Morgan', 1, " + "2003)"); + query.exec("insert into albums values(2, 'A Temporary Dive', 1, 2005)"); + query.exec("insert into albums values(3, '...The Great October Sound', 2, " + "2002)"); + query.exec("insert into albums values(4, 'Stray Dogs', 2, 2003)"); + query.exec("insert into albums values(5, " + "'One day you`ll dance for me, New York City', 2, 2004)"); + query.exec("insert into albums values(6, 'Ompa Til Du D\xf8r', 3, 2001)"); + query.exec("insert into albums values(7, 'Evig Pint', 3, 2002)"); + query.exec("insert into albums values(8, 'Maestro', 3, 2005)"); + + return true; +} + +#endif + + diff --git a/examples/sql/masterdetail/dialog.cpp b/examples/sql/masterdetail/dialog.cpp new file mode 100644 index 0000000..0adf208 --- /dev/null +++ b/examples/sql/masterdetail/dialog.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dialog.h" + +int uniqueAlbumId; +int uniqueArtistId; + +Dialog::Dialog(QSqlRelationalTableModel *albums, QDomDocument details, + QFile *output, QWidget *parent) + : QDialog(parent) +{ + model = albums; + albumDetails = details; + outputFile = output; + + QGroupBox *inputWidgetBox = createInputWidgets(); + QDialogButtonBox *buttonBox = createButtons(); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(inputWidgetBox); + layout->addWidget(buttonBox); + setLayout(layout); + + setWindowTitle(tr("Add Album")); +} + +void Dialog::submit() +{ + QString artist = artistEditor->text(); + QString title = titleEditor->text(); + + if (artist.isEmpty() || title.isEmpty()) { + QString message(tr("Please provide both the name of the artist " + "and the title of the album.")); + QMessageBox::information(this, tr("Add Album"), message); + } else { + int artistId = findArtistId(artist); + int albumId = addNewAlbum(title, artistId); + + QStringList tracks; + tracks = tracksEditor->text().split(',', QString::SkipEmptyParts); + addTracks(albumId, tracks); + + increaseAlbumCount(indexOfArtist(artist)); + accept(); + } +} + +int Dialog::findArtistId(const QString &artist) +{ + QSqlTableModel *artistModel = model->relationModel(2); + int row = 0; + + while (row < artistModel->rowCount()) { + QSqlRecord record = artistModel->record(row); + if (record.value("artist") == artist) + return record.value("id").toInt(); + else + row++; + } + return addNewArtist(artist); +} + + +int Dialog::addNewArtist(const QString &name) +{ + QSqlTableModel *artistModel = model->relationModel(2); + QSqlRecord record; + + int id = generateArtistId(); + + QSqlField f1("id", QVariant::Int); + QSqlField f2("artist", QVariant::String); + QSqlField f3("albumcount", QVariant::Int); + + f1.setValue(QVariant(id)); + f2.setValue(QVariant(name)); + f3.setValue(QVariant(0)); + record.append(f1); + record.append(f2); + record.append(f3); + + artistModel->insertRecord(-1, record); + return id; +} + +int Dialog::addNewAlbum(const QString &title, int artistId) +{ + int id = generateAlbumId(); + QSqlRecord record; + + QSqlField f1("albumid", QVariant::Int); + QSqlField f2("title", QVariant::String); + QSqlField f3("artistid", QVariant::Int); + QSqlField f4("year", QVariant::Int); + + f1.setValue(QVariant(id)); + f2.setValue(QVariant(title)); + f3.setValue(QVariant(artistId)); + f4.setValue(QVariant(yearEditor->value())); + record.append(f1); + record.append(f2); + record.append(f3); + record.append(f4); + + model->insertRecord(-1, record); + return id; +} + +void Dialog::addTracks(int albumId, QStringList tracks) +{ + QDomElement albumNode = albumDetails.createElement("album"); + albumNode.setAttribute("id", albumId); + + for (int i = 0; i < tracks.count(); i++) { + QString trackNumber = QString::number(i); + if (i < 10) + trackNumber.prepend("0"); + + QDomText textNode = albumDetails.createTextNode(tracks.at(i)); + + QDomElement trackNode = albumDetails.createElement("track"); + trackNode.setAttribute("number", trackNumber); + trackNode.appendChild(textNode); + + albumNode.appendChild(trackNode); + } + + QDomNodeList archive = albumDetails.elementsByTagName("archive"); + archive.item(0).appendChild(albumNode); + +/* + The following code is commented out since the example uses an in + memory database, i.e., altering the XML file will bring the data + out of sync. + + if (!outputFile->open(QIODevice::WriteOnly)) { + return; + } else { + QTextStream stream(outputFile); + archive.item(0).save(stream, 4); + outputFile->close(); + } +*/ +} + +void Dialog::increaseAlbumCount(QModelIndex artistIndex) +{ + QSqlTableModel *artistModel = model->relationModel(2); + + QModelIndex albumCountIndex; + albumCountIndex = artistIndex.sibling(artistIndex.row(), 2); + + int albumCount = albumCountIndex.data().toInt(); + artistModel->setData(albumCountIndex, QVariant(albumCount + 1)); +} + + +void Dialog::revert() +{ + artistEditor->clear(); + titleEditor->clear(); + yearEditor->setValue(QDate::currentDate().year()); + tracksEditor->clear(); +} + +QGroupBox *Dialog::createInputWidgets() +{ + QGroupBox *box = new QGroupBox(tr("Add Album")); + + QLabel *artistLabel = new QLabel(tr("Artist:")); + QLabel *titleLabel = new QLabel(tr("Title:")); + QLabel *yearLabel = new QLabel(tr("Year:")); + QLabel *tracksLabel = new QLabel(tr("Tracks (separated by comma):")); + + artistEditor = new QLineEdit; + titleEditor = new QLineEdit; + + yearEditor = new QSpinBox; + yearEditor->setMinimum(1900); + yearEditor->setMaximum(QDate::currentDate().year()); + yearEditor->setValue(yearEditor->maximum()); + yearEditor->setReadOnly(false); + + tracksEditor = new QLineEdit; + + QGridLayout *layout = new QGridLayout; + layout->addWidget(artistLabel, 0, 0); + layout->addWidget(artistEditor, 0, 1); + layout->addWidget(titleLabel, 1, 0); + layout->addWidget(titleEditor, 1, 1); + layout->addWidget(yearLabel, 2, 0); + layout->addWidget(yearEditor, 2, 1); + layout->addWidget(tracksLabel, 3, 0, 1, 2); + layout->addWidget(tracksEditor, 4, 0, 1, 2); + box->setLayout(layout); + + return box; +} + +QDialogButtonBox *Dialog::createButtons() +{ + QPushButton *closeButton = new QPushButton(tr("&Close")); + QPushButton *revertButton = new QPushButton(tr("&Revert")); + QPushButton *submitButton = new QPushButton(tr("&Submit")); + + closeButton->setDefault(true); + + connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); + connect(revertButton, SIGNAL(clicked()), this, SLOT(revert())); + connect(submitButton, SIGNAL(clicked()), this, SLOT(submit())); + + QDialogButtonBox *buttonBox = new QDialogButtonBox; + buttonBox->addButton(submitButton, QDialogButtonBox::ResetRole); + buttonBox->addButton(revertButton, QDialogButtonBox::ResetRole); + buttonBox->addButton(closeButton, QDialogButtonBox::RejectRole); + + return buttonBox; +} + +QModelIndex Dialog::indexOfArtist(const QString &artist) +{ + QSqlTableModel *artistModel = model->relationModel(2); + + for (int i = 0; i < artistModel->rowCount(); i++) { + QSqlRecord record = artistModel->record(i); + if (record.value("artist") == artist) + return artistModel->index(i, 1); + } + + return QModelIndex(); +} + +int Dialog::generateArtistId() +{ + uniqueArtistId += 1; + return uniqueArtistId; +} + +int Dialog::generateAlbumId() +{ + uniqueAlbumId += 1; + return uniqueAlbumId; +} diff --git a/examples/sql/masterdetail/dialog.h b/examples/sql/masterdetail/dialog.h new file mode 100644 index 0000000..0f4b54a --- /dev/null +++ b/examples/sql/masterdetail/dialog.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIALOG_H +#define DIALOG_H + +#include <QtGui> +#include <QtSql> +#include <QtXml> + +class Dialog : public QDialog +{ + Q_OBJECT + +public: + Dialog(QSqlRelationalTableModel *albums, QDomDocument details, + QFile *output, QWidget *parent = 0); + +private slots: + void revert(); + void submit(); + +private: + int addNewAlbum(const QString &title, int artistId); + int addNewArtist(const QString &name); + void addTracks(int albumId, QStringList tracks); + QDialogButtonBox *createButtons(); + QGroupBox *createInputWidgets(); + int findArtistId(const QString &artist); + int generateAlbumId(); + int generateArtistId(); + void increaseAlbumCount(QModelIndex artistIndex); + QModelIndex indexOfArtist(const QString &artist); + + QSqlRelationalTableModel *model; + QDomDocument albumDetails; + QFile *outputFile; + + QLineEdit *artistEditor; + QLineEdit *titleEditor; + QSpinBox *yearEditor; + QLineEdit *tracksEditor; +}; + +#endif diff --git a/examples/sql/masterdetail/images/icon.png b/examples/sql/masterdetail/images/icon.png Binary files differnew file mode 100644 index 0000000..31f68b8 --- /dev/null +++ b/examples/sql/masterdetail/images/icon.png diff --git a/examples/sql/masterdetail/images/image.png b/examples/sql/masterdetail/images/image.png Binary files differnew file mode 100644 index 0000000..1d78037 --- /dev/null +++ b/examples/sql/masterdetail/images/image.png diff --git a/examples/sql/masterdetail/main.cpp b/examples/sql/masterdetail/main.cpp new file mode 100644 index 0000000..932b67a --- /dev/null +++ b/examples/sql/masterdetail/main.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "database.h" +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(masterdetail); + + QApplication app(argc, argv); + + if (!createConnection()) + return 1; + + QFile *albumDetails = new QFile("albumdetails.xml"); + MainWindow window("artists", "albums", albumDetails); + window.show(); + return app.exec(); +} diff --git a/examples/sql/masterdetail/mainwindow.cpp b/examples/sql/masterdetail/mainwindow.cpp new file mode 100644 index 0000000..67825d6 --- /dev/null +++ b/examples/sql/masterdetail/mainwindow.cpp @@ -0,0 +1,430 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "dialog.h" + +#include <QtGui> +#include <QtSql> +#include <QtXml> + +extern int uniqueAlbumId; +extern int uniqueArtistId; + +MainWindow::MainWindow(const QString &artistTable, const QString &albumTable, + QFile *albumDetails, QWidget *parent) + : QMainWindow(parent) +{ + file = albumDetails; + readAlbumData(); + + model = new QSqlRelationalTableModel(this); + model->setTable(albumTable); + model->setRelation(2, QSqlRelation(artistTable, "id", "artist")); + model->select(); + + QGroupBox *artists = createArtistGroupBox(); + QGroupBox *albums = createAlbumGroupBox(); + QGroupBox *details = createDetailsGroupBox(); + + artistView->setCurrentIndex(0); + uniqueAlbumId = model->rowCount(); + uniqueArtistId = artistView->count(); + + connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), + this, SLOT(updateHeader(QModelIndex, int, int))); + connect(model, SIGNAL(rowsRemoved(QModelIndex, int, int)), + this, SLOT(updateHeader(QModelIndex, int, int))); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(artists, 0, 0); + layout->addWidget(albums, 1, 0); + layout->addWidget(details, 0, 1, 2, 1); + layout->setColumnStretch(1, 1); + layout->setColumnMinimumWidth(0, 500); + + QWidget *widget = new QWidget; + widget->setLayout(layout); + setCentralWidget(widget); + createMenuBar(); + + showImageLabel(); + resize(850, 400); + setWindowTitle(tr("Music Archive")); +} + +void MainWindow::changeArtist(int row) +{ + if (row > 0) { + QModelIndex index = model->relationModel(2)->index(row, 1); + model->setFilter("artist = '" + index.data().toString() + '\'') ; + showArtistProfile(index); + } else if (row == 0) { + model->setFilter(QString()); + showImageLabel(); + } else { + return; + } +} + +void MainWindow::showArtistProfile(QModelIndex index) +{ + QSqlRecord record = model->relationModel(2)->record(index.row()); + + QString name = record.value("artist").toString(); + QString count = record.value("albumcount").toString(); + profileLabel->setText(tr("Artist : %1 \n" \ + "Number of Albums: %2").arg(name).arg(count)); + + profileLabel->show(); + iconLabel->show(); + + titleLabel->hide(); + trackList->hide(); + imageLabel->hide(); +} + +void MainWindow::showAlbumDetails(QModelIndex index) +{ + QSqlRecord record = model->record(index.row()); + + QString artist = record.value("artist").toString(); + QString title = record.value("title").toString(); + QString year = record.value("year").toString(); + QString albumId = record.value("albumid").toString(); + + showArtistProfile(indexOfArtist(artist)); + titleLabel->setText(tr("Title: %1 (%2)").arg(title).arg(year)); + titleLabel->show(); + + QDomNodeList albums = albumData.elementsByTagName("album"); + for (int i = 0; i < albums.count(); i++) { + QDomNode album = albums.item(i); + if (album.toElement().attribute("id") == albumId) { + getTrackList(album.toElement()); + break; + } + } + if (!trackList->count() == 0) + trackList->show(); +} + +void MainWindow::getTrackList(QDomNode album) +{ + trackList->clear(); + + QDomNodeList tracks = album.childNodes(); + QDomNode track; + QString trackNumber; + + for (int j = 0; j < tracks.count(); j++) { + + track = tracks.item(j); + trackNumber = track.toElement().attribute("number"); + + QListWidgetItem *item = new QListWidgetItem(trackList); + item->setText(trackNumber + ": " + track.toElement().text()); + } +} + +void MainWindow::addAlbum() +{ + Dialog *dialog = new Dialog(model, albumData, file, this); + int accepted = dialog->exec(); + + if (accepted == 1) { + int lastRow = model->rowCount() - 1; + albumView->selectRow(lastRow); + albumView->scrollToBottom(); + showAlbumDetails(model->index(lastRow, 0)); + } +} + +void MainWindow::deleteAlbum() +{ + QModelIndexList selection = albumView->selectionModel()->selectedRows(0); + + if (!selection.empty()) { + QModelIndex idIndex = selection.at(0); + int id = idIndex.data().toInt(); + QString title = idIndex.sibling(idIndex.row(), 1).data().toString(); + QString artist = idIndex.sibling(idIndex.row(), 2).data().toString(); + + QMessageBox::StandardButton button; + button = QMessageBox::question(this, tr("Delete Album"), + QString(tr("Are you sure you want to " \ + "delete '%1' by '%2'?")) + .arg(title).arg(artist), + QMessageBox::Yes | QMessageBox::No); + + if (button == QMessageBox::Yes) { + removeAlbumFromFile(id); + removeAlbumFromDatabase(idIndex); + decreaseAlbumCount(indexOfArtist(artist)); + + showImageLabel(); + } + } else { + QMessageBox::information(this, tr("Delete Album"), + tr("Select the album you want to delete.")); + } +} + +void MainWindow::removeAlbumFromFile(int id) +{ + + QDomNodeList albums = albumData.elementsByTagName("album"); + + for (int i = 0; i < albums.count(); i++) { + QDomNode node = albums.item(i); + if (node.toElement().attribute("id").toInt() == id) { + albumData.elementsByTagName("archive").item(0).removeChild(node); + break; + } + } +/* + The following code is commented out since the example uses an in + memory database, i.e., altering the XML file will bring the data + out of sync. + + if (!file->open(QIODevice::WriteOnly)) { + return; + } else { + QTextStream stream(file); + albumData.elementsByTagName("archive").item(0).save(stream, 4); + file->close(); + } +*/ +} + +void MainWindow::removeAlbumFromDatabase(QModelIndex index) +{ + model->removeRow(index.row()); +} + +void MainWindow::decreaseAlbumCount(QModelIndex artistIndex) +{ + int row = artistIndex.row(); + QModelIndex albumCountIndex = artistIndex.sibling(row, 2); + int albumCount = albumCountIndex.data().toInt(); + + QSqlTableModel *artists = model->relationModel(2); + + if (albumCount == 1) { + artists->removeRow(row); + showImageLabel(); + } else { + artists->setData(albumCountIndex, QVariant(albumCount - 1)); + } +} + +void MainWindow::readAlbumData() +{ + if (!file->open(QIODevice::ReadOnly)) + return; + + if (!albumData.setContent(file)) { + file->close(); + return; + } + file->close(); +} + +QGroupBox* MainWindow::createArtistGroupBox() +{ + artistView = new QComboBox; + artistView->setModel(model->relationModel(2)); + artistView->setModelColumn(1); + + connect(artistView, SIGNAL(currentIndexChanged(int)), + this, SLOT(changeArtist(int))); + + QGroupBox *box = new QGroupBox(tr("Artist")); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(artistView, 0, 0); + box->setLayout(layout); + + return box; +} + +QGroupBox* MainWindow::createAlbumGroupBox() +{ + QGroupBox *box = new QGroupBox(tr("Album")); + + albumView = new QTableView; + albumView->setEditTriggers(QAbstractItemView::NoEditTriggers); + albumView->setSortingEnabled(true); + albumView->setSelectionBehavior(QAbstractItemView::SelectRows); + albumView->setSelectionMode(QAbstractItemView::SingleSelection); + albumView->setShowGrid(false); + albumView->verticalHeader()->hide(); + albumView->setAlternatingRowColors(true); + albumView->setModel(model); + adjustHeader(); + + QLocale locale = albumView->locale(); + locale.setNumberOptions(QLocale::OmitGroupSeparator); + albumView->setLocale(locale); + + connect(albumView, SIGNAL(clicked(QModelIndex)), + this, SLOT(showAlbumDetails(QModelIndex))); + connect(albumView, SIGNAL(activated(QModelIndex)), + this, SLOT(showAlbumDetails(QModelIndex))); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(albumView, 0, 0); + box->setLayout(layout); + + return box; +} + +QGroupBox* MainWindow::createDetailsGroupBox() +{ + QGroupBox *box = new QGroupBox(tr("Details")); + + profileLabel = new QLabel; + profileLabel->setWordWrap(true); + profileLabel->setAlignment(Qt::AlignBottom); + + titleLabel = new QLabel; + titleLabel->setWordWrap(true); + titleLabel->setAlignment(Qt::AlignBottom); + + iconLabel = new QLabel(); + iconLabel->setAlignment(Qt::AlignBottom | Qt::AlignRight); + iconLabel->setPixmap(QPixmap(":/images/icon.png")); + + imageLabel = new QLabel; + imageLabel->setWordWrap(true); + imageLabel->setAlignment(Qt::AlignCenter); + imageLabel->setPixmap(QPixmap(":/images/image.png")); + + trackList = new QListWidget; + + QGridLayout *layout = new QGridLayout; + layout->addWidget(imageLabel, 0, 0, 3, 2); + layout->addWidget(profileLabel, 0, 0); + layout->addWidget(iconLabel, 0, 1); + layout->addWidget(titleLabel, 1, 0, 1, 2); + layout->addWidget(trackList, 2, 0, 1, 2); + layout->setRowStretch(2, 1); + box->setLayout(layout); + + return box; +} + +void MainWindow::createMenuBar() +{ + QAction *addAction = new QAction(tr("&Add album..."), this); + QAction *deleteAction = new QAction(tr("&Delete album..."), this); + QAction *quitAction = new QAction(tr("&Quit"), this); + QAction *aboutAction = new QAction(tr("&About"), this); + QAction *aboutQtAction = new QAction(tr("About &Qt"), this); + + addAction->setShortcut(tr("Ctrl+A")); + deleteAction->setShortcut(tr("Ctrl+D")); + quitAction->setShortcut(tr("Ctrl+Q")); + + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + fileMenu->addAction(addAction); + fileMenu->addAction(deleteAction); + fileMenu->addSeparator(); + fileMenu->addAction(quitAction); + + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(aboutAction); + helpMenu->addAction(aboutQtAction); + + connect(addAction, SIGNAL(triggered(bool)), this, SLOT(addAlbum())); + connect(deleteAction, SIGNAL(triggered(bool)), this, SLOT(deleteAlbum())); + connect(quitAction, SIGNAL(triggered(bool)), this, SLOT(close())); + connect(aboutAction, SIGNAL(triggered(bool)), this, SLOT(about())); + connect(aboutQtAction, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); +} + +void MainWindow::showImageLabel() +{ + profileLabel->hide(); + titleLabel->hide(); + iconLabel->hide(); + trackList->hide(); + + imageLabel->show(); +} + +QModelIndex MainWindow::indexOfArtist(const QString &artist) +{ + QSqlTableModel *artistModel = model->relationModel(2); + + for (int i = 0; i < artistModel->rowCount(); i++) { + QSqlRecord record = artistModel->record(i); + if (record.value("artist") == artist) + return artistModel->index(i, 1); + } + return QModelIndex(); +} + +void MainWindow::updateHeader(QModelIndex, int, int) +{ + adjustHeader(); +} + +void MainWindow::adjustHeader() +{ + albumView->hideColumn(0); + albumView->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch); + albumView->resizeColumnToContents(2); + albumView->resizeColumnToContents(3); +} + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Music Archive"), + tr("<p>The <b>Music Archive</b> example shows how to present " + "data from different data sources in the same application. " + "The album titles, and the corresponding artists and release dates, " + "are kept in a database, while each album's tracks are stored " + "in an XML file. </p><p>The example also shows how to add as " + "well as remove data from both the database and the " + "associated XML file using the API provided by the QtSql and " + "QtXml modules, respectively.</p>")); +} diff --git a/examples/sql/masterdetail/mainwindow.h b/examples/sql/masterdetail/mainwindow.h new file mode 100644 index 0000000..4d05022 --- /dev/null +++ b/examples/sql/masterdetail/mainwindow.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QDomDocument> +#include <QMainWindow> +#include <QModelIndex> + +QT_BEGIN_NAMESPACE +class QComboBox; +class QFile; +class QGroupBox; +class QLabel; +class QListWidget; +class QSqlRelationalTableModel; +class QTableView; +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(const QString &artistTable, const QString &albumTable, + QFile *albumDetails, QWidget *parent = 0); + +private slots: + void about(); + void addAlbum(); + void changeArtist(int row); + void deleteAlbum(); + void showAlbumDetails(QModelIndex index); + void showArtistProfile(QModelIndex index); + void updateHeader(QModelIndex, int, int); + +private: + void adjustHeader(); + QGroupBox *createAlbumGroupBox(); + QGroupBox *createArtistGroupBox(); + QGroupBox *createDetailsGroupBox(); + void createMenuBar(); + void decreaseAlbumCount(QModelIndex artistIndex); + void getTrackList(QDomNode album); + QModelIndex indexOfArtist(const QString &artist); + void readAlbumData(); + void removeAlbumFromDatabase(QModelIndex album); + void removeAlbumFromFile(int id); + void showImageLabel(); + + QTableView *albumView; + QComboBox *artistView; + QListWidget *trackList; + + QLabel *iconLabel; + QLabel *imageLabel; + QLabel *profileLabel; + QLabel *titleLabel; + + QDomDocument albumData; + QFile *file; + QSqlRelationalTableModel *model; +}; + +#endif diff --git a/examples/sql/masterdetail/masterdetail.pro b/examples/sql/masterdetail/masterdetail.pro new file mode 100644 index 0000000..205c544 --- /dev/null +++ b/examples/sql/masterdetail/masterdetail.pro @@ -0,0 +1,16 @@ +HEADERS = database.h \ + dialog.h \ + mainwindow.h +RESOURCES = masterdetail.qrc +SOURCES = dialog.cpp \ + main.cpp \ + mainwindow.cpp + +QT += sql +QT += xml + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/sql/masterdetail +sources.files = $$SOURCES *.h $$RESOURCES $$FORMS masterdetail.pro *.xml images +sources.path = $$[QT_INSTALL_EXAMPLES]/sql/masterdetail +INSTALLS += target sources diff --git a/examples/sql/masterdetail/masterdetail.qrc b/examples/sql/masterdetail/masterdetail.qrc new file mode 100644 index 0000000..717c2eb --- /dev/null +++ b/examples/sql/masterdetail/masterdetail.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> + <qresource> + <file>images/icon.png</file> + <file>images/image.png</file> + </qresource> +</RCC> |