File indexing completed on 2024-04-28 15:35:51

0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
0002 // SPDX-License-Identifier: LGPL-2.1-only or LGPL-3.0-only or LicenseRef-KDE-Accepted-LGPL
0003 
0004 #include <QCommandLineParser>
0005 #include <QFontDatabase>
0006 #include <QNetworkProxy>
0007 #include <QNetworkProxyFactory>
0008 #include <QQmlApplicationEngine>
0009 #include <QQmlContext>
0010 #include <QQuickStyle>
0011 #include <QQuickWindow>
0012 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0013 #include <QtWebEngine>
0014 #else
0015 #include <QtWebEngineQuick>
0016 #endif
0017 
0018 #include <QApplication>
0019 
0020 #include <KAboutData>
0021 #include <KConfig>
0022 #include <KDBusService>
0023 #include <KLocalizedContext>
0024 #include <KLocalizedString>
0025 #include <KWindowConfig>
0026 #include <KWindowSystem>
0027 #include <qstringliteral.h>
0028 
0029 #include "arianna-version.h"
0030 #include "bookdatabase.h"
0031 #include "booklistmodel.h"
0032 #include "clipboard.h"
0033 #include "config.h"
0034 #include "contentlist/contentlist.h"
0035 #include "contentlist/contentquery.h"
0036 #include "format.h"
0037 #include "navigation.h"
0038 #include "tableofcontentmodel.h"
0039 
0040 int main(int argc, char *argv[])
0041 {
0042 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0043     QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
0044 #endif
0045 
0046     QNetworkProxyFactory::setUseSystemConfiguration(true);
0047 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0048     QtWebEngine::initialize();
0049 #else
0050     QtWebEngineQuick::initialize();
0051 #endif
0052 
0053     QApplication app(argc, argv);
0054     // Default to org.kde.desktop style unless the user forces another style
0055     if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) {
0056         QQuickStyle::setStyle(QStringLiteral("org.kde.desktop"));
0057     }
0058 
0059 #ifdef Q_OS_WINDOWS
0060     if (AttachConsole(ATTACH_PARENT_PROCESS)) {
0061         freopen("CONOUT$", "w", stdout);
0062         freopen("CONOUT$", "w", stderr);
0063     }
0064 
0065     QApplication::setStyle(QStringLiteral("breeze"));
0066     auto font = app.font();
0067     font.setPointSize(10);
0068     app.setFont(font);
0069 #endif
0070 
0071     KLocalizedString::setApplicationDomain("arianna");
0072 
0073     KAboutData about(QStringLiteral("arianna"),
0074                      i18n("Arianna"),
0075                      QStringLiteral(ARIANNA_VERSION_STRING),
0076                      i18n("EPub Reader"),
0077                      KAboutLicense::GPL_V3,
0078                      i18n("2022 Niccolò Venerandi <niccolo@venerandi.com>"));
0079     about.addAuthor(i18n("Niccolò Venerandi"), i18n("Maintainer"), QStringLiteral("niccolo@venerandi.com"));
0080     about.addAuthor(i18n("Carl Schwan"), i18n("Maintainer"), QStringLiteral("carl@carlschwan.eu"));
0081     about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails"));
0082     about.setOrganizationDomain("kde.org");
0083     about.setBugAddress("https://bugs.kde.org/describecomponents.cgi?product=arianna");
0084 
0085     KAboutData::setApplicationData(about);
0086     QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("org.kde.arianna")));
0087 
0088     KDBusService service(KDBusService::Unique);
0089     QQmlApplicationEngine engine;
0090     engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
0091     QObject::connect(&engine, &QQmlApplicationEngine::quit, &app, &QCoreApplication::quit);
0092 
0093     QCommandLineParser parser;
0094     parser.setApplicationDescription(i18n("Epub reader"));
0095     parser.addPositionalArgument(QLatin1String("file"), i18n("Epub file to open"));
0096 
0097     about.setupCommandLine(&parser);
0098     parser.process(app);
0099     about.processCommandLine(&parser);
0100 
0101     Clipboard clipboard;
0102     Format format;
0103     Navigation navigation;
0104     qmlRegisterSingletonInstance("org.kde.arianna", 1, 0, "Config", Config::self());
0105     qmlRegisterSingletonInstance("org.kde.arianna", 1, 0, "Clipboard", &clipboard);
0106     qmlRegisterSingletonInstance("org.kde.arianna", 1, 0, "Format", &format);
0107     qmlRegisterSingletonInstance("org.kde.arianna", 1, 0, "Navigation", &navigation);
0108     qmlRegisterType<BookListModel>("org.kde.arianna", 1, 0, "BookListModel");
0109     qmlRegisterType<ContentList>("org.kde.arianna", 1, 0, "ContentList");
0110     qmlRegisterType<QSortFilterProxyModel>("org.kde.arianna", 1, 0, "SortFilterProxyModel");
0111     qmlRegisterType<ContentQuery>("org.kde.arianna", 1, 0, "ContentQuery");
0112     qmlRegisterType<TableOfContentModel>("org.kde.arianna", 1, 0, "TableOfContentModel");
0113     qmlRegisterType<CategoryEntriesModel>("org.kde.arianna", 1, 0, "CategoryEntriesModel");
0114     qmlRegisterSingletonType("org.kde.arianna", 1, 0, "About", [](QQmlEngine *engine, QJSEngine *) -> QJSValue {
0115         return engine->toScriptValue(KAboutData::applicationData());
0116     });
0117 
0118     engine.load(QUrl(QStringLiteral("qrc:/content/ui/main.qml")));
0119     if (engine.rootObjects().isEmpty()) {
0120         return -1;
0121     }
0122 
0123     QObject::connect(&service,
0124                      &KDBusService::activateRequested,
0125                      &engine,
0126                      [&engine, &navigation](const QStringList &arguments, const QString & /*workingDirectory*/) {
0127                          const auto rootObjects = engine.rootObjects();
0128                          for (auto obj : rootObjects) {
0129                              auto view = qobject_cast<QQuickWindow *>(obj);
0130                              if (view) {
0131                                  KWindowSystem::updateStartupId(view);
0132                                  KWindowSystem::activateWindow(view);
0133 
0134                                  if (arguments.count() > 1) {
0135                                      const auto entry = BookDatabase::self().loadEntry(arguments[1]);
0136                                      if (auto book = entry) {
0137                                          Q_EMIT navigation.openBook(arguments[1], book->locations, book->currentLocation);
0138                                      } else {
0139                                          Q_EMIT navigation.openBook(arguments[1], {}, {});
0140                                      }
0141                                  }
0142                                  return;
0143                              }
0144                          }
0145                      });
0146     const auto rootObjects = engine.rootObjects();
0147     for (auto obj : rootObjects) {
0148         auto view = qobject_cast<QQuickWindow *>(obj);
0149         if (view) {
0150             KConfig dataResource(QStringLiteral("data"), KConfig::SimpleConfig, QStandardPaths::AppDataLocation);
0151             KConfigGroup windowGroup(&dataResource, "Window");
0152             KWindowConfig::restoreWindowSize(view, windowGroup);
0153             KWindowConfig::restoreWindowPosition(view, windowGroup);
0154             break;
0155         }
0156     }
0157 
0158     const QStringList args = parser.positionalArguments();
0159     if (!args.isEmpty()) {
0160         const auto entry = BookDatabase::self().loadEntry(args[0]);
0161         if (const auto book = entry) {
0162             Q_EMIT navigation.openBook(args[0], book->locations, book->currentLocation);
0163         } else {
0164             Q_EMIT navigation.openBook(args[0], {}, {});
0165         }
0166     }
0167 
0168     return QCoreApplication::exec();
0169 }