File indexing completed on 2023-10-03 11:33:25
0001 // SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu> 0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 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 #include <QtWebView> 0013 #include <clocale> 0014 0015 #ifdef Q_OS_ANDROID 0016 #include "utils/androidutils.h" 0017 #include <QGuiApplication> 0018 #else 0019 #include <QApplication> 0020 #endif 0021 0022 #include <KAboutData> 0023 #ifdef HAVE_KDBUSADDONS 0024 #include <KDBusService> 0025 #include <KWindowSystem> 0026 #endif 0027 #include <KConfig> 0028 #include <KLocalizedContext> 0029 #include <KLocalizedString> 0030 #include <KWindowConfig> 0031 0032 #include "tokodon-version.h" 0033 0034 #include "account/accountmanager.h" 0035 #include "accountconfig.h" 0036 #include "config.h" 0037 #include "network/networkaccessmanagerfactory.h" 0038 #include "network/networkcontroller.h" 0039 #include "utils/blurhashimageprovider.h" 0040 #include "utils/colorschemer.h" 0041 #include "utils/navigation.h" 0042 0043 #ifdef Q_OS_WINDOWS 0044 #include <Windows.h> 0045 #endif 0046 0047 #ifdef TEST_MODE 0048 #include "autotests/helperreply.h" 0049 #include "autotests/mockaccount.h" 0050 #endif 0051 0052 using namespace Qt::Literals::StringLiterals; 0053 0054 #ifdef Q_OS_ANDROID 0055 Q_DECL_EXPORT 0056 #endif 0057 int main(int argc, char *argv[]) 0058 { 0059 QNetworkProxyFactory::setUseSystemConfiguration(true); 0060 QtWebView::initialize(); 0061 0062 #ifdef Q_OS_ANDROID 0063 QGuiApplication app(argc, argv); 0064 app.connect(&app, &QGuiApplication::applicationStateChanged, [](Qt::ApplicationState state) { 0065 if (state == Qt::ApplicationActive) { 0066 AndroidUtils::instance().checkPendingIntents(); 0067 } 0068 }); 0069 QQuickStyle::setStyle(QStringLiteral("org.kde.breeze")); 0070 #else 0071 QApplication app(argc, argv); 0072 // Default to org.kde.desktop style unless the user forces another style 0073 if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) { 0074 QQuickStyle::setStyle(QStringLiteral("org.kde.desktop")); 0075 } 0076 #endif 0077 0078 #ifdef Q_OS_WINDOWS 0079 if (AttachConsole(ATTACH_PARENT_PROCESS)) { 0080 freopen("CONOUT$", "w", stdout); 0081 freopen("CONOUT$", "w", stderr); 0082 } 0083 0084 QApplication::setStyle(QStringLiteral("breeze")); 0085 auto font = app.font(); 0086 font.setPointSize(10); 0087 app.setFont(font); 0088 #endif 0089 KLocalizedString::setApplicationDomain("tokodon"); 0090 0091 QCoreApplication::setOrganizationName(QStringLiteral("KDE")); 0092 0093 KAboutData about(QStringLiteral("tokodon"), 0094 i18n("Tokodon"), 0095 QStringLiteral(TOKODON_VERSION_STRING), 0096 i18n("Mastodon client"), 0097 KAboutLicense::GPL_V3, 0098 i18n("© 2021-2023 Carl Schwan, 2021-2023 KDE Community")); 0099 about.addAuthor(i18n("Carl Schwan"), 0100 i18n("Maintainer"), 0101 QStringLiteral("carl@carlschwan.eu"), 0102 QStringLiteral("https://carlschwan.eu"), 0103 QStringLiteral("https://carlschwan.eu/avatar.png")); 0104 about.addAuthor(i18n("Joshua Goins"), 0105 i18n("Maintainer"), 0106 QStringLiteral("josh@redstrate.com"), 0107 QStringLiteral("https://redstrate.com/"), 0108 QStringLiteral("https://redstrate.com/rss-image.png")); 0109 about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); 0110 about.setOrganizationDomain("kde.org"); 0111 about.setBugAddress("https://bugs.kde.org/describecomponents.cgi?product=tokodon"); 0112 0113 KAboutData::setApplicationData(about); 0114 QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("org.kde.tokodon"))); 0115 0116 QCommandLineParser parser; 0117 parser.setApplicationDescription(i18n("Client for the decentralized social network: mastodon")); 0118 parser.addPositionalArgument(QStringLiteral("urls"), i18n("Supports web+ap: url scheme")); 0119 0120 QCommandLineOption shareOption(QStringLiteral("share"), i18n("Share a line of text in the standalone composer."), i18n("The text to share.")); 0121 parser.addOption(shareOption); 0122 0123 about.setupCommandLine(&parser); 0124 parser.process(app); 0125 about.processCommandLine(&parser); 0126 0127 // Qt sets the locale in the QGuiApplication constructor, but libmpv 0128 // requires the LC_NUMERIC category to be set to "C", so change it back. 0129 setlocale(LC_NUMERIC, "C"); 0130 0131 auto &colorSchemer = ColorSchemer::instance(); 0132 auto config = Config::self(); 0133 if (!config->colorScheme().isEmpty()) { 0134 colorSchemer.apply(config->colorScheme()); 0135 } 0136 0137 qmlRegisterSingletonInstance("org.kde.tokodon.private", 1, 0, "Config", config); 0138 qmlRegisterUncreatableType<AccountConfig>("org.kde.tokodon.private", 1, 0, "AccountConfig", QStringLiteral("Use via Account.config")); 0139 0140 QQmlApplicationEngine engine; 0141 #ifdef HAVE_KDBUSADDONS 0142 KDBusService service(KDBusService::Unique); 0143 QObject::connect(&service, &KDBusService::activateRequested, &engine, [&engine](const QStringList &arguments, const QString & /*workingDirectory*/) { 0144 const auto rootObjects = engine.rootObjects(); 0145 for (auto obj : rootObjects) { 0146 if (auto view = qobject_cast<QQuickWindow *>(obj)) { 0147 KWindowSystem::updateStartupId(view); 0148 KWindowSystem::activateWindow(view); 0149 0150 if (arguments.isEmpty()) { 0151 return; 0152 } 0153 0154 auto args = arguments; 0155 args.removeFirst(); 0156 0157 if (arguments.length() >= 1) { 0158 if (args[0].startsWith("web+ap"_L1)) { 0159 NetworkController::instance().openWebApLink(args[0]); 0160 } else { 0161 NetworkController::instance().setAuthCode(QUrl(args[0])); 0162 } 0163 if (args[0] == "--share"_L1) { 0164 NetworkController::instance().startComposing(args[1]); 0165 } else { 0166 NetworkController::instance().openWebApLink(args[0]); 0167 } 0168 } 0169 0170 return; 0171 } 0172 } 0173 }); 0174 #endif 0175 engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); 0176 QObject::connect(&engine, &QQmlApplicationEngine::quit, &app, &QCoreApplication::quit); 0177 0178 NetworkAccessManagerFactory namFactory; 0179 engine.setNetworkAccessManagerFactory(&namFactory); 0180 0181 engine.addImageProvider(QLatin1String("blurhash"), new BlurhashImageProvider); 0182 0183 #ifdef TEST_MODE 0184 AccountManager::instance().setTestMode(true); 0185 0186 auto account = new MockAccount(); 0187 AccountManager::instance().addAccount(account, true); 0188 AccountManager::instance().selectAccount(account); 0189 0190 QUrl url = account->apiUrl(QStringLiteral("/api/v2/search")); 0191 url.setQuery(QUrlQuery{{QStringLiteral("q"), QStringLiteral("myquery")}}); 0192 account->registerGet(url, new TestReply(QStringLiteral("search-result.json"), account)); 0193 0194 account->registerGet(account->apiUrl(QStringLiteral("/api/v1/timelines/home")), new TestReply(QStringLiteral("statuses.json"), account)); 0195 #else 0196 AccountManager::instance().migrateSettings(); 0197 AccountManager::instance().loadFromSettings(); 0198 #endif 0199 0200 if (parser.isSet(shareOption)) { 0201 engine.loadFromModule("org.kde.tokodon", "StandaloneComposer"); 0202 0203 NetworkController::instance().startComposing(parser.value(shareOption)); 0204 } else { 0205 engine.loadFromModule("org.kde.tokodon", "Main"); 0206 0207 if (parser.positionalArguments().length() > 0) { 0208 NetworkController::instance().openWebApLink(parser.positionalArguments()[0]); 0209 } 0210 } 0211 0212 if (engine.rootObjects().isEmpty()) { 0213 return -1; 0214 } 0215 #ifdef HAVE_KDBUSADDONS 0216 const auto rootObjects = engine.rootObjects(); 0217 for (auto obj : rootObjects) { 0218 auto view = qobject_cast<QQuickWindow *>(obj); 0219 if (view) { 0220 KConfig dataResource(QStringLiteral("data"), KConfig::SimpleConfig, QStandardPaths::AppDataLocation); 0221 KConfigGroup windowGroup(&dataResource, "Window"); 0222 KWindowConfig::restoreWindowSize(view, windowGroup); 0223 KWindowConfig::restoreWindowPosition(view, windowGroup); 0224 break; 0225 } 0226 } 0227 #endif 0228 return QCoreApplication::exec(); 0229 }