File indexing completed on 2024-05-12 15:54:51

0001 /*
0002  * SPDX-FileCopyrightText: (C) 2014 Vishesh Handa <vhanda@kde.org>
0003  * SPDX-FileCopyrightText: (C) 2017 Atul Sharma <atulsharma406@gmail.com>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.1-or-later
0006  */
0007 
0008 #include <QQmlApplicationEngine>
0009 #include <QQmlComponent>
0010 #include <QQmlContext>
0011 
0012 #include <QDebug>
0013 #include <QDir>
0014 #include <QStandardPaths>
0015 #include <QThread>
0016 
0017 #include <KAboutData>
0018 #include <KDBusService>
0019 #include <KLocalizedContext>
0020 #include <KLocalizedString>
0021 #include <KWindowSystem>
0022 
0023 #include <QApplication>
0024 #include <QCommandLineOption>
0025 #include <QCommandLineParser>
0026 #include <QQuickView>
0027 
0028 #include <iostream>
0029 
0030 #include "controller.h"
0031 #include "filesystemtracker.h"
0032 #include "imagestorage.h"
0033 #include "kokoconfig.h"
0034 #include "openfilemodel.h"
0035 #include "processor.h"
0036 #include "vectorimage.h"
0037 #include "version.h"
0038 
0039 #ifndef Q_OS_ANDROID
0040 #include <KConfigGroup>
0041 #include <KSharedConfig>
0042 #include <KWindowConfig>
0043 #include <QQuickWindow>
0044 #else
0045 #include <QtAndroid>
0046 #endif
0047 
0048 int main(int argc, char **argv)
0049 {
0050     QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
0051     QApplication app(argc, argv);
0052     KLocalizedString::setApplicationDomain("koko");
0053     app.setApplicationDisplayName("Koko");
0054     app.setOrganizationDomain("kde.org");
0055 
0056     KAboutData aboutData(QStringLiteral("koko"),
0057                          xi18nc("@title", "<application>Koko</application>"),
0058                          QStringLiteral(KOKO_VERSION_STRING),
0059                          xi18nc("@title", "Koko is an image viewer for your image collection."),
0060                          KAboutLicense::LGPL,
0061                          xi18nc("@info:credit", "(c) 2013-2020 KDE Contributors"));
0062 
0063     aboutData.setOrganizationDomain(QByteArray("kde.org"));
0064     aboutData.setProductName(QByteArray("koko"));
0065     aboutData.setBugAddress("https://bugs.kde.org/describecomponents.cgi?product=koko");
0066 
0067     aboutData.addAuthor(xi18nc("@info:credit", "Vishesh Handa"), xi18nc("@info:credit", "Developer"), "vhanda@kde.org");
0068 
0069     aboutData.addAuthor(xi18nc("@info:credit", "Atul Sharma"), xi18nc("@info:credit", "Developer"), "atulsharma406@gmail.com");
0070 
0071     aboutData.addAuthor(xi18nc("@info:credit", "Marco Martin"), xi18nc("@info:credit", "Developer"), "mart@kde.org");
0072 
0073     aboutData.addAuthor(xi18nc("@info:credit", "Nicolas Fella"), xi18nc("@info:credit", "Developer"), "nicolas.fella@gmx.de");
0074 
0075     aboutData.addAuthor(xi18nc("@info:credit", "Carl Schwan"), xi18nc("@info:credit", "Developer"), "carl@carlschwan.eu");
0076 
0077     aboutData.addAuthor(xi18nc("@info:credit", "Mikel Johnson"), xi18nc("@info:credit", "Developer"), "mikel5764@gmail.com");
0078 
0079     KAboutData::setApplicationData(aboutData);
0080 
0081     KLocalizedString::setApplicationDomain("koko");
0082 
0083     QCommandLineParser parser;
0084     parser.setApplicationDescription(i18n("Image viewer"));
0085     parser.addOption(QCommandLineOption("reset", i18n("Reset the database")));
0086     parser.addPositionalArgument("image", i18n("path of image you want to open"));
0087 
0088     aboutData.setupCommandLine(&parser);
0089     parser.process(app);
0090     aboutData.processCommandLine(&parser);
0091 
0092     QApplication::setApplicationName(aboutData.componentName());
0093     QApplication::setApplicationDisplayName(aboutData.displayName());
0094     QApplication::setOrganizationDomain(aboutData.organizationDomain());
0095     QApplication::setApplicationVersion(aboutData.version());
0096     QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("koko")));
0097 
0098     if (parser.isSet("reset") || ImageStorage::shouldReset()) {
0099         ImageStorage::reset();
0100     }
0101 
0102     KDBusService service(KDBusService::Unique);
0103 
0104     QThread trackerThread;
0105 
0106     QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
0107     Q_ASSERT(locations.size() >= 1);
0108     qDebug() << locations;
0109 
0110     QUrl currentDirPath = QUrl::fromLocalFile(QDir::currentPath().append('/'));
0111 
0112     QStringList directoryUrls;
0113     for (const auto &path : parser.positionalArguments()) {
0114         directoryUrls << currentDirPath.resolved(path).toString();
0115     }
0116 
0117 #ifdef Q_OS_ANDROID
0118     QtAndroid::requestPermissionsSync({"android.permission.WRITE_EXTERNAL_STORAGE"});
0119 #endif
0120 
0121     FileSystemTracker tracker;
0122     tracker.setFolder(locations.first());
0123     tracker.moveToThread(&trackerThread);
0124 
0125     Koko::Processor processor;
0126     QObject::connect(&tracker, &FileSystemTracker::imageAdded, &processor, &Koko::Processor::addFile);
0127     QObject::connect(&tracker, &FileSystemTracker::imageRemoved, &processor, &Koko::Processor::removeFile);
0128     QObject::connect(&tracker, &FileSystemTracker::initialScanComplete, &processor, &Koko::Processor::initialScanCompleted);
0129 
0130     QObject::connect(&trackerThread, &QThread::started, &tracker, &FileSystemTracker::setupDb);
0131 
0132     trackerThread.start();
0133     tracker.setSubFolder(tracker.folder());
0134 
0135     KokoConfig config;
0136     // General group
0137     QObject::connect(&config, &KokoConfig::IconSizeChanged, &config, &KokoConfig::save);
0138     QObject::connect(&config, &KokoConfig::ImageViewPreviewChanged, &config, &KokoConfig::save);
0139     QObject::connect(&config, &KokoConfig::SavedFoldersChanged, &config, &KokoConfig::save);
0140     // Slideshow group
0141     QObject::connect(&config, &KokoConfig::NextImageIntervalChanged, &config, &KokoConfig::save);
0142     QObject::connect(&config, &KokoConfig::LoopImagesChanged, &config, &KokoConfig::save);
0143     QObject::connect(&config, &KokoConfig::RandomizeImagesChanged, &config, &KokoConfig::save);
0144     // KokoConfig WindowState group
0145     QObject::connect(&config, &KokoConfig::WidthChanged, &config, &KokoConfig::save);
0146     QObject::connect(&config, &KokoConfig::HeightChanged, &config, &KokoConfig::save);
0147     QObject::connect(&config, &KokoConfig::VisibilityChanged, &config, &KokoConfig::save);
0148     QObject::connect(&config, &KokoConfig::ControlsVisibleChanged, &config, &KokoConfig::save);
0149 
0150     QQmlApplicationEngine engine;
0151     engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
0152 
0153     OpenFileModel openFileModel(directoryUrls);
0154     QObject::connect(&service,
0155                      &KDBusService::activateRequested,
0156                      &openFileModel,
0157                      [&openFileModel, &parser, &engine](const QStringList &arguments, const QString &workingDirectory) {
0158                          QUrl currentDirPath = QUrl::fromLocalFile(workingDirectory);
0159 
0160                          parser.parse(arguments);
0161 
0162                          QStringList directoryUrls;
0163                          for (const auto &path : parser.positionalArguments()) {
0164                              directoryUrls << currentDirPath.resolved(path).toString();
0165                          }
0166 
0167                          openFileModel.updateOpenFiles(directoryUrls);
0168 
0169                          const auto rootObjects = engine.rootObjects();
0170                          for (auto obj : rootObjects) {
0171                              auto window = qobject_cast<QQuickWindow *>(obj);
0172                              if (window) {
0173                                  KWindowSystem::updateStartupId(window);
0174                                  KWindowSystem::activateWindow(window);
0175                                  return;
0176                              }
0177                          }
0178                      });
0179 
0180     qmlRegisterSingletonInstance("org.kde.koko.private", 0, 1, "OpenFileModel", &openFileModel);
0181     qmlRegisterType<VectorImage>("org.kde.koko.image", 0, 1, "VectorImage");
0182 
0183     Controller controller;
0184     qmlRegisterSingletonInstance("org.kde.koko.private", 0, 1, "Controller", &controller);
0185 
0186     engine.rootContext()->setContextProperty("kokoProcessor", &processor);
0187     engine.rootContext()->setContextProperty("kokoConfig", &config);
0188     engine.rootContext()->setContextProperty(QStringLiteral("kokoAboutData"), QVariant::fromValue(aboutData));
0189 
0190     QString path;
0191     // we want different main files on desktop or mobile
0192     // very small difference as they as they are subclasses of the same thing
0193     engine.load(QUrl(QStringLiteral("qrc:/qml/Main.qml")));
0194 
0195 #ifndef Q_OS_ANDROID
0196     const auto rootObjects = engine.rootObjects();
0197     for (auto obj : rootObjects) {
0198         auto view = qobject_cast<QQuickWindow *>(obj);
0199         if (view) {
0200             KConfig dataResource(QStringLiteral("data"), KConfig::SimpleConfig, QStandardPaths::AppDataLocation);
0201             KConfigGroup windowGroup(&dataResource, "Window");
0202             KWindowConfig::restoreWindowSize(view, windowGroup);
0203             KWindowConfig::restoreWindowPosition(view, windowGroup);
0204             break;
0205         }
0206     }
0207 #endif
0208 
0209     int rt = app.exec();
0210     trackerThread.quit();
0211     return rt;
0212 }