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@229
|
65 QCheckBox *show = new QCheckBox(tr("Show tip on startup"));
|
Chris@228
|
66 hbox->addWidget(show);
|
Chris@228
|
67
|
Chris@229
|
68 hbox->addSpacing(20);
|
Chris@228
|
69 hbox->addStretch(10);
|
Chris@228
|
70
|
Chris@228
|
71 QPushButton *prev = new QPushButton(tr("<< Previous"));
|
Chris@228
|
72 hbox->addWidget(prev);
|
Chris@228
|
73 connect(prev, SIGNAL(clicked()), this, SLOT(previous()));
|
Chris@228
|
74
|
Chris@228
|
75 QPushButton *next = new QPushButton(tr("Next >>"));
|
Chris@228
|
76 hbox->addWidget(next);
|
Chris@228
|
77 connect(next, SIGNAL(clicked()), this, SLOT(next()));
|
Chris@225
|
78
|
Chris@225
|
79 QPushButton *close = new QPushButton(tr("Close"));
|
Chris@225
|
80 hbox->addWidget(close);
|
Chris@225
|
81 connect(close, SIGNAL(clicked()), this, SLOT(accept()));
|
Chris@225
|
82
|
Chris@228
|
83 close->setDefault(true);
|
Chris@228
|
84
|
Chris@225
|
85 showTip();
|
Chris@225
|
86 }
|
Chris@225
|
87
|
Chris@225
|
88 TipDialog::~TipDialog()
|
Chris@225
|
89 {
|
Chris@225
|
90 }
|
Chris@225
|
91
|
Chris@225
|
92 void
|
Chris@225
|
93 TipDialog::next()
|
Chris@225
|
94 {
|
Chris@225
|
95 if (++m_tipNumber >= int(m_tips.size())) {
|
Chris@225
|
96 //!!! The tips file should define where we loop back to -- the
|
Chris@225
|
97 // first one at least is likely to be a generic welcome message
|
Chris@225
|
98 m_tipNumber = 0;
|
Chris@225
|
99 }
|
Chris@225
|
100
|
Chris@225
|
101 showTip();
|
Chris@225
|
102 }
|
Chris@225
|
103
|
Chris@225
|
104 void
|
Chris@225
|
105 TipDialog::previous()
|
Chris@225
|
106 {
|
Chris@225
|
107 if (--m_tipNumber < 0) {
|
Chris@225
|
108 m_tipNumber = m_tips.size() - 1;
|
Chris@225
|
109 }
|
Chris@225
|
110
|
Chris@225
|
111 showTip();
|
Chris@225
|
112 }
|
Chris@225
|
113
|
Chris@225
|
114 void
|
Chris@225
|
115 TipDialog::readTips()
|
Chris@225
|
116 {
|
Chris@585
|
117 DEBUG << "TipDialog::readTips" << endl;
|
Chris@225
|
118
|
Chris@225
|
119 QString language = QLocale::system().name();
|
Chris@225
|
120 QString filename = QString(":i18n/tips_%1.xml").arg(language);
|
Chris@225
|
121
|
Chris@225
|
122 if (!QFileInfo(filename).exists()) {
|
Chris@225
|
123
|
Chris@225
|
124 QString base = language.section('_', 0, 0);
|
Chris@225
|
125 filename = QString(":i18n/tips_%1.xml").arg(base);
|
Chris@225
|
126
|
Chris@225
|
127 if (!QFileInfo(filename).exists()) {
|
Chris@225
|
128
|
Chris@225
|
129 filename = QString(":i18n/tips.xml");
|
Chris@225
|
130
|
Chris@225
|
131 if (!QFileInfo(filename).exists()) return;
|
Chris@225
|
132 }
|
Chris@225
|
133 }
|
Chris@225
|
134
|
Chris@225
|
135 QFile file(filename);
|
Chris@225
|
136
|
Chris@585
|
137 DEBUG << "TipDialog::readTips from " << filename << endl;
|
Chris@225
|
138
|
Chris@225
|
139 QXmlInputSource source(&file);
|
Chris@225
|
140
|
Chris@225
|
141 TipFileParser parser(this);
|
Chris@225
|
142 parser.parse(source);
|
Chris@225
|
143 }
|
Chris@225
|
144
|
Chris@225
|
145 void
|
Chris@225
|
146 TipDialog::showTip()
|
Chris@225
|
147 {
|
Chris@225
|
148 if (m_tipNumber < int(m_tips.size())) {
|
Chris@584
|
149 std::cerr << "Tip " << m_tipNumber << " is: " << m_tips[m_tipNumber] << std::endl;
|
Chris@225
|
150 m_label->setText(m_tips[m_tipNumber]);
|
Chris@225
|
151 } else {
|
Chris@225
|
152 accept();
|
Chris@225
|
153 }
|
Chris@225
|
154
|
Chris@225
|
155 int tn = m_tipNumber;
|
Chris@225
|
156 if (++tn >= int(m_tips.size())) tn = 0; //!!! as above
|
Chris@225
|
157
|
Chris@225
|
158 QSettings settings;
|
Chris@225
|
159 settings.beginGroup("TipOfTheDay");
|
Chris@225
|
160 settings.setValue("nexttip", tn);
|
Chris@225
|
161 }
|
Chris@225
|
162
|
Chris@225
|
163 TipDialog::TipFileParser::TipFileParser(TipDialog *dialog) :
|
Chris@225
|
164 m_dialog(dialog),
|
Chris@225
|
165 m_inTip(false),
|
Chris@228
|
166 m_inText(false),
|
Chris@228
|
167 m_inHtml(false)
|
Chris@225
|
168 {
|
Chris@225
|
169 }
|
Chris@225
|
170
|
Chris@225
|
171 TipDialog::TipFileParser::~TipFileParser()
|
Chris@225
|
172 {
|
Chris@225
|
173 }
|
Chris@225
|
174
|
Chris@225
|
175 void
|
Chris@225
|
176 TipDialog::TipFileParser::parse(QXmlInputSource &source)
|
Chris@225
|
177 {
|
Chris@225
|
178 QXmlSimpleReader reader;
|
Chris@225
|
179 reader.setContentHandler(this);
|
Chris@225
|
180 reader.setErrorHandler(this);
|
Chris@225
|
181 reader.parse(source);
|
Chris@225
|
182 }
|
Chris@225
|
183
|
Chris@225
|
184 bool
|
Chris@225
|
185 TipDialog::TipFileParser::startElement(const QString &, const QString &,
|
Chris@225
|
186 const QString &qName,
|
Chris@225
|
187 const QXmlAttributes &attributes)
|
Chris@225
|
188 {
|
Chris@225
|
189 QString name = qName.toLower();
|
Chris@225
|
190
|
Chris@585
|
191 DEBUG << "TipFileParser::startElement(" << name << ")" << endl;
|
Chris@225
|
192
|
Chris@225
|
193 if (name == "tips") {
|
Chris@225
|
194 QString caption = attributes.value("caption");
|
Chris@585
|
195 DEBUG << "TipFileParser::caption = " << caption << endl;
|
Chris@225
|
196 if (caption != "") m_dialog->m_caption = caption;
|
Chris@225
|
197 } else if (name == "tip") {
|
Chris@225
|
198 if (m_inTip) {
|
Chris@225
|
199 std::cerr << "WARNING: TipFileParser: nested <tip> elements" << std::endl;
|
Chris@225
|
200 }
|
Chris@225
|
201 m_inTip = true;
|
Chris@225
|
202 } else if (name == "text") {
|
Chris@225
|
203 if (m_inTip) {
|
Chris@225
|
204 m_inText = true;
|
Chris@225
|
205 std::cerr << "TipFileParser: adding new tip" << std::endl;
|
Chris@225
|
206 m_dialog->m_tips.push_back("");
|
Chris@225
|
207 } else {
|
Chris@225
|
208 std::cerr << "WARNING: TipFileParser: <text> outside <tip> element" << std::endl;
|
Chris@225
|
209 }
|
Chris@228
|
210 } else if (name == "html") {
|
Chris@228
|
211 if (m_inTip) {
|
Chris@228
|
212 m_inHtml = true;
|
Chris@228
|
213 std::cerr << "TipFileParser: adding new tip" << std::endl;
|
Chris@228
|
214 m_dialog->m_tips.push_back("");
|
Chris@228
|
215 } else {
|
Chris@228
|
216 std::cerr << "WARNING: TipFileParser: <html> outside <tip> element" << std::endl;
|
Chris@228
|
217 }
|
Chris@228
|
218 } else if (m_inHtml) {
|
Chris@228
|
219 m_dialog->m_tips[m_dialog->m_tips.size()-1] += "<" + qName;
|
Chris@228
|
220 for (int i = 0; i < attributes.count(); ++i) {
|
Chris@228
|
221 m_dialog->m_tips[m_dialog->m_tips.size()-1] +=
|
Chris@228
|
222 " " + attributes.qName(i) + "=\"" + attributes.value(i) + "\"";
|
Chris@228
|
223 }
|
Chris@228
|
224 m_dialog->m_tips[m_dialog->m_tips.size()-1] += ">";
|
Chris@225
|
225 }
|
Chris@225
|
226
|
Chris@585
|
227 DEBUG << "TipFileParser::startElement done" << endl;
|
Chris@225
|
228 return true;
|
Chris@225
|
229 }
|
Chris@225
|
230
|
Chris@225
|
231 bool
|
Chris@225
|
232 TipDialog::TipFileParser::endElement(const QString &, const QString &,
|
Chris@225
|
233 const QString &qName)
|
Chris@225
|
234 {
|
Chris@225
|
235 QString name = qName.toLower();
|
Chris@225
|
236
|
Chris@225
|
237 if (name == "text") {
|
Chris@228
|
238 if (!m_inText) {
|
Chris@225
|
239 std::cerr << "WARNING: TipFileParser: </text> without <text>" << std::endl;
|
Chris@225
|
240 }
|
Chris@225
|
241 m_inText = false;
|
Chris@228
|
242 } else if (name == "html") {
|
Chris@228
|
243 if (!m_inHtml) {
|
Chris@228
|
244 std::cerr << "WARNING: TipFileParser: </html> without <html>" << std::endl;
|
Chris@228
|
245 }
|
Chris@228
|
246 m_inHtml = false;
|
Chris@225
|
247 } else if (name == "tip") {
|
Chris@225
|
248 if (m_inText) {
|
Chris@225
|
249 std::cerr << "WARNING: TipFileParser: <text> without </text>" << std::endl;
|
Chris@228
|
250 } else if (m_inHtml) {
|
Chris@228
|
251 std::cerr << "WARNING: TipFileParser: <html> without </html>" << std::endl;
|
Chris@225
|
252 } else if (!m_inTip) {
|
Chris@225
|
253 std::cerr << "WARNING: TipFileParser: </tip> without <tip>" << std::endl;
|
Chris@225
|
254 }
|
Chris@225
|
255 m_inTip = false;
|
Chris@228
|
256 } else if (m_inHtml) {
|
Chris@228
|
257 m_dialog->m_tips[m_dialog->m_tips.size()-1] += "</" + qName + ">";
|
Chris@225
|
258 }
|
Chris@225
|
259
|
Chris@225
|
260 return true;
|
Chris@225
|
261 }
|
Chris@225
|
262
|
Chris@225
|
263 bool
|
Chris@225
|
264 TipDialog::TipFileParser::characters(const QString &text)
|
Chris@225
|
265 {
|
Chris@585
|
266 DEBUG << "TipFileParser::characters(" << text << ")" << endl;
|
Chris@225
|
267
|
Chris@228
|
268 if (m_inText || m_inHtml) {
|
Chris@225
|
269 m_dialog->m_tips[m_dialog->m_tips.size()-1] += text;
|
Chris@225
|
270 }
|
Chris@225
|
271
|
Chris@225
|
272 return true;
|
Chris@225
|
273 }
|
Chris@225
|
274
|
Chris@225
|
275 bool
|
Chris@225
|
276 TipDialog::TipFileParser::error(const QXmlParseException &exception)
|
Chris@225
|
277 {
|
Chris@225
|
278 QString errorString =
|
Chris@225
|
279 QString("ERROR: TipFileParser: %1 at line %2, column %3")
|
Chris@225
|
280 .arg(exception.message())
|
Chris@225
|
281 .arg(exception.lineNumber())
|
Chris@225
|
282 .arg(exception.columnNumber());
|
Chris@584
|
283 std::cerr << errorString << std::endl;
|
Chris@225
|
284 return QXmlDefaultHandler::error(exception);
|
Chris@225
|
285 }
|
Chris@225
|
286
|
Chris@225
|
287 bool
|
Chris@225
|
288 TipDialog::TipFileParser::fatalError(const QXmlParseException &exception)
|
Chris@225
|
289 {
|
Chris@225
|
290 QString errorString =
|
Chris@225
|
291 QString("FATAL ERROR: TipFileParser: %1 at line %2, column %3")
|
Chris@225
|
292 .arg(exception.message())
|
Chris@225
|
293 .arg(exception.lineNumber())
|
Chris@225
|
294 .arg(exception.columnNumber());
|
Chris@584
|
295 std::cerr << errorString << std::endl;
|
Chris@225
|
296 return QXmlDefaultHandler::fatalError(exception);
|
Chris@225
|
297 }
|