1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the examples of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
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 https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "dialog.h" |
52 | |
53 | int uniqueAlbumId; |
54 | int uniqueArtistId; |
55 | |
56 | Dialog::Dialog(QSqlRelationalTableModel *albums, QDomDocument details, |
57 | QFile *output, QWidget *parent) |
58 | : QDialog(parent) |
59 | { |
60 | model = albums; |
61 | albumDetails = details; |
62 | outputFile = output; |
63 | |
64 | QGroupBox *inputWidgetBox = createInputWidgets(); |
65 | QDialogButtonBox *buttonBox = createButtons(); |
66 | |
67 | QVBoxLayout *layout = new QVBoxLayout; |
68 | layout->addWidget(inputWidgetBox); |
69 | layout->addWidget(buttonBox); |
70 | setLayout(layout); |
71 | |
72 | setWindowTitle(tr(s: "Add Album" )); |
73 | } |
74 | |
75 | void Dialog::submit() |
76 | { |
77 | QString artist = artistEditor->text(); |
78 | QString title = titleEditor->text(); |
79 | |
80 | if (artist.isEmpty() || title.isEmpty()) { |
81 | QString message(tr(s: "Please provide both the name of the artist " |
82 | "and the title of the album." )); |
83 | QMessageBox::information(parent: this, title: tr(s: "Add Album" ), text: message); |
84 | } else { |
85 | int artistId = findArtistId(artist); |
86 | int albumId = addNewAlbum(title, artistId); |
87 | |
88 | QStringList tracks; |
89 | tracks = tracksEditor->text().split(sep: QLatin1Char(','), behavior: Qt::SkipEmptyParts); |
90 | addTracks(albumId, tracks); |
91 | |
92 | increaseAlbumCount(artistIndex: indexOfArtist(artist)); |
93 | accept(); |
94 | } |
95 | } |
96 | |
97 | int Dialog::findArtistId(const QString &artist) |
98 | { |
99 | QSqlTableModel *artistModel = model->relationModel(column: 2); |
100 | int row = 0; |
101 | |
102 | while (row < artistModel->rowCount()) { |
103 | QSqlRecord record = artistModel->record(row); |
104 | if (record.value(name: "artist" ) == artist) |
105 | return record.value(name: "id" ).toInt(); |
106 | else |
107 | row++; |
108 | } |
109 | return addNewArtist(name: artist); |
110 | } |
111 | |
112 | |
113 | int Dialog::addNewArtist(const QString &name) |
114 | { |
115 | QSqlTableModel *artistModel = model->relationModel(column: 2); |
116 | QSqlRecord record; |
117 | |
118 | int id = generateArtistId(); |
119 | |
120 | QSqlField f1("id" , QVariant::Int); |
121 | QSqlField f2("artist" , QVariant::String); |
122 | QSqlField f3("albumcount" , QVariant::Int); |
123 | |
124 | f1.setValue(QVariant(id)); |
125 | f2.setValue(QVariant(name)); |
126 | f3.setValue(QVariant(0)); |
127 | record.append(field: f1); |
128 | record.append(field: f2); |
129 | record.append(field: f3); |
130 | |
131 | artistModel->insertRecord(row: -1, record); |
132 | return id; |
133 | } |
134 | |
135 | int Dialog::addNewAlbum(const QString &title, int artistId) |
136 | { |
137 | int id = generateAlbumId(); |
138 | QSqlRecord record; |
139 | |
140 | QSqlField f1("albumid" , QVariant::Int); |
141 | QSqlField f2("title" , QVariant::String); |
142 | QSqlField f3("artistid" , QVariant::Int); |
143 | QSqlField f4("year" , QVariant::Int); |
144 | |
145 | f1.setValue(QVariant(id)); |
146 | f2.setValue(QVariant(title)); |
147 | f3.setValue(QVariant(artistId)); |
148 | f4.setValue(QVariant(yearEditor->value())); |
149 | record.append(field: f1); |
150 | record.append(field: f2); |
151 | record.append(field: f3); |
152 | record.append(field: f4); |
153 | |
154 | model->insertRecord(row: -1, record); |
155 | return id; |
156 | } |
157 | |
158 | void Dialog::addTracks(int albumId, const QStringList &tracks) |
159 | { |
160 | QDomElement albumNode = albumDetails.createElement(tagName: "album" ); |
161 | albumNode.setAttribute(name: "id" , value: albumId); |
162 | |
163 | for (int i = 0; i < tracks.count(); ++i) { |
164 | QString trackNumber = QString::number(i); |
165 | if (i < 10) |
166 | trackNumber.prepend(c: '0'); |
167 | |
168 | QDomText textNode = albumDetails.createTextNode(data: tracks.at(i)); |
169 | |
170 | QDomElement trackNode = albumDetails.createElement(tagName: "track" ); |
171 | trackNode.setAttribute(name: "number" , value: trackNumber); |
172 | trackNode.appendChild(newChild: textNode); |
173 | |
174 | albumNode.appendChild(newChild: trackNode); |
175 | } |
176 | |
177 | QDomNodeList archive = albumDetails.elementsByTagName(tagname: "archive" ); |
178 | archive.item(index: 0).appendChild(newChild: albumNode); |
179 | |
180 | /* |
181 | The following code is commented out since the example uses an in |
182 | memory database, i.e., altering the XML file will bring the data |
183 | out of sync. |
184 | |
185 | if (!outputFile->open(QIODevice::WriteOnly)) { |
186 | return; |
187 | } else { |
188 | QTextStream stream(outputFile); |
189 | archive.item(0).save(stream, 4); |
190 | outputFile->close(); |
191 | } |
192 | */ |
193 | } |
194 | |
195 | void Dialog::increaseAlbumCount(QModelIndex artistIndex) |
196 | { |
197 | QSqlTableModel *artistModel = model->relationModel(column: 2); |
198 | |
199 | QModelIndex albumCountIndex; |
200 | albumCountIndex = artistIndex.sibling(arow: artistIndex.row(), acolumn: 2); |
201 | |
202 | int albumCount = albumCountIndex.data().toInt(); |
203 | artistModel->setData(index: albumCountIndex, value: QVariant(albumCount + 1)); |
204 | } |
205 | |
206 | |
207 | void Dialog::revert() |
208 | { |
209 | artistEditor->clear(); |
210 | titleEditor->clear(); |
211 | yearEditor->setValue(QDate::currentDate().year()); |
212 | tracksEditor->clear(); |
213 | } |
214 | |
215 | QGroupBox *Dialog::createInputWidgets() |
216 | { |
217 | QGroupBox *box = new QGroupBox(tr(s: "Add Album" )); |
218 | |
219 | QLabel *artistLabel = new QLabel(tr(s: "Artist:" )); |
220 | QLabel *titleLabel = new QLabel(tr(s: "Title:" )); |
221 | QLabel *yearLabel = new QLabel(tr(s: "Year:" )); |
222 | QLabel *tracksLabel = new QLabel(tr(s: "Tracks (separated by comma):" )); |
223 | |
224 | artistEditor = new QLineEdit; |
225 | titleEditor = new QLineEdit; |
226 | |
227 | yearEditor = new QSpinBox; |
228 | yearEditor->setMinimum(1900); |
229 | yearEditor->setMaximum(QDate::currentDate().year()); |
230 | yearEditor->setValue(yearEditor->maximum()); |
231 | yearEditor->setReadOnly(false); |
232 | |
233 | tracksEditor = new QLineEdit; |
234 | |
235 | QGridLayout *layout = new QGridLayout; |
236 | layout->addWidget(artistLabel, row: 0, column: 0); |
237 | layout->addWidget(artistEditor, row: 0, column: 1); |
238 | layout->addWidget(titleLabel, row: 1, column: 0); |
239 | layout->addWidget(titleEditor, row: 1, column: 1); |
240 | layout->addWidget(yearLabel, row: 2, column: 0); |
241 | layout->addWidget(yearEditor, row: 2, column: 1); |
242 | layout->addWidget(tracksLabel, row: 3, column: 0, rowSpan: 1, columnSpan: 2); |
243 | layout->addWidget(tracksEditor, row: 4, column: 0, rowSpan: 1, columnSpan: 2); |
244 | box->setLayout(layout); |
245 | |
246 | return box; |
247 | } |
248 | |
249 | QDialogButtonBox *Dialog::createButtons() |
250 | { |
251 | QPushButton *closeButton = new QPushButton(tr(s: "&Close" )); |
252 | QPushButton *revertButton = new QPushButton(tr(s: "&Revert" )); |
253 | QPushButton *submitButton = new QPushButton(tr(s: "&Submit" )); |
254 | |
255 | closeButton->setDefault(true); |
256 | |
257 | connect(sender: closeButton, signal: &QPushButton::clicked, receiver: this, slot: &Dialog::close); |
258 | connect(sender: revertButton, signal: &QPushButton::clicked, receiver: this, slot: &Dialog::revert); |
259 | connect(sender: submitButton, signal: &QPushButton::clicked, receiver: this, slot: &Dialog::submit); |
260 | |
261 | QDialogButtonBox *buttonBox = new QDialogButtonBox; |
262 | buttonBox->addButton(button: submitButton, role: QDialogButtonBox::ResetRole); |
263 | buttonBox->addButton(button: revertButton, role: QDialogButtonBox::ResetRole); |
264 | buttonBox->addButton(button: closeButton, role: QDialogButtonBox::RejectRole); |
265 | |
266 | return buttonBox; |
267 | } |
268 | |
269 | QModelIndex Dialog::indexOfArtist(const QString &artist) |
270 | { |
271 | QSqlTableModel *artistModel = model->relationModel(column: 2); |
272 | |
273 | for (int i = 0; i < artistModel->rowCount(); ++i) { |
274 | QSqlRecord record = artistModel->record(row: i); |
275 | if (record.value(name: "artist" ) == artist) |
276 | return artistModel->index(row: i, column: 1); |
277 | } |
278 | |
279 | return QModelIndex(); |
280 | } |
281 | |
282 | int Dialog::generateArtistId() |
283 | { |
284 | uniqueArtistId += 1; |
285 | return uniqueArtistId; |
286 | } |
287 | |
288 | int Dialog::generateAlbumId() |
289 | { |
290 | uniqueAlbumId += 1; |
291 | return uniqueAlbumId; |
292 | } |
293 | |