changeset 225:6f46179086c0

* Basic beginnings of what will become a tip-of-the-day dialog
author Chris Cannam
date Fri, 09 Mar 2007 18:18:30 +0000
parents 9465b5375235
children 2ccd02015530
files widgets/TipDialog.cpp widgets/TipDialog.h widgets/widgets.pro
diffstat 3 files changed, 339 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/TipDialog.cpp	Fri Mar 09 18:18:30 2007 +0000
@@ -0,0 +1,255 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2007 QMUL.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "TipDialog.h"
+
+#include <QLabel>
+#include <QPushButton>
+#include <QSettings>
+#include <QLabel>
+#include <QLocale>
+#include <QXmlInputSource>
+#include <QFileInfo>
+#include <QGridLayout>
+#include <QGroupBox>
+
+#include <iostream>
+
+TipDialog::TipDialog(QWidget *parent, Qt::WFlags flags) :
+    QDialog(parent, flags),
+    m_tipNumber(0),
+    m_label(0),
+    m_caption(tr("Tip of the Day"))
+{
+    readTips();
+
+    QSettings settings;
+    settings.beginGroup("TipOfTheDay");
+
+    if (!settings.value("showonstartup", true).toBool()) return;
+
+    m_tipNumber = settings.value("nexttip", 0).toInt();
+
+    setWindowTitle(m_caption);
+
+    QGridLayout *grid = new QGridLayout;
+    setLayout(grid);
+    
+    QGroupBox *groupBox = new QGroupBox;
+    groupBox->setTitle(m_caption);
+    grid->addWidget(groupBox, 0, 0);
+    
+    QGridLayout *subgrid = new QGridLayout;
+    groupBox->setLayout(subgrid);
+
+    m_label = new QLabel;
+    subgrid->addWidget(m_label, 0, 0);
+
+    QHBoxLayout *hbox = new QHBoxLayout;
+    grid->addLayout(hbox, 1, 0);
+    
+    QPushButton *close = new QPushButton(tr("Close"));
+    hbox->addStretch(10);
+    hbox->addWidget(close);
+    connect(close, SIGNAL(clicked()), this, SLOT(accept()));
+    
+    showTip();
+}
+
+TipDialog::~TipDialog()
+{
+}
+
+void
+TipDialog::next()
+{
+    if (++m_tipNumber >= int(m_tips.size())) {
+        //!!! The tips file should define where we loop back to -- the
+        // first one at least is likely to be a generic welcome message
+        m_tipNumber = 0;
+    }
+
+    showTip();
+}
+
+void
+TipDialog::previous()
+{
+    if (--m_tipNumber < 0) {
+        m_tipNumber = m_tips.size() - 1;
+    }
+
+    showTip();
+}
+
+void
+TipDialog::readTips()
+{
+    std::cerr << "TipDialog::readTips" << std::endl;
+
+    QString language = QLocale::system().name();
+    QString filename = QString(":i18n/tips_%1.xml").arg(language);
+
+    if (!QFileInfo(filename).exists()) {
+
+        QString base = language.section('_', 0, 0);
+        filename = QString(":i18n/tips_%1.xml").arg(base);
+
+        if (!QFileInfo(filename).exists()) {
+
+            filename = QString(":i18n/tips.xml");
+
+            if (!QFileInfo(filename).exists()) return;
+        }
+    }
+
+    QFile file(filename);
+
+    std::cerr << "TipDialog::readTips from " << filename.toStdString() << std::endl;
+
+    QXmlInputSource source(&file);
+    
+    TipFileParser parser(this);
+    parser.parse(source);
+}
+
+void
+TipDialog::showTip()
+{
+    if (m_tipNumber < int(m_tips.size())) {
+        std::cerr << "Tip " << m_tipNumber << " is: " << m_tips[m_tipNumber].toStdString() << std::endl;
+        m_label->setText(m_tips[m_tipNumber]);
+    } else {
+        accept();
+    }
+
+    int tn = m_tipNumber;
+    if (++tn >= int(m_tips.size())) tn = 0; //!!! as above
+
+    QSettings settings;
+    settings.beginGroup("TipOfTheDay");
+    settings.setValue("nexttip", tn);
+}
+
+TipDialog::TipFileParser::TipFileParser(TipDialog *dialog) :
+    m_dialog(dialog),
+    m_inTip(false),
+    m_inText(false)
+{
+}
+
+TipDialog::TipFileParser::~TipFileParser()
+{
+}
+
+void
+TipDialog::TipFileParser::parse(QXmlInputSource &source)
+{
+    QXmlSimpleReader reader;
+    reader.setContentHandler(this);
+    reader.setErrorHandler(this);
+    reader.parse(source);
+}
+
+bool
+TipDialog::TipFileParser::startElement(const QString &, const QString &,
+                                       const QString &qName,
+                                       const QXmlAttributes &attributes)
+{
+    QString name = qName.toLower();
+
+    std::cerr << "TipFileParser::startElement(" << name.toStdString() << ")" << std::endl;
+
+    if (name == "tips") {
+        QString caption = attributes.value("caption");
+        std::cerr << "TipFileParser::caption = " << caption.toStdString() << std::endl;
+        if (caption != "") m_dialog->m_caption = caption;
+    } else if (name == "tip") {
+        if (m_inTip) {
+            std::cerr << "WARNING: TipFileParser: nested <tip> elements" << std::endl;
+        }
+        m_inTip = true;
+    } else if (name == "text") {
+        if (m_inTip) {
+            m_inText = true;
+            std::cerr << "TipFileParser: adding new tip" << std::endl;
+            m_dialog->m_tips.push_back("");
+        } else {
+            std::cerr << "WARNING: TipFileParser: <text> outside <tip> element" << std::endl;
+        }
+    }
+    
+    std::cerr << "TipFileParser::startElement done" << std::endl;
+    return true;
+}
+
+bool
+TipDialog::TipFileParser::endElement(const QString &, const QString &,
+                                     const QString &qName)
+{
+    QString name = qName.toLower();
+
+    if (name == "text") {
+        if (m_inText) {
+            std::cerr << "WARNING: TipFileParser: </text> without <text>" << std::endl;
+        }
+        m_inText = false;
+    } else if (name == "tip") {
+        if (m_inText) {
+            std::cerr << "WARNING: TipFileParser: <text> without </text>" << std::endl;
+        } else if (!m_inTip) {
+            std::cerr << "WARNING: TipFileParser: </tip> without <tip>" << std::endl;
+        }
+        m_inTip = false;
+    }
+
+    return true;
+}
+
+bool
+TipDialog::TipFileParser::characters(const QString &text)
+{
+    std::cerr << "TipFileParser::characters(" << text.toStdString() << ")" << std::endl;
+
+    if (m_inText) {
+        m_dialog->m_tips[m_dialog->m_tips.size()-1] += text;
+    }
+
+    return true;
+}
+
+bool
+TipDialog::TipFileParser::error(const QXmlParseException &exception)
+{
+    QString errorString =
+	QString("ERROR: TipFileParser: %1 at line %2, column %3")
+	.arg(exception.message())
+	.arg(exception.lineNumber())
+	.arg(exception.columnNumber());
+    std::cerr << errorString.toStdString() << std::endl;
+    return QXmlDefaultHandler::error(exception);
+}
+
+bool
+TipDialog::TipFileParser::fatalError(const QXmlParseException &exception)
+{
+    QString errorString =
+	QString("FATAL ERROR: TipFileParser: %1 at line %2, column %3")
+	.arg(exception.message())
+	.arg(exception.lineNumber())
+	.arg(exception.columnNumber());
+    std::cerr << errorString.toStdString() << std::endl;
+    return QXmlDefaultHandler::fatalError(exception);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/TipDialog.h	Fri Mar 09 18:18:30 2007 +0000
@@ -0,0 +1,82 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2007 QMUL.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#ifndef _TIP_DIALOG_H_
+#define _TIP_DIALOG_H_
+
+#include <QDialog>
+#include <QString>
+#include <QXmlDefaultHandler>
+
+#include <vector>
+
+class QLabel;
+class QXmlInputSource;
+
+class TipDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    TipDialog(QWidget *parent = 0, Qt::WFlags flags = 0);
+    virtual ~TipDialog();
+
+    bool isOK() { return !m_tips.empty(); }
+
+protected slots:
+    void previous();
+    void next();
+
+protected:
+    int m_tipNumber;
+    QLabel *m_label;
+    QString m_caption;
+
+    std::vector<QString> m_tips;
+
+    void readTips();
+    void showTip();
+
+    class TipFileParser : public QXmlDefaultHandler
+    {
+    public:
+        TipFileParser(TipDialog *dialog);
+        virtual ~TipFileParser();
+        
+        void parse(QXmlInputSource &source);
+
+        virtual bool startElement(const QString &namespaceURI,
+                                  const QString &localName,
+                                  const QString &qName,
+                                  const QXmlAttributes& atts);
+        
+        virtual bool characters(const QString &);
+        
+        virtual bool endElement(const QString &namespaceURI,
+                                const QString &localName,
+                                const QString &qName);
+        
+        bool error(const QXmlParseException &exception);
+        bool fatalError(const QXmlParseException &exception);
+
+    protected:
+        TipDialog *m_dialog;
+
+        bool m_inTip;
+        bool m_inText;
+    };
+};
+
+#endif
--- a/widgets/widgets.pro	Thu Mar 08 16:53:08 2007 +0000
+++ b/widgets/widgets.pro	Fri Mar 09 18:18:30 2007 +0000
@@ -32,6 +32,7 @@
            RangeInputDialog.h \
            SubdividingMenu.h \
            Thumbwheel.h \
+           TipDialog.h \
            WindowShapePreview.h \
            WindowTypeSelector.h
 SOURCES += AudioDial.cpp \
@@ -52,5 +53,6 @@
            RangeInputDialog.cpp \
            SubdividingMenu.cpp \
            Thumbwheel.cpp \
+           TipDialog.cpp \
            WindowShapePreview.cpp \
            WindowTypeSelector.cpp