diff --git a/.gitignore b/.gitignore index d4adf5b..b2dd87d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ appdir AppDir Makefile linuxdeploy* -other_libs \ No newline at end of file +other_libs +sffmpeg \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e152cfb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.1.0) + +project(KittehPlayer) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -fstrict-aliasing -Wno-deprecated-declarations -Wno-unused-variable") + +option(DEVELOP "Enable runtime QML reloading for developing." OFF) + + +find_package(Qt5Core REQUIRED) +find_package(Qt5 REQUIRED Qml Quick Gui Widgets Core) + +find_package(Qt5QuickCompiler) +qtquick_compiler_add_resources(qml_QRC src/qml/qml.qrc) + +set(SOURCES + src/main.cpp + src/mpvobject.cpp +) + +if(DEVELOP) +set(SOURCES ${SOURCES} runtimeqml/runtimeqml.cpp) +add_definitions(-DQRC_SOURCE_PATH="${PROJECT_SOURCE_DIR}/src/qml") +endif(DEVELOP) + +add_executable(KittehPlayer ${SOURCES} ${qml_QRC}) + +# Use the Qml/Quick modules from Qt 5. +target_link_libraries(KittehPlayer mpv) + +qt5_use_modules(KittehPlayer Qml Quick Core Gui Widgets) + + + + diff --git a/runtimeqml/.gitignore b/runtimeqml/.gitignore new file mode 100644 index 0000000..dcd1292 --- /dev/null +++ b/runtimeqml/.gitignore @@ -0,0 +1,75 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* +# qtcreator builds of test project +build-RuntimeQML-* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/runtimeqml/LICENSE b/runtimeqml/LICENSE new file mode 100644 index 0000000..f67c3ad --- /dev/null +++ b/runtimeqml/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2018, Benjamin Balga +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/runtimeqml/README.md b/runtimeqml/README.md new file mode 100644 index 0000000..01ca199 --- /dev/null +++ b/runtimeqml/README.md @@ -0,0 +1,87 @@ +# Runtime QML for Qt + +**Written by**: *Benjamin Balga.* +**Copyright**: ***2018***, *Benjamin Balga*, released under BSD license. + + +## About + +This is a base project to get runtime QML reload in your Qt project. +It allows you to reload all QML code at runtime, without recompiling or restarting your app, saving time. + +With auto-reload, QML files are watched (based on the QRC file) and reloaded when you save them, or can trigger it manually. + +On reload, all windows are closed, and the main window is reloaded. All "QML-only data" is lost, so use links to C++ models/properties as needed. + +It only works with Window component as top object, or QQuickWindow subclasses. + +### Examples +Example project is located here: https://github.com/GIPdA/runtimeqml_examples + + +## How to use it in your project + +Clone the repo into your project (or copy-paste the ```runtimeqml``` folder) and import the ```.pri``` project file into your ```.pro``` file: + + include(runtimeqml/runtimeqml.pri) + + +### With Qbs +The Qbs project file includes RuntimeQML as a static library. Check the example project to see how to include it in your project. + + +## Usage + +Include ```runtimeqml.h``` header file, and create the RuntimeQML object (after the QML engine) : + + RuntimeQML *rt = new RuntimeQML(&engine, QRC_SOURCE_PATH"/qml.qrc"); + +The second argument is the path to your qrc file listing all your QML files, needed for the auto-reload feature only. You can omit it if you don't want auto-reload. +```QRC_SOURCE_PATH``` is defined in the ```.pri/.qbs``` file to its parent path, just to not have to manually set an absolute path... + + +Set the "options" you want, or not: + + rt->noDebug(); // Removes debug prints + rt->setAutoReload(true); // Enable auto-reload (begin to watch files) + //rt->setCloseAllOnReload(false); // Don't close all windows on reload. Not advised! + rt->setMainQmlFilename("main.qml"); // This is the file that loaded on reload, default is "main.qml" + +For the auto-reload feature: + + rt->addSuffix("conf"); // Adds a file suffix to the "white list" for watched files. "qml" is already in. + rt->ignorePrefix("/test"); // Ignore a prefix in the QRC file. + rt->ignoreFile("/Page2.qml"); // Ignore a file name with prefix (supports classic wildcard matching) + + +Then load the main QML file : + + rt->reload(); + +And you're all set! + + +You can also check the test project. Beware, includes and defines differs a bit... + + +## Manual reload + +Add the RuntimeQML object to the QML context: + + engine.rootContext()->setContextProperty("RuntimeQML", rt); + +Trigger the reload when and where you want, like with a button: + + Button { + text: "Reload" + onClicked: { + RuntimeQML.reload(); + } + } + +You can do it in C++ too, of course. + + + +## License +See LICENSE file. diff --git a/runtimeqml/runtimeqml.cpp b/runtimeqml/runtimeqml.cpp new file mode 100644 index 0000000..8eb63c9 --- /dev/null +++ b/runtimeqml/runtimeqml.cpp @@ -0,0 +1,398 @@ +#include "runtimeqml.h" + +#include +#include +#include +#include + +/*! + * \brief Construct a RuntimeQML object with a path to the qrc file. + * \param engine App engine to reload. + * \param qrcFilename File name of the QRC file for auto reload. + * \param parent Pointer to a parent object. + */ +RuntimeQML::RuntimeQML(QQmlApplicationEngine* engine, const QString &qrcFilename, QObject *parent) : + QObject(parent), + m_engine(engine), + m_qrcFilename(qrcFilename), + m_mainQmlFilename("main.qml") +{ + m_allowedSuffixList << "qml"; +} + + +/*! + * \brief Returns the absolute path for the given qml file. + * \param qmlFile Qml filename + */ +QString RuntimeQML::adjustPath(QString qmlFile) +{ + return m_selector.select(qrcAbsolutePath() + "/" + qmlFile); +} + +/*! + * \brief Returns the absolute path to the QRC file. + */ +QString RuntimeQML::qrcAbsolutePath() const +{ + return QFileInfo(m_qrcFilename).absolutePath(); +} + +/*! + * \brief Filename of the QRC file. + */ +QString RuntimeQML::qrcFilename() const +{ + return m_qrcFilename; +} + +/*! + * \brief If true, files are watched for changes and auto-reloaded. + * Otherwise, you need to trigger a reload manually from your code by calling reload(). + * \sa reload + */ +bool RuntimeQML::autoReload() const +{ + return m_autoReload; +} + +/*! + * \brief If true, all open windows will be closed upon reload. + * \default true + */ +bool RuntimeQML::closeAllOnReload() const +{ + return m_closeAllOnReload; +} + +/*! + * \brief QRC prefixes that are ignored. + */ +const QList& RuntimeQML::prefixIgnoreList() const +{ + return m_prefixIgnoreList; +} + +/*! + * \brief Files that are ignored. + */ +const QList &RuntimeQML::fileIgnoreList() const +{ + return m_fileIgnoreList; +} + +/*! + * \brief Allowed suffixes to filter files to watch for changes. + * By default contains only "qml". + */ +const QList &RuntimeQML::allowedSuffixes() const +{ + return m_allowedSuffixList; +} + +/*! + * \brief Call it if you don't want debug outputs from this class. + */ +void RuntimeQML::noDebug() +{ + if (m_noDebug) + return; + m_noDebug = true; +} + + +/*! + * \brief Reload the window. + */ +void RuntimeQML::reload() +{ + QMetaObject::invokeMethod(this, "reloadQml", Qt::QueuedConnection); +} + + +/*! + * \brief Call it from QML to set the current QQuickWindow. + * You shouldn't need to call it as it is done automatically on reload. + * \param window + */ +void RuntimeQML::setWindow(QQuickWindow* window) +{ + if (window == m_window) + return; + m_window = window; +} + + +/*! + * \brief Set the QRC filename for files to watch for changes. + * \param qrcFilename Path to a .qrc file. + */ +void RuntimeQML::setQrcFilename(QString qrcFilename) +{ + if (m_qrcFilename == qrcFilename) + return; + + m_qrcFilename = qrcFilename; + emit qrcFilenameChanged(qrcFilename); + + loadQrcFiles(); +} + +/*! + * \brief Set the name of the main qml file. + * Default is "main.qml". + * \param filename The main qml filename. + */ +void RuntimeQML::setMainQmlFilename(QString filename) +{ + if (m_mainQmlFilename == filename) + return; + + m_mainQmlFilename = filename; +} + + +/*! + * \brief If true, files are watched for changes and auto-reloaded. + * Otherwise, you need to trigger a reload manually from your code by calling reload(). + * \param reload True to auto-reload, false otherwise. + */ +void RuntimeQML::setAutoReload(bool autoReload) +{ + if (m_autoReload == autoReload) + return; + + m_autoReload = autoReload; + emit autoReloadChanged(autoReload); + + if (autoReload) + loadQrcFiles(); + else + unloadFileWatcher(); +} + +/*! + * \brief If true, all open windows are closed upon reload. Otherwise, might cause "link" errors with QML components. + * \param closeAllOnReload True to close all windows on reload, false otherwise. + */ +void RuntimeQML::setCloseAllOnReload(bool closeAllOnReload) +{ + if (m_closeAllOnReload == closeAllOnReload) + return; + + m_closeAllOnReload = closeAllOnReload; + emit closeAllOnReloadChanged(m_closeAllOnReload); +} + +/*! + * \brief Add a QRC prefix to ignore. + * \note Relevant for auto-reload only. + * \param prefix Prefix to ignore. + */ +void RuntimeQML::ignoreQrcPrefix(const QString& prefix) +{ + if (m_prefixIgnoreList.contains(prefix)) + return; + + m_prefixIgnoreList.append(prefix); + + if (m_autoReload) + loadQrcFiles(); +} + +/*! + * \brief Add a filename to ignore from changes. + * Applies to the full filename in the QRC entry (i.e. the local "path"), with the prefix. + * Supports "file globbing" matching using wildcards. + * \note Relevant for auto-reload only. + * \param filename Filename to ignore. + */ +void RuntimeQML::ignoreFile(const QString &filename) +{ + if (m_fileIgnoreList.contains(filename)) + return; + + m_fileIgnoreList.append(filename); + + if (m_autoReload) + loadQrcFiles(); +} + +/*! + * \brief Allow a file suffix to be watched for changes. + * \note Relevant for auto-reload only. + * \param suffix + */ +void RuntimeQML::addSuffix(const QString &suffix) +{ + if (m_allowedSuffixList.contains(suffix)) + return; + + m_allowedSuffixList.append(suffix); + + if (m_autoReload) + loadQrcFiles(); +} + + +/*! + * \brief Reload the QML. Do not call it directly, use reload() instead. + */ +void RuntimeQML::reloadQml() +{ + if (m_mainQmlFilename.isEmpty()) { + qWarning("No QML file specified."); + return; + } + + if (m_window) { + if (m_closeAllOnReload) { + // Find all child windows and close them + auto const allWindows = m_window->findChildren(); + for (int i {0}; i < allWindows.size(); ++i) { + QQuickWindow* w = qobject_cast(allWindows.at(i)); + if (w) { + w->close(); + w->deleteLater(); + } + } + } + + m_window->close(); + m_window->deleteLater(); + } + + m_engine->clearComponentCache(); + // TODO: test with network files + // TODO: QString path to QUrl doesn't work under Windows with load() (load fail) + m_engine->load(m_selector.select(qrcAbsolutePath() + "/" + m_mainQmlFilename)); + // NOTE: QQmlApplicationEngine::rootObjects() isn't cleared, should it be? + + if (!m_engine->rootObjects().isEmpty()) { + QQuickWindow* w = qobject_cast(m_engine->rootObjects().last()); + if (w) m_window = w; + } + +// for (auto *o : m_engine->rootObjects()) { +// qDebug() << "> " << o; +// } +} + +/*! + * \brief Called when a watched file changed, from QFileSystemWatcher. + * \param path Path/file that triggered the signal. + */ +void RuntimeQML::fileChanged(const QString& path) +{ + if (!m_noDebug) + qDebug() << "Reloading qml:" << path; + reload(); + +#if defined(Q_OS_WIN) + // Deleted files are removed from the watcher, re-add the file for + // systems that delete files to update them + if (m_fileWatcher) + QTimer::singleShot(500, m_fileWatcher, [this,path](){ + m_fileWatcher->addPath(path); + }); +#endif +} + + +/*! + * \brief Load qml from the QRC file to watch them. + */ +void RuntimeQML::loadQrcFiles() +{ + unloadFileWatcher(); + + m_fileWatcher = new QFileSystemWatcher(this); + connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &RuntimeQML::fileChanged); + + QFile file(m_qrcFilename); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning("Unable to open resource file '%s', RuntimeQML will not work! Error: %s", + qPrintable(m_qrcFilename), qPrintable(file.errorString())); + return; + } + + QString const basePath = qrcAbsolutePath() + "/"; + QString currentPrefix; + + // Read each entry + QXmlStreamReader inputStream(&file); + while (!inputStream.atEnd() && !inputStream.hasError()) { + inputStream.readNext(); + if (inputStream.isStartElement()) { + QString name { inputStream.name().toString() }; + + // Check prefix + if (name == "qresource") { + if (inputStream.attributes().hasAttribute("prefix")) { + auto p = inputStream.attributes().value("prefix").toString(); + if (m_prefixIgnoreList.contains(p)) { + // Ignore this prefix, loop through elements in this 'qresource' tag + while (!inputStream.atEnd() && !inputStream.hasError()) { + inputStream.readNext(); + if (inputStream.isEndElement() && inputStream.name() == "qresource") + break; + } + continue; + } + currentPrefix = p; + } + } + + // Check file name + if (name == "file") { + QString const filename { inputStream.readElementText() }; + + // Check ignore list + QString const fullFilename { currentPrefix + filename }; + auto it = std::find_if(m_fileIgnoreList.cbegin(), m_fileIgnoreList.cend(), [&](QString const& pattern) { + QRegExp re(pattern); + re.setPatternSyntax(QRegExp::WildcardUnix); + return re.exactMatch(fullFilename); + }); + + if (it != m_fileIgnoreList.cend()) + continue; + + QFileInfo const file { filename }; + + // Add to the watch list if the file suffix is allowed + if (m_allowedSuffixList.contains(file.suffix())) { + QString fp { m_selector.select(basePath + filename) }; + m_fileWatcher->addPath(fp); + //qDebug() << " " << file.absoluteFilePath() << fp; + } + } + } + } + + if (!m_noDebug) { + qDebug("Watching QML files:"); + int const fileCount = m_fileWatcher->files().size(); + + for (auto &f : m_fileWatcher->files()) { + qDebug() << " " << f; + } + + if (fileCount > 0) + qDebug(" Total: %d", fileCount); + else + qDebug(" None."); + } +} + +/*! + * \brief Unload the file watcher. + */ +void RuntimeQML::unloadFileWatcher() +{ + if (m_fileWatcher) { + disconnect(m_fileWatcher); + delete m_fileWatcher; + m_fileWatcher = nullptr; + } +} diff --git a/runtimeqml/runtimeqml.h b/runtimeqml/runtimeqml.h new file mode 100644 index 0000000..b58359b --- /dev/null +++ b/runtimeqml/runtimeqml.h @@ -0,0 +1,82 @@ +#ifndef RUNTIMEQML_H +#define RUNTIMEQML_H + +#include +#include +#include +#include +#include + +#include + + +class RuntimeQML : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString qrcFilename READ qrcFilename WRITE setQrcFilename NOTIFY qrcFilenameChanged) + Q_PROPERTY(bool autoReload READ autoReload WRITE setAutoReload NOTIFY autoReloadChanged) + Q_PROPERTY(bool closeAllOnReload READ closeAllOnReload WRITE setCloseAllOnReload NOTIFY closeAllOnReloadChanged) + +public: + explicit RuntimeQML(QQmlApplicationEngine *engine, QString const& qrcFilename = QString(), QObject *parent = 0); + + // If using QQmlFileSelector with Loader + Q_INVOKABLE QString adjustPath(QString qmlFile); + Q_INVOKABLE QString qrcAbsolutePath() const; + + QString qrcFilename() const; + + bool autoReload() const; + bool closeAllOnReload() const; + + QList const & prefixIgnoreList() const; + QList const & fileIgnoreList() const; + QList const & allowedSuffixes() const; + + void noDebug(); + +signals: + void autoReloadChanged(bool autoReload); + void qrcFilenameChanged(QString qrcFilename); + void closeAllOnReloadChanged(bool closeAllOnReload); + +public slots: + void reload(); + void setWindow(QQuickWindow* window); + + void setQrcFilename(QString qrcFilename); + void setMainQmlFilename(QString filename); + + void setAutoReload(bool autoReload); + void setCloseAllOnReload(bool closeAllOnReload); + + void ignoreQrcPrefix(QString const& prefix); + void ignoreFile(QString const& filename); + + void addSuffix(QString const& suffix); + +private slots: + void reloadQml(); + void fileChanged(const QString &path); + +private: + void loadQrcFiles(); + void unloadFileWatcher(); + + QQmlApplicationEngine *m_engine {nullptr}; + QQuickWindow *m_window {nullptr}; + QFileSelector m_selector; + + QString m_qrcFilename; + QString m_mainQmlFilename; + + bool m_autoReload {false}; + QFileSystemWatcher* m_fileWatcher {nullptr}; + QList m_prefixIgnoreList; + QList m_fileIgnoreList; + QList m_allowedSuffixList; + bool m_noDebug {false}; + bool m_closeAllOnReload {true}; +}; + +#endif // RUNTIMEQML_H diff --git a/runtimeqml/runtimeqml.pri b/runtimeqml/runtimeqml.pri new file mode 100644 index 0000000..41040dd --- /dev/null +++ b/runtimeqml/runtimeqml.pri @@ -0,0 +1,13 @@ +# Qt Quick Runtime Reloader + +QT += core qml quick + +INCLUDEPATH += $$PWD + +DEFINES += "QRC_SOURCE_PATH=\\\"$$PWD/..\\\"" + +SOURCES += \ + $$PWD/runtimeqml.cpp + +HEADERS += \ + $$PWD/runtimeqml.h diff --git a/runtimeqml/runtimeqml.qbs b/runtimeqml/runtimeqml.qbs new file mode 100644 index 0000000..c5beb52 --- /dev/null +++ b/runtimeqml/runtimeqml.qbs @@ -0,0 +1,18 @@ +import qbs 1.0 + +StaticLibrary { + name: "runtimeqml" + files: [ + "runtimeqml.cpp", + "runtimeqml.h", + ] + Depends { name: 'cpp' } + Depends { name: "Qt.core" } + Depends { name: "Qt.quick" } + + Export { + Depends { name: "cpp" } + cpp.includePaths: [product.sourceDirectory] + cpp.defines: ['QRC_SOURCE_PATH="'+path+'/.."'] + } +} diff --git a/src/main.cpp b/src/main.cpp index 45b9d80..2d6aae4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,9 @@ #include "config.h" #include "mpvobject.h" - +#ifdef QRC_SOURCE_PATH +#include "runtimeqml/runtimeqml.h" +#endif #include @@ -59,6 +61,15 @@ view->setSource(QUrl("qrc:///player/main.qml")); view->show();*/ QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:///player/main.qml"))); +#ifdef QRC_SOURCE_PATH +RuntimeQML *rt = new RuntimeQML(&engine, QRC_SOURCE_PATH"/qml.qrc"); + +rt->setAutoReload(true); +rt->setMainQmlFilename("main.qml"); +rt->reload(); +#else +engine.load(QUrl(QStringLiteral("qrc:///player/main.qml"))); +#endif + return app.exec(); } diff --git a/src/mpvobject.cpp b/src/mpvobject.cpp index 39c2eb7..fbcdf39 100644 --- a/src/mpvobject.cpp +++ b/src/mpvobject.cpp @@ -118,7 +118,7 @@ MpvObject::MpvObject(QQuickItem * parent) throw std::runtime_error("could not create mpv context"); mpv_set_option_string(mpv, "terminal", "yes"); - mpv_set_option_string(mpv, "msg-level", "all=v"); + //mpv_set_option_string(mpv, "msg-level", "all=v"); // Fix? mpv_set_option_string(mpv, "ytdl", "yes"); diff --git a/src/qml/CustomMenuItem.qmlc b/src/qml/CustomMenuItem.qmlc new file mode 100644 index 0000000..5b14449 Binary files /dev/null and b/src/qml/CustomMenuItem.qmlc differ diff --git a/src/qml/codes.jsc b/src/qml/codes.jsc new file mode 100644 index 0000000..d1b78e9 Binary files /dev/null and b/src/qml/codes.jsc differ diff --git a/src/qml/main.qml b/src/qml/main.qml index 57ef901..26ae16b 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -43,7 +43,6 @@ ApplicationWindow { var sid = player.getProperty("sid") var vid = player.getProperty("vid") - console.log("Updating Track Menu, Total Tracks: " + tracks) for (track = 0; track <= tracks; track++) { var trackID = player.getProperty("track-list/" + track + "/id") var trackType = player.getProperty("track-list/" + track + "/type") @@ -155,12 +154,10 @@ ApplicationWindow { } function skipToNinth(val) { - console.log(val) var skipto = 0 if (val != 0) { skipto = Math.floor(progressBar.to / 9 * val) } - console.log(skipto) player.command(["seek", skipto, "absolute"]) } @@ -175,7 +172,6 @@ ApplicationWindow { } function updateVolume(volume) { - console.log(volume) var muted = player.getProperty("mute") if (muted || volume === 0) { @@ -405,7 +401,7 @@ ApplicationWindow { } background: Rectangle { - implicitWidth: parent.width + width: parent.width implicitHeight: 10 color: "black" opacity: 0.6 @@ -468,7 +464,7 @@ ApplicationWindow { Menu { id: playbackMenuBarItem title: "Playback" - width: 100 + width: 150 background: Rectangle { implicitWidth: parent.width implicitHeight: 10 @@ -476,7 +472,7 @@ ApplicationWindow { opacity: 0.6 } delegate: CustomMenuItem { - width: 100 + width: parent.width } Action { @@ -569,7 +565,7 @@ ApplicationWindow { Menu { id: tracksMenuBarItem title: "Tracks" - width: 150 + width: 140 background: Rectangle { implicitWidth: parent.width implicitHeight: 10 @@ -577,7 +573,7 @@ ApplicationWindow { opacity: 0.6 } delegate: CustomMenuItem { - width: 100 + width: parent.width } Action { text: "Track Menu" @@ -621,7 +617,7 @@ ApplicationWindow { Menu { id: viewMenuBarItem title: "View" - width: 100 + width: 120 background: Rectangle { implicitWidth: parent.width implicitHeight: 10 @@ -629,6 +625,7 @@ ApplicationWindow { opacity: 0.6 } delegate: CustomMenuItem { + width: parent.width } Action { @@ -716,8 +713,6 @@ ApplicationWindow { height: childrenRect.height visible: false anchors.centerIn: player - anchors.right: player.right - anchors.bottom: progressBar.top border.color: "black" border.width: 2 diff --git a/src/qml/main.qmlc b/src/qml/main.qmlc new file mode 100644 index 0000000..30df796 Binary files /dev/null and b/src/qml/main.qmlc differ