Chris@225: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@225: Chris@225: /* Chris@225: Sonic Visualiser Chris@225: An audio file viewer and annotation editor. Chris@225: Centre for Digital Music, Queen Mary, University of London. Chris@225: This file copyright 2007 QMUL. Chris@225: Chris@225: This program is free software; you can redistribute it and/or Chris@225: modify it under the terms of the GNU General Public License as Chris@225: published by the Free Software Foundation; either version 2 of the Chris@225: License, or (at your option) any later version. See the file Chris@225: COPYING included with this distribution for more information. Chris@225: */ Chris@225: Chris@225: #include "TipDialog.h" Chris@225: Chris@225: #include Chris@225: #include Chris@225: #include Chris@225: #include Chris@225: #include Chris@225: #include Chris@225: #include Chris@225: #include Chris@225: #include Chris@228: #include Chris@225: Chris@225: #include Chris@225: Chris@616: TipDialog::TipDialog(QWidget *parent) : Chris@616: QDialog(parent), Chris@225: m_tipNumber(0), Chris@225: m_label(0), Chris@225: m_caption(tr("Tip of the Day")) Chris@225: { Chris@225: readTips(); Chris@225: Chris@225: QSettings settings; Chris@225: settings.beginGroup("TipOfTheDay"); Chris@225: Chris@225: if (!settings.value("showonstartup", true).toBool()) return; Chris@225: Chris@225: m_tipNumber = settings.value("nexttip", 0).toInt(); Chris@225: Chris@225: setWindowTitle(m_caption); Chris@225: Chris@225: QGridLayout *grid = new QGridLayout; Chris@225: setLayout(grid); Chris@225: Chris@225: QGroupBox *groupBox = new QGroupBox; Chris@228: // groupBox->setTitle(m_caption); Chris@225: grid->addWidget(groupBox, 0, 0); Chris@225: Chris@225: QGridLayout *subgrid = new QGridLayout; Chris@225: groupBox->setLayout(subgrid); Chris@225: Chris@225: m_label = new QLabel; Chris@225: subgrid->addWidget(m_label, 0, 0); Chris@228: m_label->setWordWrap(true); Chris@225: Chris@225: QHBoxLayout *hbox = new QHBoxLayout; Chris@225: grid->addLayout(hbox, 1, 0); Chris@228: Chris@229: QCheckBox *show = new QCheckBox(tr("Show tip on startup")); Chris@228: hbox->addWidget(show); Chris@228: Chris@229: hbox->addSpacing(20); Chris@228: hbox->addStretch(10); Chris@228: Chris@228: QPushButton *prev = new QPushButton(tr("<< Previous")); Chris@228: hbox->addWidget(prev); Chris@228: connect(prev, SIGNAL(clicked()), this, SLOT(previous())); Chris@228: Chris@228: QPushButton *next = new QPushButton(tr("Next >>")); Chris@228: hbox->addWidget(next); Chris@228: connect(next, SIGNAL(clicked()), this, SLOT(next())); Chris@225: Chris@225: QPushButton *close = new QPushButton(tr("Close")); Chris@225: hbox->addWidget(close); Chris@225: connect(close, SIGNAL(clicked()), this, SLOT(accept())); Chris@225: Chris@228: close->setDefault(true); Chris@228: Chris@225: showTip(); Chris@225: } Chris@225: Chris@225: TipDialog::~TipDialog() Chris@225: { Chris@225: } Chris@225: Chris@225: void Chris@225: TipDialog::next() Chris@225: { Chris@225: if (++m_tipNumber >= int(m_tips.size())) { Chris@225: //!!! The tips file should define where we loop back to -- the Chris@225: // first one at least is likely to be a generic welcome message Chris@225: m_tipNumber = 0; Chris@225: } Chris@225: Chris@225: showTip(); Chris@225: } Chris@225: Chris@225: void Chris@225: TipDialog::previous() Chris@225: { Chris@225: if (--m_tipNumber < 0) { Chris@908: m_tipNumber = int(m_tips.size()) - 1; Chris@225: } Chris@225: Chris@225: showTip(); Chris@225: } Chris@225: Chris@225: void Chris@225: TipDialog::readTips() Chris@225: { Chris@587: SVDEBUG << "TipDialog::readTips" << endl; Chris@225: Chris@225: QString language = QLocale::system().name(); Chris@225: QString filename = QString(":i18n/tips_%1.xml").arg(language); Chris@225: Chris@225: if (!QFileInfo(filename).exists()) { Chris@225: Chris@225: QString base = language.section('_', 0, 0); Chris@225: filename = QString(":i18n/tips_%1.xml").arg(base); Chris@225: Chris@225: if (!QFileInfo(filename).exists()) { Chris@225: Chris@225: filename = QString(":i18n/tips.xml"); Chris@225: Chris@225: if (!QFileInfo(filename).exists()) return; Chris@225: } Chris@225: } Chris@225: Chris@225: QFile file(filename); Chris@225: Chris@587: SVDEBUG << "TipDialog::readTips from " << filename << endl; Chris@225: Chris@225: QXmlInputSource source(&file); Chris@225: Chris@225: TipFileParser parser(this); Chris@225: parser.parse(source); Chris@225: } Chris@225: Chris@225: void Chris@225: TipDialog::showTip() Chris@225: { Chris@225: if (m_tipNumber < int(m_tips.size())) { Chris@682: cerr << "Tip " << m_tipNumber << " is: " << m_tips[m_tipNumber] << endl; Chris@225: m_label->setText(m_tips[m_tipNumber]); Chris@225: } else { Chris@225: accept(); Chris@225: } Chris@225: Chris@225: int tn = m_tipNumber; Chris@225: if (++tn >= int(m_tips.size())) tn = 0; //!!! as above Chris@225: Chris@225: QSettings settings; Chris@225: settings.beginGroup("TipOfTheDay"); Chris@225: settings.setValue("nexttip", tn); Chris@225: } Chris@225: Chris@225: TipDialog::TipFileParser::TipFileParser(TipDialog *dialog) : Chris@225: m_dialog(dialog), Chris@225: m_inTip(false), Chris@228: m_inText(false), Chris@228: m_inHtml(false) Chris@225: { Chris@225: } Chris@225: Chris@225: TipDialog::TipFileParser::~TipFileParser() Chris@225: { Chris@225: } Chris@225: Chris@225: void Chris@225: TipDialog::TipFileParser::parse(QXmlInputSource &source) Chris@225: { Chris@225: QXmlSimpleReader reader; Chris@225: reader.setContentHandler(this); Chris@225: reader.setErrorHandler(this); Chris@225: reader.parse(source); Chris@225: } Chris@225: Chris@225: bool Chris@225: TipDialog::TipFileParser::startElement(const QString &, const QString &, Chris@225: const QString &qName, Chris@225: const QXmlAttributes &attributes) Chris@225: { Chris@225: QString name = qName.toLower(); Chris@225: Chris@587: SVDEBUG << "TipFileParser::startElement(" << name << ")" << endl; Chris@225: Chris@225: if (name == "tips") { Chris@225: QString caption = attributes.value("caption"); Chris@587: SVDEBUG << "TipFileParser::caption = " << caption << endl; Chris@225: if (caption != "") m_dialog->m_caption = caption; Chris@225: } else if (name == "tip") { Chris@225: if (m_inTip) { Chris@682: cerr << "WARNING: TipFileParser: nested elements" << endl; Chris@225: } Chris@225: m_inTip = true; Chris@225: } else if (name == "text") { Chris@225: if (m_inTip) { Chris@225: m_inText = true; Chris@682: cerr << "TipFileParser: adding new tip" << endl; Chris@225: m_dialog->m_tips.push_back(""); Chris@225: } else { Chris@682: cerr << "WARNING: TipFileParser: outside element" << endl; Chris@225: } Chris@228: } else if (name == "html") { Chris@228: if (m_inTip) { Chris@228: m_inHtml = true; Chris@682: cerr << "TipFileParser: adding new tip" << endl; Chris@228: m_dialog->m_tips.push_back(""); Chris@228: } else { Chris@682: cerr << "WARNING: TipFileParser: outside element" << endl; Chris@228: } Chris@228: } else if (m_inHtml) { Chris@228: m_dialog->m_tips[m_dialog->m_tips.size()-1] += "<" + qName; Chris@228: for (int i = 0; i < attributes.count(); ++i) { Chris@228: m_dialog->m_tips[m_dialog->m_tips.size()-1] += Chris@228: " " + attributes.qName(i) + "=\"" + attributes.value(i) + "\""; Chris@228: } Chris@228: m_dialog->m_tips[m_dialog->m_tips.size()-1] += ">"; Chris@225: } Chris@225: Chris@587: SVDEBUG << "TipFileParser::startElement done" << endl; Chris@225: return true; Chris@225: } Chris@225: Chris@225: bool Chris@225: TipDialog::TipFileParser::endElement(const QString &, const QString &, Chris@225: const QString &qName) Chris@225: { Chris@225: QString name = qName.toLower(); Chris@225: Chris@225: if (name == "text") { Chris@228: if (!m_inText) { Chris@682: cerr << "WARNING: TipFileParser: without " << endl; Chris@225: } Chris@225: m_inText = false; Chris@228: } else if (name == "html") { Chris@228: if (!m_inHtml) { Chris@682: cerr << "WARNING: TipFileParser: without " << endl; Chris@228: } Chris@228: m_inHtml = false; Chris@225: } else if (name == "tip") { Chris@225: if (m_inText) { Chris@682: cerr << "WARNING: TipFileParser: without " << endl; Chris@228: } else if (m_inHtml) { Chris@682: cerr << "WARNING: TipFileParser: without " << endl; Chris@225: } else if (!m_inTip) { Chris@682: cerr << "WARNING: TipFileParser: without " << endl; Chris@225: } Chris@225: m_inTip = false; Chris@228: } else if (m_inHtml) { Chris@228: m_dialog->m_tips[m_dialog->m_tips.size()-1] += ""; Chris@225: } Chris@225: Chris@225: return true; Chris@225: } Chris@225: Chris@225: bool Chris@225: TipDialog::TipFileParser::characters(const QString &text) Chris@225: { Chris@587: SVDEBUG << "TipFileParser::characters(" << text << ")" << endl; Chris@225: Chris@228: if (m_inText || m_inHtml) { Chris@225: m_dialog->m_tips[m_dialog->m_tips.size()-1] += text; Chris@225: } Chris@225: Chris@225: return true; Chris@225: } Chris@225: Chris@225: bool Chris@225: TipDialog::TipFileParser::error(const QXmlParseException &exception) Chris@225: { Chris@225: QString errorString = Chris@225: QString("ERROR: TipFileParser: %1 at line %2, column %3") Chris@225: .arg(exception.message()) Chris@225: .arg(exception.lineNumber()) Chris@225: .arg(exception.columnNumber()); Chris@682: cerr << errorString << endl; Chris@225: return QXmlDefaultHandler::error(exception); Chris@225: } Chris@225: Chris@225: bool Chris@225: TipDialog::TipFileParser::fatalError(const QXmlParseException &exception) Chris@225: { Chris@225: QString errorString = Chris@225: QString("FATAL ERROR: TipFileParser: %1 at line %2, column %3") Chris@225: .arg(exception.message()) Chris@225: .arg(exception.lineNumber()) Chris@225: .arg(exception.columnNumber()); Chris@682: cerr << errorString << endl; Chris@225: return QXmlDefaultHandler::fatalError(exception); Chris@225: }