annotate widgets/TipDialog.cpp @ 349:369a197737c7

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents 387f2f6fc333
children 1fe7951a61e8
rev   line source
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@225 117 std::cerr << "TipDialog::readTips" << std::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@225 137 std::cerr << "TipDialog::readTips from " << filename.toStdString() << std::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@225 149 std::cerr << "Tip " << m_tipNumber << " is: " << m_tips[m_tipNumber].toStdString() << 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@225 191 std::cerr << "TipFileParser::startElement(" << name.toStdString() << ")" << std::endl;
Chris@225 192
Chris@225 193 if (name == "tips") {
Chris@225 194 QString caption = attributes.value("caption");
Chris@225 195 std::cerr << "TipFileParser::caption = " << caption.toStdString() << std::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@225 227 std::cerr << "TipFileParser::startElement done" << std::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@225 266 std::cerr << "TipFileParser::characters(" << text.toStdString() << ")" << std::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@225 283 std::cerr << errorString.toStdString() << 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@225 295 std::cerr << errorString.toStdString() << std::endl;
Chris@225 296 return QXmlDefaultHandler::fatalError(exception);
Chris@225 297 }