Warning, /multimedia/kid3/src/plugins/kid3qml/Kid3Script.qml is written in an unsupported language. File is not indexed.

0001 /**
0002  * \file Kid3Script.qml
0003  * Base component for Kid3 user command scripts.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 27 Feb 2015
0008  *
0009  * Copyright (C) 2015-2024  Urs Fleisch
0010  *
0011  * This program is free software; you can redistribute it and/or modify
0012  * it under the terms of the GNU Lesser General Public License as published by
0013  * the Free Software Foundation; version 3.
0014  *
0015  * This program is distributed in the hope that it will be useful,
0016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018  * GNU Lesser General Public License for more details.
0019  *
0020  * You should have received a copy of the GNU Lesser General Public License
0021  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022  */
0023 
0024 import QtQml 2.2 //@QtQuick2
0025 //import QtQuick 2.2 //@QtQuick1
0026 import Kid3 1.0
0027 
0028 /**
0029  * @qmltype Kid3Script
0030  * @brief Base component for Kid3 user command scripts.
0031  *
0032  * This component can be used to write scripts which can be started as
0033  * user commands from Kid3 or started stand-alone using qml.
0034  * A minimal script could be:
0035  *
0036  * @code
0037  * import Kid3 1.0
0038  *
0039  * Kid3Script {
0040  *   onRun: {
0041  *     console.log("Hello world")
0042  *     Qt.quit()
0043  *   }
0044  * }
0045  * @endcode
0046  */
0047 Timer {
0048   id: timer
0049   signal run
0050 
0051   /**
0052    * tagv1, tagv2, tagv2v1 can be used for the tag version with both
0053    * QtQuick 1 (Qt 4) and QtQuick 2 (Qt 5).
0054    * QtQuick 1 needs the enum types from C++, so a helper function is used.
0055    */
0056   //property variant tagv1: script.toTagVersion(Frame.TagV1) //@QtQuick1
0057   //property variant tagv2: script.toTagVersion(Frame.TagV2) //@QtQuick1
0058   //property variant tagv3: script.toTagVersion(Frame.TagV3) //@QtQuick1
0059   //property variant tagv2v1: script.toTagVersion(Frame.TagV2V1) //@QtQuick1
0060   readonly property int tagv1: Frame.TagV1 //@QtQuick2
0061   readonly property int tagv2: Frame.TagV2 //@QtQuick2
0062   readonly property int tagv3: Frame.TagV3 //@QtQuick2
0063   readonly property int tagv2v1: Frame.TagV2V1 //@QtQuick2
0064   readonly property int tagvall: Frame.TagVAll //@QtQuick2
0065 
0066   // Container for sub module instances.
0067   property list<QtObject> _data: [
0068     ScriptUtils {
0069       id: _script
0070     },
0071     ConfigObjects {
0072       id: _configs
0073     }
0074   ]
0075 
0076   /** Access to ScriptUtils instance. */
0077   property alias script: _script
0078   /** Access to ConfigObjects instance. */
0079   property alias configs: _configs
0080 
0081   /** List of files to process with firstFile(), nextFile(). */
0082   property variant _paths: []
0083   /** Index of current file, -1 if _paths is not initialized yet. */
0084   property int _pathIndex: -1
0085 
0086   /**
0087    * Set list of files to process.
0088    * This function will be called by firstFile() if it has not been called
0089    * before. Calling it explicitly is only needed if the default file list
0090    * (from arguments if standalone, else from selected tagged files in file
0091    * list) is not appropriate.
0092    */
0093   function initFiles(paths) {
0094     _pathIndex = 0
0095     if (paths && paths.length > 0) {
0096       _paths = paths;
0097     } else if (isStandalone()) {
0098       _paths = getArguments();
0099     } else {
0100       _paths = app.getSelectedFilePaths();
0101     }
0102   }
0103 
0104   /**
0105    * To first file.
0106    * Will use the _paths list if available, else delegate to app.firstFile()
0107    * which will start iterating through all files.
0108    */
0109   function firstFile() {
0110     if (_pathIndex === -1) {
0111       initFiles()
0112     }
0113     if (_paths.length > 0) {
0114       _pathIndex = 0
0115       return nextFile()
0116     } else {
0117       return app.firstFile();
0118     }
0119   }
0120 
0121   /**
0122    * To next file.
0123    * firstFile() has to be called before. Returns false if at end of files.
0124    */
0125   function nextFile() {
0126     if (_paths.length > 0) {
0127       if (_pathIndex < _paths.length) {
0128         var path = _paths[_pathIndex++]
0129         return app.selectFile(path)
0130       } else {
0131         return false
0132       }
0133     } else  {
0134       return app.nextFile();
0135     }
0136   }
0137 
0138   /**
0139    * Get arguments after .qml script.
0140    * The arguments are passed to the script when the user command is
0141    * called from Kid3. In Qt 5, it is also possible to get arguments from
0142    * the command line when the script is invoked with qml or qmlscene.
0143    */
0144   function getArguments() {
0145     var params = []
0146     if (typeof args !== "undefined") {
0147       params = args.slice(0)
0148     } else if (Qt.application.arguments) {
0149       params = Qt.application.arguments.slice(0)
0150     }
0151     while (params.length > 0) {
0152       var p = params.shift()
0153       if (p.substr(-4) === ".qml") {
0154         if (params.length > 0 && params[0] === "--") {
0155           params.shift()
0156         }
0157         break
0158       }
0159     }
0160     return params
0161   }
0162 
0163   /**
0164    * Signal run() after the directory @a paths has been opened.
0165    * This function is used when the script is called stand-alone and
0166    * the directory is passed as a command line parameter.
0167    */
0168   function openDirectory(paths) {
0169     function onDirectoryOpened() {
0170       app.directoryOpened.disconnect(onDirectoryOpened)
0171       run()
0172     }
0173     app.directoryOpened.connect(onDirectoryOpened)
0174     app.openDirectory(paths)
0175   }
0176 
0177   /**
0178    * Check if script is running stand-alone, i.e. not in the Kid3 application.
0179    */
0180   function isStandalone() {
0181     return typeof args === "undefined"
0182   }
0183 
0184   /**
0185    * Main function.
0186    * When the script is run as a user command from Kid3, simply run() is
0187    * signalled. When the script is called from the command line, run() is
0188    * signalled after opening the directory.
0189    */
0190   function main() {
0191     if (!isStandalone()) {
0192       // Started as a user action from Kid3.
0193       run()
0194     } else {
0195       // Started as a QML script outside Kid3, start in current directory.
0196       app.selectedFilesUpdated.connect(app.tagsToFrameModels)
0197       app.selectedFilesChanged.connect(app.tagsToFrameModels)
0198       app.readConfig()
0199       openDirectory(".")
0200     }
0201   }
0202 
0203   /**
0204    * Invoke a callback with delay in ms and optional arguments.
0205    * This can be used to keep the GUI responsive by splitting the code
0206    * into asynchronous functions and call them after a small delay.
0207    */
0208   function setTimeout(callback, delay) {
0209     var argv = Array.prototype.slice.call(arguments, 2)
0210 
0211     function timeoutHandler() {
0212       triggered.disconnect(timeoutHandler)
0213       callback.apply(null, argv)
0214     }
0215 
0216     triggered.connect(timeoutHandler)
0217     interval = delay
0218     if (!running) {
0219       start()
0220     } else {
0221       // QtQuick 1 cannot restart a timer from a handler, see QTBUG-22004,
0222       // https://bugreports.qt.io/browse/QTBUG-22004
0223       // This workaround starts it when it is possible again.
0224       function restartHandler() {
0225         runningChanged.disconnect(restartHandler)
0226         if (!running) {
0227           start()
0228         }
0229       }
0230 
0231       runningChanged.connect(restartHandler)
0232     }
0233   }
0234 
0235   Component.onCompleted: setTimeout(main, 1)
0236 }