File indexing completed on 2024-05-12 04:55:01
0001 /** 0002 * \file mainqml.cpp 0003 * Main program. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 7 Jun 2014 0008 * 0009 * Copyright (C) 2014-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #include <QFile> 0028 #include <QApplication> 0029 #include <QTranslator> 0030 #include <QDir> 0031 #include <QSettings> 0032 #if !defined NDEBUG && !defined QT_QML_DEBUG 0033 #define QT_QML_DEBUG 0034 #endif 0035 #include <QQmlApplicationEngine> 0036 #include <QQuickStyle> 0037 #if QT_VERSION > 0x060200 && defined Q_OS_ANDROID 0038 #include <QtCore/private/qandroidextras_p.h> 0039 #endif 0040 #include <typeinfo> 0041 #include "config.h" 0042 #include "loadtranslation.h" 0043 #include "kid3application.h" 0044 0045 namespace { 0046 0047 /** 0048 * QApplication subclass with adapted session management. 0049 */ 0050 class Kid3QtApplication : public QApplication { 0051 public: 0052 /** 0053 * Constructor. 0054 * @param argc number of arguments (including command) 0055 * @param argv arguments 0056 */ 0057 Kid3QtApplication(int& argc, char** argv) : QApplication(argc, argv) {} 0058 0059 /** 0060 * Destructor. 0061 */ 0062 ~Kid3QtApplication() override = default; 0063 0064 /** 0065 * Called when session manager wants application to commit all its data. 0066 * 0067 * This method is reimplemented to avoid closing all top level widgets and 0068 * make restoring with the KDE window manager working. 0069 * 0070 * @param manager session manager 0071 */ 0072 virtual void commitData(QSessionManager& manager) { 0073 emit commitDataRequest(manager); 0074 } 0075 0076 /** 0077 * Send event to receiver. 0078 * @param receiver receiver 0079 * @param event event 0080 * @return return value from receiver's event handler. 0081 */ 0082 bool notify(QObject* receiver, QEvent* event) override; 0083 }; 0084 0085 /** 0086 * Send event to receiver. 0087 * @param receiver receiver 0088 * @param event event 0089 * @return return value from receiver's event handler. 0090 */ 0091 bool Kid3QtApplication::notify(QObject* receiver, QEvent* event) 0092 { 0093 try { 0094 return QApplication::notify(receiver, event); 0095 } catch (std::exception& ex) { 0096 qWarning("Exception %s (%s) was caught", typeid(ex).name(), ex.what()); 0097 } 0098 return false; 0099 } 0100 0101 } 0102 0103 /** 0104 * Main program. 0105 * 0106 * @param argc number of arguments including command name 0107 * @param argv arguments, argv[0] is command name 0108 * 0109 * @return exit code of application. 0110 */ 0111 0112 int main(int argc, char* argv[]) 0113 { 0114 #ifdef HAVE_QMLDIR_IN_QRC 0115 Q_INIT_RESOURCE(qmlapp); 0116 #endif 0117 #ifdef HAVE_TRANSLATIONSDIR_IN_QRC 0118 Q_INIT_RESOURCE(translations); 0119 #endif 0120 0121 #if QT_VERSION > 0x060200 && defined Q_OS_ANDROID 0122 const QString storagePermission = 0123 QLatin1String("android.permission.WRITE_EXTERNAL_STORAGE"); 0124 auto permissionResult = 0125 QtAndroidPrivate::checkPermission(storagePermission).result(); 0126 if (permissionResult != QtAndroidPrivate::Authorized) { 0127 permissionResult = 0128 QtAndroidPrivate::requestPermission(storagePermission).result(); 0129 } 0130 #endif 0131 0132 QCoreApplication::setApplicationName(QLatin1String("Kid3")); 0133 #if QT_VERSION < 0x060000 0134 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 0135 #endif 0136 0137 // The QtQuickStyle setting has to be read bypassing the regular 0138 // configuration object because the style environment variable 0139 // must be set before the QGuiApplication is created. 0140 auto style = QSettings(QSettings::UserScope, QLatin1String("Kid3"), 0141 QLatin1String("Kid3")) 0142 .value(QLatin1String("MainWindow/QtQuickStyle")).toByteArray(); 0143 auto configuredLanguage = QSettings( 0144 QSettings::UserScope, QLatin1String("Kid3"), QLatin1String("Kid3")) 0145 .value(QLatin1String("MainWindow/Language")).toString(); 0146 if (style.isEmpty()) { 0147 #ifdef Q_OS_ANDROID 0148 style = "Material/Light"; 0149 #else 0150 style = "Default"; 0151 #endif 0152 } 0153 auto styleTheme = style.split('/'); 0154 style = styleTheme.at(0); 0155 if (!style.isEmpty()) { 0156 qputenv("QT_QUICK_CONTROLS_STYLE", style); 0157 } 0158 auto theme = styleTheme.size() > 1 ? styleTheme.at(1) : ""; 0159 if (!theme.isEmpty() && style == "Material") { 0160 qputenv("QT_QUICK_CONTROLS_MATERIAL_THEME", theme); 0161 } 0162 0163 Kid3QtApplication app(argc, argv); 0164 Utils::loadTranslation(configuredLanguage); 0165 #ifdef Q_OS_MAC 0166 QDir dir(QCoreApplication::applicationDirPath()); 0167 dir.cdUp(); 0168 dir.cd(QLatin1String("PlugIns")); 0169 QCoreApplication::setLibraryPaths(QStringList(dir.absolutePath())); 0170 #endif 0171 0172 QStringList qmlDirs; 0173 #if !defined NDEBUG && defined CFG_QMLSRCDIR 0174 qmlDirs.append(QLatin1String(CFG_QMLSRCDIR)); 0175 #endif 0176 #ifdef CFG_QMLDIR 0177 qmlDirs.append(QLatin1String(CFG_QMLDIR)); 0178 #endif 0179 QString mainQmlPath; 0180 const auto constQmlDirs = qmlDirs; 0181 for (const QString& qmlDir : constQmlDirs) { 0182 QString qmlPath(qmlDir); 0183 Utils::prependApplicationDirPathIfRelative(qmlPath); 0184 qmlPath += QDir::separator(); 0185 qmlPath += QLatin1String("app"); 0186 qmlPath += QDir::separator(); 0187 qmlPath += QLatin1String("Main.qml"); 0188 if (QFile::exists(qmlPath)) { 0189 mainQmlPath = qmlPath; 0190 break; 0191 } 0192 } 0193 if (mainQmlPath.isEmpty()) { 0194 qWarning("Could not find app/Main.qml in the following paths:\n%s", 0195 qPrintable(qmlDirs.join(QLatin1String("\n")))); 0196 return 1; 0197 } 0198 0199 QQmlApplicationEngine engine; 0200 #ifdef HAVE_QMLDIR_IN_QRC 0201 engine.addImportPath(QLatin1String(CFG_QMLDIR "imports")); 0202 QDir pluginsDir; 0203 if (Kid3Application::findPluginsDirectory(pluginsDir) && 0204 pluginsDir.cd(QLatin1String("imports/Kid3"))) { 0205 engine.addPluginPath(pluginsDir.absolutePath()); 0206 } 0207 engine.load(QUrl(QLatin1String("qrc:///app/Main.qml"))); 0208 #else 0209 QDir pluginsDir; 0210 if (Kid3Application::findPluginsDirectory(pluginsDir) && 0211 pluginsDir.cd(QLatin1String("imports"))) { 0212 engine.addImportPath(pluginsDir.absolutePath()); 0213 } 0214 engine.load(QUrl::fromLocalFile(mainQmlPath)); 0215 #endif 0216 return QApplication::exec(); 0217 }