File indexing completed on 2024-05-12 04:55:39
0001 /** 0002 * \file kid3qmlplugin.cpp 0003 * QML plugin for Kid3 application. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 19 Sep 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 "kid3qmlplugin.h" 0028 #include <QCoreApplication> 0029 #include <QQmlComponent> 0030 #include <QQmlContext> 0031 #include "kid3application.h" 0032 #include "guiplatformtools.h" 0033 #include "qmlimageprovider.h" 0034 #include "fileproxymodel.h" 0035 #include "dirproxymodel.h" 0036 #include "genremodel.h" 0037 #include "frametablemodel.h" 0038 #include "framelist.h" 0039 #include "frameeditorobject.h" 0040 #include "frameobjectmodel.h" 0041 #include "taggedfileselection.h" 0042 #include "scriptutils.h" 0043 #include "configobjects.h" 0044 #include "formatconfig.h" 0045 #include "playlistconfig.h" 0046 #include "tagconfig.h" 0047 #include "checkablelistmodel.h" 0048 #include "dirrenamer.h" 0049 #include "filefilter.h" 0050 #include "batchimporter.h" 0051 #include "downloadclient.h" 0052 #include "config.h" 0053 #ifdef HAVE_QTMULTIMEDIA 0054 #include "audioplayer.h" 0055 #endif 0056 0057 Q_DECLARE_METATYPE(Kid3Application*) 0058 Q_DECLARE_METATYPE(QAbstractItemModel*) 0059 Q_DECLARE_METATYPE(FileProxyModel*) 0060 Q_DECLARE_METATYPE(DirProxyModel*) 0061 Q_DECLARE_METATYPE(GenreModel*) 0062 Q_DECLARE_METATYPE(FrameTableModel*) 0063 Q_DECLARE_METATYPE(FrameList*) 0064 Q_DECLARE_METATYPE(FrameEditorObject*) 0065 Q_DECLARE_METATYPE(FrameObjectModel*) 0066 Q_DECLARE_METATYPE(TaggedFileSelectionTagContext*) 0067 Q_DECLARE_METATYPE(TaggedFileSelection*) 0068 Q_DECLARE_METATYPE(QList<QPersistentModelIndex>) 0069 Q_DECLARE_METATYPE(Frame::TagVersion) 0070 Q_DECLARE_METATYPE(Frame::TagNumber) 0071 Q_DECLARE_METATYPE(Frame) 0072 Q_DECLARE_METATYPE(ScriptUtils*) 0073 Q_DECLARE_METATYPE(ConfigObjects*) 0074 Q_DECLARE_METATYPE(CheckableListModel*) 0075 Q_DECLARE_METATYPE(QItemSelectionModel*) 0076 Q_DECLARE_METATYPE(DirRenamer*) 0077 Q_DECLARE_METATYPE(BatchImporter*) 0078 Q_DECLARE_METATYPE(DownloadClient*) 0079 Q_DECLARE_METATYPE(Kid3ApplicationTagContext*) 0080 #ifdef HAVE_QTMULTIMEDIA 0081 Q_DECLARE_METATYPE(AudioPlayer*) 0082 #endif 0083 0084 namespace { 0085 0086 /** 0087 * Get the plugins path from the QML import path. 0088 * 0089 * The plugins path is normally found relative to the directory where the 0090 * application binary is located. However, when the application is started 0091 * from a QML script using qmlscene, the path plugins path cannot be found 0092 * from the location of qmlscene. In this case, the plugins path can be 0093 * derived from the QML import path, which contains the Kid3 QML plugin. 0094 * 0095 * @param engine QML engine 0096 * @return plugins directory path, empty if not found. 0097 */ 0098 QString getPluginsPathFromImportPathList(const QQmlEngine* engine) 0099 { 0100 QString cfgPluginsDir(QLatin1String(CFG_PLUGINSDIR)); 0101 if (cfgPluginsDir.startsWith(QLatin1String("./"))) { 0102 cfgPluginsDir.remove(0, 2); 0103 } else if (cfgPluginsDir.startsWith(QLatin1String("../"))) { 0104 cfgPluginsDir.remove(0, 3); 0105 } 0106 0107 QString pluginsPath; 0108 const auto paths = engine->importPathList(); 0109 for (const QString& path : paths) { 0110 if (int index = path.indexOf(cfgPluginsDir); index != -1) { 0111 pluginsPath = path.left(index + cfgPluginsDir.length()); 0112 break; 0113 } else if (pluginsPath.isEmpty() && 0114 (index = path.indexOf(QLatin1String("plugins"))) != -1) { 0115 pluginsPath = path.left(index + 7); 0116 // Probably a path in the build directory, use it if CFG_PLUGINSDIR is 0117 // not found. 0118 } 0119 } 0120 return pluginsPath; 0121 } 0122 0123 } 0124 0125 /** 0126 * Constructor. 0127 * @param parent parent object 0128 */ 0129 Kid3QmlPlugin::Kid3QmlPlugin(QObject* parent) 0130 : QQmlExtensionPlugin(parent), 0131 m_platformTools(nullptr), m_kid3App(nullptr), m_imageProvider(nullptr), 0132 m_ownsKid3App(false) 0133 { 0134 } 0135 0136 /** 0137 * Destructor. 0138 */ 0139 Kid3QmlPlugin::~Kid3QmlPlugin() 0140 { 0141 if (m_ownsKid3App) { 0142 delete m_kid3App; 0143 delete m_platformTools; 0144 } 0145 } 0146 0147 /** 0148 * Register the types used by the QML plugin. 0149 * @param uri URI of imported module, must be "Kid3" 0150 */ 0151 void Kid3QmlPlugin::registerTypes(const char *uri) 0152 { 0153 if (qstrcmp(uri, "Kid3") == 0) { 0154 qRegisterMetaType<QList<QPersistentModelIndex> >(); 0155 qRegisterMetaType<Frame::TagVersion>(); 0156 qRegisterMetaType<Frame::TagNumber>(); 0157 qRegisterMetaType<QAbstractItemModel*>(); 0158 // @uri Kid3 0159 qmlRegisterUncreatableType<Kid3Application>(uri, 1, 1, "Kid3Application", 0160 QLatin1String("Retrieve it using app")); 0161 qmlRegisterUncreatableType<FileProxyModel>(uri, 1, 0, "FileProxyModel", 0162 QLatin1String("Retrieve it using app.fileProxyModel")); 0163 qmlRegisterUncreatableType<DirProxyModel>(uri, 1, 0, "DirProxyModel", 0164 QLatin1String("Retrieve it using app.dirProxyModel")); 0165 qmlRegisterUncreatableType<GenreModel>(uri, 1, 0, "GenreModel", 0166 QLatin1String("Retrieve it using app.tag().genreModel")); 0167 qmlRegisterUncreatableType<FrameTableModel>(uri, 1, 0, "FrameTableModel", 0168 QLatin1String("Retrieve it using app.tag().frameModel")); 0169 qmlRegisterUncreatableType<FrameList>(uri, 1, 0, "FrameList", 0170 QLatin1String("Retrieve it using app.tag().frameList")); 0171 qmlRegisterType<FrameEditorObject>(uri, 1, 0, "FrameEditorObject"); 0172 qmlRegisterUncreatableType<FrameObjectModel>(uri, 1, 0, "FrameObjectModel", 0173 QLatin1String("Argument of FrameEditorObject.frameEditFinished()")); 0174 qmlRegisterUncreatableType<TaggedFileSelection>( 0175 uri, 1, 0, "TaggedFileSelection", 0176 QLatin1String("Retrieve it using app.selectionInfo")); 0177 qmlRegisterUncreatableType<TaggedFileSelectionTagContext>(uri, 1, 0, 0178 "TaggedFileSelectionTagContext", 0179 QLatin1String("Retrieve it using app.selectionInfo.tag()")); 0180 qmlRegisterUncreatableType<QItemSelectionModel>( 0181 uri, 1, 0, "QItemSelectionModel", 0182 QLatin1String("Retrieve it using app.fileSelectionModel")); 0183 qmlRegisterType<ScriptUtils>(uri, 1, 0, "ScriptUtils"); 0184 qmlRegisterType<ConfigObjects>(uri, 1, 0, "ConfigObjects"); 0185 qmlRegisterType<CheckableListModel>(uri, 1, 0, "CheckableListModel"); 0186 qmlRegisterUncreatableType<Frame>(uri, 1, 0, "Frame", 0187 QLatin1String("Only enum container")); 0188 qmlRegisterUncreatableType<FrameNotice>(uri, 1, 0, "FrameNotice", 0189 QLatin1String("Only enum container")); 0190 qmlRegisterUncreatableType<FormatConfig>( 0191 uri, 1, 0, "FormatConfig", QLatin1String("Only enum container")); 0192 qmlRegisterUncreatableType<PlaylistConfig>( 0193 uri, 1, 0, "PlaylistConfig", QLatin1String("Only enum container")); 0194 qmlRegisterUncreatableType<TagConfig>( 0195 uri, 1, 0, "TagConfig", QLatin1String("Only enum container")); 0196 qmlRegisterUncreatableType<DirRenamer>(uri, 1, 0, "DirRenamer", 0197 QLatin1String("Retrieve it using app.dirRenamer")); 0198 qmlRegisterUncreatableType<FileFilter>( 0199 uri, 1, 0, "FileFilter", QLatin1String("Only enum container")); 0200 qmlRegisterUncreatableType<BatchImporter>(uri, 1, 0, "BatchImporter", 0201 QLatin1String("Retrieve it using app.batchImporter")); 0202 qmlRegisterUncreatableType<DownloadClient>(uri, 1, 0, "DownloadClient", 0203 QLatin1String("Retrieve it using app.downloadClient")); 0204 qmlRegisterUncreatableType<Kid3ApplicationTagContext>(uri, 1, 0, 0205 "Kid3ApplicationTagContext", 0206 QLatin1String("Retrieve it using app.tag()")); 0207 #ifdef HAVE_QTMULTIMEDIA 0208 qmlRegisterUncreatableType<AudioPlayer>(uri, 1, 0, "AudioPlayer", 0209 QLatin1String("Retrieve it using app.getAudioPlayer()")); 0210 #endif 0211 } 0212 } 0213 0214 /** 0215 * Initialize the QML engine when the plugin is imported. 0216 * @param engine QML engine 0217 * @param uri URI of imported module, must be "Kid3" 0218 */ 0219 void Kid3QmlPlugin::initializeEngine(QQmlEngine* engine, const char* uri) 0220 { 0221 if (qstrcmp(uri, "Kid3") == 0) { 0222 Kid3Application::setPluginsPathFallback( 0223 getPluginsPathFromImportPathList(engine)); 0224 QQmlContext* rootContext = engine->rootContext(); 0225 m_kid3App = qvariant_cast<Kid3Application*>( 0226 rootContext->contextProperty(QLatin1String("app"))); 0227 if (!m_kid3App) { 0228 m_platformTools = new GuiPlatformTools; 0229 m_kid3App = new Kid3Application(m_platformTools); 0230 m_ownsKid3App = true; 0231 rootContext->setContextProperty(QLatin1String("app"), m_kid3App); 0232 } 0233 if (!m_imageProvider) { 0234 m_imageProvider = new QmlImageProvider( 0235 m_kid3App->getFileProxyModel()->getIconProvider()); 0236 } 0237 m_kid3App->setImageProvider(m_imageProvider); 0238 // The QQmlEngine takes ownership of m_imageProvider. 0239 engine->addImageProvider(QLatin1String("kid3"), m_imageProvider); 0240 } 0241 }