diff --git a/src/alkonlinequotesprofile.cpp b/src/alkonlinequotesprofile.cpp index 24fd455..1987c3a 100644 --- a/src/alkonlinequotesprofile.cpp +++ b/src/alkonlinequotesprofile.cpp @@ -1,359 +1,393 @@ /*************************************************************************** * Copyright 2018 Ralf Habacker * * * * This file is part of libalkimia. * * * * libalkimia is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * * as published by the Free Software Foundation; either version 2.1 of * * the License or (at your option) version 3 or any later version. * * * * libalkimia is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ #include "alkonlinequotesprofile.h" #include "alkonlinequotesprofilemanager.h" #include "alkonlinequotesource.h" #include "alkfinancequoteprocess.h" #include #include #include #include #include #include #include #include #include #include class AlkOnlineQuotesProfile::Private : public QObject { Q_OBJECT public: AlkOnlineQuotesProfile *m_p; QString m_name; QString m_GHNSFile; QString m_GHNSFilePath; QString m_kconfigFile; AlkOnlineQuotesProfileManager *m_profileManager; KNS3::DownloadManager *m_manager; KConfig *m_config; Type m_type; static QString m_financeQuoteScriptPath; static QStringList m_financeQuoteSources; Private(AlkOnlineQuotesProfile *p) : m_p(p) , m_profileManager(0) , m_manager(0) , m_config(0) , m_type(Type::Undefined) { if (m_financeQuoteScriptPath.isEmpty()) { m_financeQuoteScriptPath = KGlobal::dirs()->findResource("appdata", QString("misc/financequote.pl")); } } ~Private() { delete m_manager; delete m_config; } void checkUpdates() { m_manager = new KNS3::DownloadManager(m_p->hotNewStuffConfigFile(), this); // to know when checking for updates is done connect(m_manager, SIGNAL(searchResult(KNS3::Entry::List)), this, SLOT(slotUpdatesFound(KNS3::Entry::List))); // to know about finished installations connect(m_manager, SIGNAL(entryStatusChanged(KNS3::Entry)), this, SLOT(entryStatusChanged(KNS3::Entry))); // start checking for updates m_manager->checkForUpdates(); } public Q_SLOTS: void slotUpdatesFound(const KNS3::Entry::List &updates) { foreach (const KNS3::Entry &entry, updates) { qDebug() << entry.name(); } } // to know about finished installations void entryStatusChanged(const KNS3::Entry &entry) { qDebug() << entry.summary(); } const QStringList quoteSourcesNative() { //KSharedConfigPtr kconfig = KGlobal::config(); KConfig config(m_kconfigFile); KConfig *kconfig = &config; QStringList groups = kconfig->groupList(); QStringList::Iterator it; QRegExp onlineQuoteSource(QString("^Online-Quote-Source-(.*)$")); // get rid of all 'non online quote source' entries for (it = groups.begin(); it != groups.end(); it = groups.erase(it)) { if (onlineQuoteSource.indexIn(*it) >= 0) { // Insert the name part it = groups.insert(it, onlineQuoteSource.cap(1)); ++it; } } // Set up each of the default sources. These are done piecemeal so that // when we add a new source, it's automatically picked up. And any changes // are also picked up. QMap defaults = defaultQuoteSources(); QMap::iterator it_source = defaults.begin(); while (it_source != defaults.end()) { if (!groups.contains((*it_source).name())) { groups += (*it_source).name(); (*it_source).write(); kconfig->sync(); } ++it_source; } return groups; } const QStringList quoteSourcesFinanceQuote() { if (m_financeQuoteSources.empty()) { // run the process one time only // since this is a static function it can be called without constructing an object // so we need to make sure that m_financeQuoteScriptPath is properly initialized if (m_financeQuoteScriptPath.isEmpty()) { m_financeQuoteScriptPath = KGlobal::dirs()->findResource("appdata", QString("financequote.pl")); } AlkFinanceQuoteProcess getList; getList.launch(m_financeQuoteScriptPath); while (!getList.isFinished()) { qApp->processEvents(); } m_financeQuoteSources = getList.getSourceList(); } return m_financeQuoteSources; } const QStringList quoteSourcesSkrooge() { return quoteSourcesGHNS(); } const QStringList quoteSourcesGHNS() { QStringList sources; QString relPath = m_GHNSFilePath; foreach (const QString &file, KStandardDirs().findAllResources("data", relPath + QString::fromLatin1("/*.txt"))) { QFileInfo f(file); QString file2 = f.completeBaseName(); AlkOnlineQuoteSource source(file2, m_p); if (source.isEmpty()) { qDebug() << "skipping" << file2; continue; } if (!sources.contains(file2)) { sources.push_back(file2); } } return sources; } const AlkOnlineQuotesProfile::Map defaultQuoteSources() { QMap result; // Use fx-rate.net as the standard currency exchange rate source until // we have the capability to use more than one source. Use a neutral // name for the source. switch (m_p->type()) { case AlkOnlineQuotesProfile::Type::None: case AlkOnlineQuotesProfile::Type::Alkimia4: case AlkOnlineQuotesProfile::Type::Alkimia5: { AlkOnlineQuoteSource source("Alkimia Currency", "https://fx-rate.net/%1/%2", QString(), // symbolregexp "1[ a-zA-Z]+=
*(\\d+\\.\\d+)", "updated\\s\\d+:\\d+:\\d+\\(\\w+\\)\\s+(\\d{1,2}/\\d{2}/\\d{4})", "%d/%m/%y", true // skip HTML stripping ); source.setProfile(m_p); result[source.name()] = source; source.setName(source.name() + ".webkit"); result[source.name()] = source; break; } default: break; } return result; } + + QString configPath() + { + // TODO: add windows support + if (m_type == Type::KMyMoney5 || m_type == Type::Alkimia5 || m_type == Type::Skrooge5) + return QString("%1/.config").arg(QDir::homePath()); + else if (m_type == Type::KMyMoney4 || m_type == Type::Alkimia4 || m_type == Type::Skrooge4) + return QString("%1/.kde4/share/config").arg(QDir::homePath()); + return + QString(); + } + + QString dataReadPath() + { + // TODO: add windows support + if (m_type == Type::KMyMoney5 || m_type == Type::Alkimia5 || m_type == Type::Skrooge5) + return QString("/usr/share/kf5"); + else if (m_type == Type::KMyMoney4 || m_type == Type::Alkimia4 || m_type == Type::Skrooge4) + return QString("/usr/share/kde4/apps"); + return + QString(); + } + + QString dataWritePath() + { + // TODO: add windows support + if (m_type == Type::KMyMoney5 || m_type == Type::Alkimia5 || m_type == Type::Skrooge5) + return QString("%1/.local/share").arg(QDir::homePath()); + else if (m_type == Type::KMyMoney4 || m_type == Type::Alkimia4 || m_type == Type::Skrooge4) + return QString("%1/.kde4/share/apps").arg(QDir::homePath()); + return + QString(); + } }; // define static members QString AlkOnlineQuotesProfile::Private::m_financeQuoteScriptPath; QStringList AlkOnlineQuotesProfile::Private::m_financeQuoteSources; AlkOnlineQuotesProfile::AlkOnlineQuotesProfile(const QString &name, Type type, const QString &ghnsConfigFile) : d(new Private(this)) { d->m_name = name; d->m_GHNSFile = ghnsConfigFile; d->m_type = type; if (type == Type::KMyMoney5) - d->m_kconfigFile = QString("%1/.config/kmymoney/kmymoneyrc").arg(QDir::homePath()); + d->m_kconfigFile = QString("%1/kmymoney/kmymoneyrc").arg(d->configPath()); else if (type == Type::KMyMoney4) - d->m_kconfigFile = QString("%1/.kde4/share/config/kmymoneyrc").arg(QDir::homePath()); - else if (type == Type::Alkimia5) - d->m_kconfigFile = QString("%1/.config/alkimiarc").arg(QDir::homePath()); - else if (type == Type::Alkimia4) - d->m_kconfigFile = QString("%1/.kde4/share/config/alkimiarc").arg(QDir::homePath()); + d->m_kconfigFile = QString("%1/kmymoneyrc").arg(d->configPath()); + else if (type == Type::Alkimia5 || type == Type::Alkimia4) + d->m_kconfigFile = QString("%1/alkimiarc").arg(d->configPath()); else d->m_kconfigFile = ""; if (!d->m_kconfigFile.isEmpty()) d->m_config = new KConfig(d->m_kconfigFile); if (!d->m_GHNSFile.isEmpty()) { KConfig ghnsFile(hotNewStuffConfigFile()); KConfigGroup group = ghnsFile.group("KNewStuff3"); d->m_GHNSFilePath = group.readEntry("TargetDir"); d->checkUpdates(); } } AlkOnlineQuotesProfile::~AlkOnlineQuotesProfile() { delete d; } QString AlkOnlineQuotesProfile::name() const { return d->m_name; } QString AlkOnlineQuotesProfile::hotNewStuffConfigFile() const { QString configFile = KStandardDirs::locate("config", d->m_GHNSFile); if (configFile.isEmpty()) { configFile = QString("%1/%2").arg(KNSRC_DIR, d->m_GHNSFile); } return configFile; } QString AlkOnlineQuotesProfile::hotNewStuffReadFilePath(const QString &fileName) const { foreach(const QString &path, hotNewStuffReadPath()) { QFileInfo f(path + fileName); if (f.exists()) return f.absoluteFilePath(); } return QString(); } QString AlkOnlineQuotesProfile::hotNewStuffWriteFilePath(const QString &fileName) const { - return KStandardDirs::locateLocal("data", d->m_GHNSFilePath + "/" + fileName); + return QString("%1%2").arg(hotNewStuffWriteDir(), fileName); } QStringList AlkOnlineQuotesProfile::hotNewStuffReadPath() const { - return KStandardDirs().findDirs("data", d->m_GHNSFilePath + "/"); + return QStringList() + << QString("%1/%2/").arg(d->dataReadPath(), d->m_GHNSFilePath) + << hotNewStuffWriteDir(); } QString AlkOnlineQuotesProfile::hotNewStuffWriteDir() const { - return KStandardDirs().saveLocation("data", d->m_GHNSFilePath + "/"); + return QString("%1/%2/").arg(d->dataWritePath(), d->m_GHNSFilePath); } QString AlkOnlineQuotesProfile::hotNewStuffRelPath() const { return d->m_GHNSFilePath; } QString AlkOnlineQuotesProfile::kConfigFile() const { return d->m_kconfigFile; } KConfig *AlkOnlineQuotesProfile::kConfig() const { return d->m_config; } AlkOnlineQuotesProfile::Type AlkOnlineQuotesProfile::type() { return d->m_type; } bool AlkOnlineQuotesProfile::hasGHNSSupport() { return !d->m_GHNSFile.isEmpty(); } const AlkOnlineQuotesProfile::Map AlkOnlineQuotesProfile::defaultQuoteSources() { return d->defaultQuoteSources(); } const QStringList AlkOnlineQuotesProfile::quoteSources() { QStringList result; switch(d->m_type) { case AlkOnlineQuotesProfile::Type::Alkimia4: case AlkOnlineQuotesProfile::Type::Alkimia5: case AlkOnlineQuotesProfile::Type::KMyMoney4: case AlkOnlineQuotesProfile::Type::KMyMoney5: result << d->quoteSourcesNative(); break; case AlkOnlineQuotesProfile::Type::Script: result << d->quoteSourcesFinanceQuote(); break; - case AlkOnlineQuotesProfile::Type::Skrooge: + case AlkOnlineQuotesProfile::Type::Skrooge4: + case AlkOnlineQuotesProfile::Type::Skrooge5: result << d->quoteSourcesSkrooge(); break; case AlkOnlineQuotesProfile::Type::None: result << d->defaultQuoteSources().keys(); default: break; } if (hasGHNSSupport()) result << d->quoteSourcesGHNS(); return result; } void AlkOnlineQuotesProfile::setManager(AlkOnlineQuotesProfileManager *manager) { d->m_profileManager = manager; } AlkOnlineQuotesProfileManager *AlkOnlineQuotesProfile::manager() { return d->m_profileManager; } #include "alkonlinequotesprofile.moc" diff --git a/src/alkonlinequotesprofile.h b/src/alkonlinequotesprofile.h index d84e30a..61ed6b6 100644 --- a/src/alkonlinequotesprofile.h +++ b/src/alkonlinequotesprofile.h @@ -1,74 +1,74 @@ /*************************************************************************** * Copyright 2018 Ralf Habacker * * * * This file is part of libalkimia. * * * * libalkimia is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public License * * as published by the Free Software Foundation; either version 2.1 of * * the License or (at your option) version 3 or any later version. * * * * libalkimia is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ #ifndef ALKONLINEQUOTESPROFILE_H #define ALKONLINEQUOTESPROFILE_H #include #include #include #include class KConfig; class AlkOnlineQuoteSource; class AlkOnlineQuotesProfileManager; class ALK_EXPORT AlkOnlineQuotesProfile { public: typedef QMap Map; enum class Type { - Undefined, None, Alkimia4, Alkimia5, KMyMoney4, KMyMoney5, Skrooge, Script + Undefined, None, Alkimia4, Alkimia5, KMyMoney4, KMyMoney5, Skrooge4, Skrooge5, Script }; AlkOnlineQuotesProfile(const QString &name = "alkimia", Type type = Type::None, const QString &ghnsConfigFile = QString()); ~AlkOnlineQuotesProfile(); QString name() const; QString hotNewStuffConfigFile() const; QString hotNewStuffRelPath() const; QStringList hotNewStuffReadPath() const; QString hotNewStuffWriteDir() const; QString hotNewStuffReadFilePath(const QString &fileName) const; QString hotNewStuffWriteFilePath(const QString &fileName) const; QString kConfigFile() const; void setManager(AlkOnlineQuotesProfileManager *manager); AlkOnlineQuotesProfileManager *manager(); KConfig *kConfig() const; Type type(); bool hasGHNSSupport(); /** * return available default sources of this profile */ const Map defaultQuoteSources(); /** * return available sources of this profile */ const QStringList quoteSources(); private: class Private; Private *const d; }; #endif // ALKONLINEQUOTESPROFILE_H diff --git a/tools/onlinequoteseditor/mainwindow.cpp b/tools/onlinequoteseditor/mainwindow.cpp index e4678c7..05320b5 100644 --- a/tools/onlinequoteseditor/mainwindow.cpp +++ b/tools/onlinequoteseditor/mainwindow.cpp @@ -1,149 +1,150 @@ /*************************************************************************** * Copyright 2018 Ralf Habacker * * * * This file is part of libalkimia. * * * * libalkimia 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.1 of * * the License or (at your option) version 3 or any later version. * * * * libalkimia is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include "alkonlinequotesprofile.h" #include "alkonlinequotesprofilemanager.h" #include "alkonlinequoteswidget.h" #include "alkwebpage.h" #include #include #include #include #include class MainWindow::Private { public: Private() : urlLine(nullptr) , quotesWidget(nullptr) { } ~Private() { delete quotesWidget; } QLineEdit *urlLine; AlkOnlineQuotesWidget *quotesWidget; Ui::MainWindow ui; }; void MainWindow::slotUrlChanged(const QUrl &url) { d->urlLine->setText(url.toString()); } void MainWindow::slotEditingFinished() { AlkOnlineQuotesProfileManager::instance().webPage()->load(QUrl(d->urlLine->text()), d->quotesWidget->acceptLanguage()); } void MainWindow::slotLanguageChanged(const QString &text) { d->quotesWidget->setAcceptLanguage(text); if (!d->urlLine->text().isEmpty()) slotEditingFinished(); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , d(new Private) { AlkOnlineQuotesProfileManager &manager = AlkOnlineQuotesProfileManager::instance(); manager.setWebPageEnabled(true); manager.addProfile(new AlkOnlineQuotesProfile("no-config-file", AlkOnlineQuotesProfile::Type::None)); manager.addProfile(new AlkOnlineQuotesProfile("alkimia4", AlkOnlineQuotesProfile::Type::Alkimia4, "alkimia-quotes.knsrc")); manager.addProfile(new AlkOnlineQuotesProfile("alkimia5", AlkOnlineQuotesProfile::Type::Alkimia5, "alkimia-quotes.knsrc")); - manager.addProfile(new AlkOnlineQuotesProfile("skrooge", AlkOnlineQuotesProfile::Type::None, "skrooge-quotes.knsrc")); + manager.addProfile(new AlkOnlineQuotesProfile("skrooge4", AlkOnlineQuotesProfile::Type::Skrooge4, "skrooge-quotes.knsrc")); + manager.addProfile(new AlkOnlineQuotesProfile("skrooge5", AlkOnlineQuotesProfile::Type::Skrooge5, "skrooge-quotes.knsrc")); manager.addProfile(new AlkOnlineQuotesProfile("kmymoney4", AlkOnlineQuotesProfile::Type::KMyMoney4, "kmymoney-quotes.knsrc")); manager.addProfile(new AlkOnlineQuotesProfile("kmymoney5", AlkOnlineQuotesProfile::Type::KMyMoney5, "kmymoney-quotes.knsrc")); d->ui.setupUi(this); d->quotesWidget = new AlkOnlineQuotesWidget(true, true); QDockWidget *profilesWidget = new QDockWidget(tr("Profiles"), this); profilesWidget->setWidget(d->quotesWidget->profilesWidget()); addDockWidget(Qt::LeftDockWidgetArea, profilesWidget); QDockWidget *profileDetailsWidget = new QDockWidget(tr("Profile details"), this); profileDetailsWidget->setWidget(d->quotesWidget->profileDetailsWidget()); addDockWidget(Qt::RightDockWidgetArea, profileDetailsWidget); QDockWidget *onlineQuotesWidget = new QDockWidget(tr("Online quotes"), this); onlineQuotesWidget->setWidget(d->quotesWidget->onlineQuotesWidget()); addDockWidget(Qt::LeftDockWidgetArea, onlineQuotesWidget); QDockWidget *debugWidget = new QDockWidget(tr("Debug"), this); debugWidget->setWidget(d->quotesWidget->debugWidget()); addDockWidget(Qt::LeftDockWidgetArea, debugWidget); QDockWidget *quoteDetailsWidget = new QDockWidget(tr("Quote details"), this); quoteDetailsWidget->setWidget(d->quotesWidget->quoteDetailsWidget()); addDockWidget(Qt::RightDockWidgetArea, quoteDetailsWidget); QDockWidget *browserWidget = new QDockWidget(tr("Browser"), this); AlkWebPage *webPage = manager.webPage(); connect(webPage, SIGNAL(urlChanged(QUrl)), this, SLOT(slotUrlChanged(QUrl))); d->urlLine = new QLineEdit; connect(d->urlLine, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); // setup language box QComboBox *box = new QComboBox; QList allLocales = QLocale::matchingLocales( QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); QStringList languages; foreach(const QLocale &locale, allLocales) { languages.append(locale.uiLanguages()); } languages.sort(); box->addItems(languages); d->quotesWidget->setAcceptLanguage(box->currentText()); connect(box, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotLanguageChanged(QString))); // setup layouts QHBoxLayout *hLayout = new QHBoxLayout; hLayout->addWidget(d->urlLine); hLayout->addWidget(box); QVBoxLayout *layout = new QVBoxLayout; layout->addLayout(hLayout); layout->addWidget(webPage); QWidget *group = new QWidget; group->setLayout(layout); browserWidget->setWidget(group); addDockWidget(Qt::RightDockWidgetArea, browserWidget); setCentralWidget(nullptr); webPage->setWebInspectorEnabled(true); } MainWindow::~MainWindow() { delete d; }