Chris@225
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@225
|
2
|
Chris@225
|
3 /*
|
Chris@225
|
4 Sonic Visualiser
|
Chris@225
|
5 An audio file viewer and annotation editor.
|
Chris@225
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@225
|
7 This file copyright 2007 QMUL.
|
Chris@225
|
8
|
Chris@225
|
9 This program is free software; you can redistribute it and/or
|
Chris@225
|
10 modify it under the terms of the GNU General Public License as
|
Chris@225
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@225
|
12 License, or (at your option) any later version. See the file
|
Chris@225
|
13 COPYING included with this distribution for more information.
|
Chris@225
|
14 */
|
Chris@225
|
15
|
Chris@225
|
16 #include "TipDialog.h"
|
Chris@225
|
17
|
Chris@225
|
18 #include <QLabel>
|
Chris@225
|
19 #include <QPushButton>
|
Chris@225
|
20 #include <QSettings>
|
Chris@225
|
21 #include <QLabel>
|
Chris@225
|
22 #include <QLocale>
|
Chris@225
|
23 #include <QXmlInputSource>
|
Chris@225
|
24 #include <QFileInfo>
|
Chris@225
|
25 #include <QGridLayout>
|
Chris@225
|
26 #include <QGroupBox>
|
Chris@228
|
27 #include <QCheckBox>
|
Chris@225
|
28
|
Chris@225
|
29 #include <iostream>
|
Chris@225
|
30
|
Chris@225
|
31 TipDialog::TipDialog(QWidget *parent, Qt::WFlags flags) :
|
Chris@225
|
32 QDialog(parent, flags),
|
Chris@225
|
33 m_tipNumber(0),
|
Chris@225
|
34 m_label(0),
|
Chris@225
|
35 m_caption(tr("Tip of the Day"))
|
Chris@225
|
36 {
|
Chris@225
|
37 readTips();
|
Chris@225
|
38
|
Chris@225
|
39 QSettings settings;
|
Chris@225
|
40 settings.beginGroup("TipOfTheDay");
|
Chris@225
|
41
|
Chris@225
|
42 if (!settings.value("showonstartup", true).toBool()) return;
|
Chris@225
|
43
|
Chris@225
|
44 m_tipNumber = settings.value("nexttip", 0).toInt();
|
Chris@225
|
45
|
Chris@225
|
46 setWindowTitle(m_caption);
|
Chris@225
|
47
|
Chris@225
|
48 QGridLayout *grid = new QGridLayout;
|
Chris@225
|
49 setLayout(grid);
|
Chris@225
|
50
|
Chris@225
|
51 QGroupBox *groupBox = new QGroupBox;
|
Chris@228
|
52 // groupBox->setTitle(m_caption);
|
Chris@225
|
53 grid->addWidget(groupBox, 0, 0);
|
Chris@225
|
54
|
Chris@225
|
55 QGridLayout *subgrid = new QGridLayout;
|
Chris@225
|
56 groupBox->setLayout(subgrid);
|
Chris@225
|
57
|
Chris@225
|
58 m_label = new QLabel;
|
Chris@225
|
59 subgrid->addWidget(m_label, 0, 0);
|
Chris@228
|
60 m_label->setWordWrap(true);
|
Chris@225
|
61
|
Chris@225
|
62 QHBoxLayout *hbox = new QHBoxLayout;
|
Chris@225
|
63 grid->addLayout(hbox, 1, 0);
|
Chris@228
|
64
|
Chris@228
|
65 QCheckBox *show = new QCheckBox(tr("Show tips on startup"));
|
Chris@228
|
66 hbox->addWidget(show);
|
Chris@228
|
67
|
Chris@228
|
68 hbox->addStretch(10);
|
Chris@228
|
69
|
Chris@228
|
70 QPushButton *prev = new QPushButton(tr("<< Previous"));
|
Chris@228
|
71 hbox->addWidget(prev);
|
Chris@228
|
72 connect(prev, SIGNAL(clicked()), this, SLOT(previous()));
|
Chris@228
|
73
|
Chris@228
|
74 QPushButton *next = new QPushButton(tr("Next >>"));
|
Chris@228
|
75 hbox->addWidget(next);
|
Chris@228
|
76 connect(next, SIGNAL(clicked()), this, SLOT(next()));
|
Chris@225
|
77
|
Chris@225
|
78 QPushButton *close = new QPushButton(tr("Close"));
|
Chris@225
|
79 hbox->addWidget(close);
|
Chris@225
|
80 connect(close, SIGNAL(clicked()), this, SLOT(accept()));
|
Chris@225
|
81
|
Chris@228
|
82 close->setDefault(true);
|
Chris@228
|
83
|
Chris@225
|
84 showTip();
|
Chris@225
|
85 }
|
Chris@225
|
86
|
Chris@225
|
87 TipDialog::~TipDialog()
|
Chris@225
|
88 {
|
Chris@225
|
89 }
|
Chris@225
|
90
|
Chris@225
|
91 void
|
Chris@225
|
92 TipDialog::next()
|
Chris@225
|
93 {
|
Chris@225
|
94 if (++m_tipNumber >= int(m_tips.size())) {
|
Chris@225
|
95 //!!! The tips file should define where we loop back to -- the
|
Chris@225
|
96 // first one at least is likely to be a generic welcome message
|
Chris@225
|
97 m_tipNumber = 0;
|
Chris@225
|
98 }
|
Chris@225
|
99
|
Chris@225
|
100 showTip();
|
Chris@225
|
101 }
|
Chris@225
|
102
|
Chris@225
|
103 void
|
Chris@225
|
104 TipDialog::previous()
|
Chris@225
|
105 {
|
Chris@225
|
106 if (--m_tipNumber < 0) {
|
Chris@225
|
107 m_tipNumber = m_tips.size() - 1;
|
Chris@225
|
108 }
|
Chris@225
|
109
|
Chris@225
|
110 showTip();
|
Chris@225
|
111 }
|
Chris@225
|
112
|
Chris@225
|
113 void
|
Chris@225
|
114 TipDialog::readTips()
|
Chris@225
|
115 {
|
Chris@225
|
116 std::cerr << "TipDialog::readTips" << std::endl;
|
Chris@225
|
117
|
Chris@225
|
118 QString language = QLocale::system().name();
|
Chris@225
|
119 QString filename = QString(":i18n/tips_%1.xml").arg(language);
|
Chris@225
|
120
|
Chris@225
|
121 if (!QFileInfo(filename).exists()) {
|
Chris@225
|
122
|
Chris@225
|
123 QString base = language.section('_', 0, 0);
|
Chris@225
|
124 filename = QString(":i18n/tips_%1.xml").arg(base);
|
Chris@225
|
125
|
Chris@225
|
126 if (!QFileInfo(filename).exists()) {
|
Chris@225
|
127
|
Chris@225
|
128 filename = QString(":i18n/tips.xml");
|
Chris@225
|
129
|
Chris@225
|
130 if (!QFileInfo(filename).exists()) return;
|
Chris@225
|
131 }
|
Chris@225
|
132 }
|
Chris@225
|
133
|
Chris@225
|
134 QFile file(filename);
|
Chris@225
|
135
|
Chris@225
|
136 std::cerr << "TipDialog::readTips from " << filename.toStdString() << std::endl;
|
Chris@225
|
137
|
Chris@225
|
138 QXmlInputSource source(&file);
|
Chris@225
|
139
|
Chris@225
|
140 TipFileParser parser(this);
|
Chris@225
|
141 parser.parse(source);
|
Chris@225
|
142 }
|
Chris@225
|
143
|
Chris@225
|
144 void
|
Chris@225
|
145 TipDialog::showTip()
|
Chris@225
|
146 {
|
Chris@225
|
147 if (m_tipNumber < int(m_tips.size())) {
|
Chris@225
|
148 std::cerr << "Tip " << m_tipNumber << " is: " << m_tips[m_tipNumber].toStdString() << std::endl;
|
Chris@225
|
149 m_label->setText(m_tips[m_tipNumber]);
|
Chris@225
|
150 } else {
|
Chris@225
|
151 accept();
|
Chris@225
|
152 }
|
Chris@225
|
153
|
Chris@225
|
154 int tn = m_tipNumber;
|
Chris@225
|
155 if (++tn >= int(m_tips.size())) tn = 0; //!!! as above
|
Chris@225
|
156
|
Chris@225
|
157 QSettings settings;
|
Chris@225
|
158 settings.beginGroup("TipOfTheDay");
|
Chris@225
|
159 settings.setValue("nexttip", tn);
|
Chris@225
|
160 }
|
Chris@225
|
161
|
Chris@225
|
162 TipDialog::TipFileParser::TipFileParser(TipDialog *dialog) :
|
Chris@225
|
163 m_dialog(dialog),
|
Chris@225
|
164 m_inTip(false),
|
Chris@228
|
165 m_inText(false),
|
Chris@228
|
166 m_inHtml(false)
|
Chris@225
|
167 {
|
Chris@225
|
168 }
|
Chris@225
|
169
|
Chris@225
|
170 TipDialog::TipFileParser::~TipFileParser()
|
Chris@225
|
171 {
|
Chris@225
|
172 }
|
Chris@225
|
173
|
Chris@225
|
174 void
|
Chris@225
|
175 TipDialog::TipFileParser::parse(QXmlInputSource &source)
|
Chris@225
|
176 {
|
Chris@225
|
177 QXmlSimpleReader reader;
|
Chris@225
|
178 reader.setContentHandler(this);
|
Chris@225
|
179 reader.setErrorHandler(this);
|
Chris@225
|
180 reader.parse(source);
|
Chris@225
|
181 }
|
Chris@225
|
182
|
Chris@225
|
183 bool
|
Chris@225
|
184 TipDialog::TipFileParser::startElement(const QString &, const QString &,
|
Chris@225
|
185 const QString &qName,
|
Chris@225
|
186 const QXmlAttributes &attributes)
|
Chris@225
|
187 {
|
Chris@225
|
188 QString name = qName.toLower();
|
Chris@225
|
189
|
Chris@225
|
190 std::cerr << "TipFileParser::startElement(" << name.toStdString() << ")" << std::endl;
|
Chris@225
|
191
|
Chris@225
|
192 if (name == "tips") {
|
Chris@225
|
193 QString caption = attributes.value("caption");
|
Chris@225
|
194 std::cerr << "TipFileParser::caption = " << caption.toStdString() << std::endl;
|
Chris@225
|
195 if (caption != "") m_dialog->m_caption = caption;
|
Chris@225
|
196 } else if (name == "tip") {
|
Chris@225
|
197 if (m_inTip) {
|
Chris@225
|
198 std::cerr << "WARNING: TipFileParser: nested <tip> elements" << std::endl;
|
Chris@225
|
199 }
|
Chris@225
|
200 m_inTip = true;
|
Chris@225
|
201 } else if (name == "text") {
|
Chris@225
|
202 if (m_inTip) {
|
Chris@225
|
203 m_inText = true;
|
Chris@225
|
204 std::cerr << "TipFileParser: adding new tip" << std::endl;
|
Chris@225
|
205 m_dialog->m_tips.push_back("");
|
Chris@225
|
206 } else {
|
Chris@225
|
207 std::cerr << "WARNING: TipFileParser: <text> outside <tip> element" << std::endl;
|
Chris@225
|
208 }
|
Chris@228
|
209 } else if (name == "html") {
|
Chris@228
|
210 if (m_inTip) {
|
Chris@228
|
211 m_inHtml = true;
|
Chris@228
|
212 std::cerr << "TipFileParser: adding new tip" << std::endl;
|
Chris@228
|
213 m_dialog->m_tips.push_back("");
|
Chris@228
|
214 } else {
|
Chris@228
|
215 std::cerr << "WARNING: TipFileParser: <html> outside <tip> element" << std::endl;
|
Chris@228
|
216 }
|
Chris@228
|
217 } else if (m_inHtml) {
|
Chris@228
|
218 m_dialog->m_tips[m_dialog->m_tips.size()-1] += "<" + qName;
|
Chris@228
|
219 for (int i = 0; i < attributes.count(); ++i) {
|
Chris@228
|
220 m_dialog->m_tips[m_dialog->m_tips.size()-1] +=
|
Chris@228
|
221 " " + attributes.qName(i) + "=\"" + attributes.value(i) + "\"";
|
Chris@228
|
222 }
|
Chris@228
|
223 m_dialog->m_tips[m_dialog->m_tips.size()-1] += ">";
|
Chris@225
|
224 }
|
Chris@225
|
225
|
Chris@225
|
226 std::cerr << "TipFileParser::startElement done" << std::endl;
|
Chris@225
|
227 return true;
|
Chris@225
|
228 }
|
Chris@225
|
229
|
Chris@225
|
230 bool
|
Chris@225
|
231 TipDialog::TipFileParser::endElement(const QString &, const QString &,
|
Chris@225
|
232 const QString &qName)
|
Chris@225
|
233 {
|
Chris@225
|
234 QString name = qName.toLower();
|
Chris@225
|
235
|
Chris@225
|
236 if (name == "text") {
|
Chris@228
|
237 if (!m_inText) {
|
Chris@225
|
238 std::cerr << "WARNING: TipFileParser: </text> without <text>" << std::endl;
|
Chris@225
|
239 }
|
Chris@225
|
240 m_inText = false;
|
Chris@228
|
241 } else if (name == "html") {
|
Chris@228
|
242 if (!m_inHtml) {
|
Chris@228
|
243 std::cerr << "WARNING: TipFileParser: </html> without <html>" << std::endl;
|
Chris@228
|
244 }
|
Chris@228
|
245 m_inHtml = false;
|
Chris@225
|
246 } else if (name == "tip") {
|
Chris@225
|
247 if (m_inText) {
|
Chris@225
|
248 std::cerr << "WARNING: TipFileParser: <text> without </text>" << std::endl;
|
Chris@228
|
249 } else if (m_inHtml) {
|
Chris@228
|
250 std::cerr << "WARNING: TipFileParser: <html> without </html>" << std::endl;
|
Chris@225
|
251 } else if (!m_inTip) {
|
Chris@225
|
252 std::cerr << "WARNING: TipFileParser: </tip> without <tip>" << std::endl;
|
Chris@225
|
253 }
|
Chris@225
|
254 m_inTip = false;
|
Chris@228
|
255 } else if (m_inHtml) {
|
Chris@228
|
256 m_dialog->m_tips[m_dialog->m_tips.size()-1] += "</" + qName + ">";
|
Chris@225
|
257 }
|
Chris@225
|
258
|
Chris@225
|
259 return true;
|
Chris@225
|
260 }
|
Chris@225
|
261
|
Chris@225
|
262 bool
|
Chris@225
|
263 TipDialog::TipFileParser::characters(const QString &text)
|
Chris@225
|
264 {
|
Chris@225
|
265 std::cerr << "TipFileParser::characters(" << text.toStdString() << ")" << std::endl;
|
Chris@225
|
266
|
Chris@228
|
267 if (m_inText || m_inHtml) {
|
Chris@225
|
268 m_dialog->m_tips[m_dialog->m_tips.size()-1] += text;
|
Chris@225
|
269 }
|
Chris@225
|
270
|
Chris@225
|
271 return true;
|
Chris@225
|
272 }
|
Chris@225
|
273
|
Chris@225
|
274 bool
|
Chris@225
|
275 TipDialog::TipFileParser::error(const QXmlParseException &exception)
|
Chris@225
|
276 {
|
Chris@225
|
277 QString errorString =
|
Chris@225
|
278 QString("ERROR: TipFileParser: %1 at line %2, column %3")
|
Chris@225
|
279 .arg(exception.message())
|
Chris@225
|
280 .arg(exception.lineNumber())
|
Chris@225
|
281 .arg(exception.columnNumber());
|
Chris@225
|
282 std::cerr << errorString.toStdString() << std::endl;
|
Chris@225
|
283 return QXmlDefaultHandler::error(exception);
|
Chris@225
|
284 }
|
Chris@225
|
285
|
Chris@225
|
286 bool
|
Chris@225
|
287 TipDialog::TipFileParser::fatalError(const QXmlParseException &exception)
|
Chris@225
|
288 {
|
Chris@225
|
289 QString errorString =
|
Chris@225
|
290 QString("FATAL ERROR: TipFileParser: %1 at line %2, column %3")
|
Chris@225
|
291 .arg(exception.message())
|
Chris@225
|
292 .arg(exception.lineNumber())
|
Chris@225
|
293 .arg(exception.columnNumber());
|
Chris@225
|
294 std::cerr << errorString.toStdString() << std::endl;
|
Chris@225
|
295 return QXmlDefaultHandler::fatalError(exception);
|
Chris@225
|
296 }
|