annotate widgets/TipDialog.cpp @ 1578:57a4ee52ad69 background-mode

Make nearby-colour matching a bit more sophisticated, with slightly better algorithm (we think?) and ability to insist on dark/light background
author Chris Cannam
date Fri, 24 Jan 2020 12:40:07 +0000
parents c8a6fd3f9dff
children
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@616 31 TipDialog::TipDialog(QWidget *parent) :
Chris@616 32 QDialog(parent),
Chris@225 33 m_tipNumber(0),
Chris@1408 34 m_label(nullptr),
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@908 108 m_tipNumber = int(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@587 117 SVDEBUG << "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@587 137 SVDEBUG << "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@682 149 cerr << "Tip " << m_tipNumber << " is: " << m_tips[m_tipNumber] << 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@587 191 SVDEBUG << "TipFileParser::startElement(" << name << ")" << endl;
Chris@225 192
Chris@225 193 if (name == "tips") {
Chris@225 194 QString caption = attributes.value("caption");
Chris@587 195 SVDEBUG << "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@682 199 cerr << "WARNING: TipFileParser: nested <tip> elements" << 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@682 205 cerr << "TipFileParser: adding new tip" << endl;
Chris@225 206 m_dialog->m_tips.push_back("");
Chris@225 207 } else {
Chris@682 208 cerr << "WARNING: TipFileParser: <text> outside <tip> element" << endl;
Chris@225 209 }
Chris@228 210 } else if (name == "html") {
Chris@228 211 if (m_inTip) {
Chris@228 212 m_inHtml = true;
Chris@682 213 cerr << "TipFileParser: adding new tip" << endl;
Chris@228 214 m_dialog->m_tips.push_back("");
Chris@228 215 } else {
Chris@682 216 cerr << "WARNING: TipFileParser: <html> outside <tip> element" << 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@587 227 SVDEBUG << "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@682 239 cerr << "WARNING: TipFileParser: </text> without <text>" << endl;
Chris@225 240 }
Chris@225 241 m_inText = false;
Chris@228 242 } else if (name == "html") {
Chris@228 243 if (!m_inHtml) {
Chris@682 244 cerr << "WARNING: TipFileParser: </html> without <html>" << endl;
Chris@228 245 }
Chris@228 246 m_inHtml = false;
Chris@225 247 } else if (name == "tip") {
Chris@225 248 if (m_inText) {
Chris@682 249 cerr << "WARNING: TipFileParser: <text> without </text>" << endl;
Chris@228 250 } else if (m_inHtml) {
Chris@682 251 cerr << "WARNING: TipFileParser: <html> without </html>" << endl;
Chris@225 252 } else if (!m_inTip) {
Chris@682 253 cerr << "WARNING: TipFileParser: </tip> without <tip>" << 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@587 266 SVDEBUG << "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@1266 279 QString("ERROR: TipFileParser: %1 at line %2, column %3")
Chris@1266 280 .arg(exception.message())
Chris@1266 281 .arg(exception.lineNumber())
Chris@1266 282 .arg(exception.columnNumber());
Chris@682 283 cerr << errorString << 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@1266 291 QString("FATAL ERROR: TipFileParser: %1 at line %2, column %3")
Chris@1266 292 .arg(exception.message())
Chris@1266 293 .arg(exception.lineNumber())
Chris@1266 294 .arg(exception.columnNumber());
Chris@682 295 cerr << errorString << endl;
Chris@225 296 return QXmlDefaultHandler::fatalError(exception);
Chris@225 297 }