diff --git a/discover/main.cpp b/discover/main.cpp index b45c1002..90d87860 100644 --- a/discover/main.cpp +++ b/discover/main.cpp @@ -1,157 +1,157 @@ /* * Copyright (C) 2012 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // #define QT_QML_DEBUG #include #include #include #include #include #include #include #include "DiscoverObject.h" #include #include "DiscoverVersion.h" #include #include typedef QHash StringCompactMode; Q_GLOBAL_STATIC_WITH_ARGS(StringCompactMode, s_decodeCompactMode, (StringCompactMode { { QLatin1String("auto"), DiscoverObject::Auto }, { QLatin1String("compact"), DiscoverObject::Compact }, { QLatin1String("full"), DiscoverObject::Full } })) QCommandLineParser* createParser() { QCommandLineParser* parser = new QCommandLineParser; parser->addOption(QCommandLineOption(QStringLiteral("application"), i18n("Directly open the specified application by its package name."), QStringLiteral("name"))); parser->addOption(QCommandLineOption(QStringLiteral("mime"), i18n("Open with a program that can deal with the given mimetype."), QStringLiteral("name"))); parser->addOption(QCommandLineOption(QStringLiteral("category"), i18n("Display a list of entries with a category."), QStringLiteral("name"))); parser->addOption(QCommandLineOption(QStringLiteral("mode"), i18n("Open Discover in a said mode. Modes correspond to the toolbar buttons."), QStringLiteral("name"))); parser->addOption(QCommandLineOption(QStringLiteral("listmodes"), i18n("List all the available modes."))); parser->addOption(QCommandLineOption(QStringLiteral("compact"), i18n("Compact Mode (auto/compact/full)."), QStringLiteral("mode"), QStringLiteral("auto"))); parser->addOption(QCommandLineOption(QStringLiteral("local-filename"), i18n("Local package file to install"), QStringLiteral("package"))); parser->addOption(QCommandLineOption(QStringLiteral("listbackends"), i18n("List all the available backends."))); parser->addOption(QCommandLineOption(QStringLiteral("test"), QStringLiteral("Test file"), QStringLiteral("file.qml"))); parser->addPositionalArgument(QStringLiteral("urls"), i18n("Supports appstream: url scheme")); DiscoverBackendsFactory::setupCommandLine(parser); KAboutData::applicationData().setupCommandLine(parser); parser->addHelpOption(); parser->addVersionOption(); return parser; } void processArgs(QCommandLineParser* parser, DiscoverObject* mainWindow) { if(parser->isSet(QStringLiteral("application"))) mainWindow->openApplication(QUrl(parser->value(QStringLiteral("application")))); else if(parser->isSet(QStringLiteral("mime"))) mainWindow->openMimeType(parser->value(QStringLiteral("mime"))); else if(parser->isSet(QStringLiteral("category"))) mainWindow->openCategory(parser->value(QStringLiteral("category"))); if(parser->isSet(QStringLiteral("mode"))) mainWindow->openMode(parser->value(QStringLiteral("mode"))); if(parser->isSet(QStringLiteral("local-filename"))) mainWindow->openLocalPackage(QUrl::fromUserInput(parser->value(QStringLiteral("local-filename")), {}, QUrl::AssumeLocalFile)); foreach(const QString &arg, parser->positionalArguments()) { const QUrl url = QUrl::fromUserInput(arg, {}, QUrl::AssumeLocalFile); if (url.isLocalFile()) mainWindow->openLocalPackage(url); else if (url.scheme() == QLatin1String("apt")) mainWindow->openSearch(url.host()); else mainWindow->openApplication(url); } } int main(int argc, char** argv) { QApplication app(argc, argv); app.setWindowIcon(QIcon::fromTheme(QStringLiteral("plasmadiscover"))); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); KCrash::initialize(); KLocalizedString::setApplicationDomain("plasma-discover"); KAboutData about(QStringLiteral("discover"), i18n("Discover"), version, i18n("An application explorer"), - KAboutLicense::GPL, i18n("© 2010-2016 Plasma Development Team")); + KAboutLicense::GPL, i18n("© 2010-2018 Plasma Development Team")); about.addAuthor(i18n("Aleix Pol Gonzalez"), QString(), QStringLiteral("aleixpol@blue-systems.com")); about.addAuthor(i18n("Jonathan Thomas"), QString(), QStringLiteral("echidnaman@kubuntu.org")); about.setProductName("discover/discover"); KAboutData::setApplicationData(about); DiscoverObject *mainWindow = nullptr; { QScopedPointer parser(createParser()); parser->process(app); about.processCommandLine(parser.data()); DiscoverBackendsFactory::processCommandLine(parser.data(), parser->isSet(QStringLiteral("test"))); if(parser->isSet(QStringLiteral("listbackends"))) { QTextStream(stdout) << i18n("Available backends:\n"); DiscoverBackendsFactory f; foreach(const QString& name, f.allBackendNames(false, true)) QTextStream(stdout) << " * " << name << '\n'; return 0; } if (parser->isSet(QStringLiteral("test"))) { QStandardPaths::setTestModeEnabled(true); } KDBusService* service = new KDBusService(KDBusService::Unique, &app); mainWindow = new DiscoverObject(s_decodeCompactMode->value(parser->value(QStringLiteral("compact")), DiscoverObject::Full)); QObject::connect(&app, &QCoreApplication::aboutToQuit, mainWindow, &DiscoverObject::deleteLater); QObject::connect(service, &KDBusService::activateRequested, mainWindow, [mainWindow](const QStringList &arguments, const QString &/*workingDirectory*/){ if (!mainWindow->rootObject()) QCoreApplication::instance()->quit(); mainWindow->rootObject()->raise(); if (arguments.isEmpty()) return; QScopedPointer parser(createParser()); parser->parse(arguments); processArgs(parser.data(), mainWindow); }); processArgs(parser.data(), mainWindow); if(parser->isSet(QStringLiteral("listmodes"))) { QTextStream(stdout) << i18n("Available modes:\n"); foreach(const QString& mode, mainWindow->modes()) QTextStream(stdout) << " * " << mode << '\n'; delete mainWindow; return 0; } if (parser->isSet(QStringLiteral("test"))) { const QUrl testFile = QUrl::fromUserInput(parser->value(QStringLiteral("test")), {}, QUrl::AssumeLocalFile); Q_ASSERT(!testFile.isEmpty() && testFile.isLocalFile()); mainWindow->loadTest(testFile); } } return app.exec(); } diff --git a/discover/qml/ApplicationScreenshots.qml b/discover/qml/ApplicationScreenshots.qml index e5204414..12e30440 100644 --- a/discover/qml/ApplicationScreenshots.qml +++ b/discover/qml/ApplicationScreenshots.qml @@ -1,174 +1,174 @@ /* * Copyright (C) 2012 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.1 import QtQuick.Controls 2.1 as QQC2 import QtGraphicalEffects 1.0 import org.kde.discover 2.0 import org.kde.kirigami 2.0 as Kirigami Flickable { id: root readonly property alias count: screenshotsModel.count property alias resource: screenshotsModel.application property var resource property int currentIndex: -1 property Item currentItem: screenshotsRep.itemAt(currentIndex) Layout.preferredHeight: Kirigami.Units.gridUnit * 13 contentHeight: height contentWidth: screenshotsLayout.width QQC2.Popup { id: overlay parent: applicationWindow().overlay modal: true x: (parent.width - width)/2 y: (parent.height - height)/2 readonly property real proportion: overlayImage.sourceSize.width>1 ? overlayImage.sourceSize.height/overlayImage.sourceSize.width : 1 height: Math.min(parent.height * 0.9, (parent.width * 0.9) * proportion, overlayImage.sourceSize.height) width: height/proportion Image { id: overlayImage anchors.fill: parent source: root.currentItem ? root.currentItem.imageSource : "" fillMode: Image.PreserveAspectFit smooth: true } Button { anchors { right: parent.left verticalCenter: parent.verticalCenter } visible: leftAction.visible iconName: leftAction.iconName onClicked: leftAction.triggered(null) } Button { anchors { left: parent.right verticalCenter: parent.verticalCenter } visible: rightAction.visible iconName: rightAction.iconName onClicked: rightAction.triggered(null) } Kirigami.Action { id: leftAction iconName: "arrow-left" enabled: overlay.visible && visible visible: root.currentIndex >= 1 onTriggered: root.currentIndex = (root.currentIndex - 1) % screenshotsModel.count } Kirigami.Action { id: rightAction iconName: "arrow-right" enabled: overlay.visible && visible visible: root.currentIndex < (root.count - 1) onTriggered: root.currentIndex = (root.currentIndex + 1) % screenshotsModel.count } } Row { id: screenshotsLayout height: root.contentHeight spacing: Kirigami.Units.largeSpacing focus: overlay.visible Keys.onLeftPressed: if (leftAction.visible) leftAction.trigger() Keys.onRightPressed: if (rightAction.visible) rightAction.trigger() Repeater { id: screenshotsRep model: ScreenshotsModel { id: screenshotsModel } delegate: MouseArea { readonly property url imageSource: large_image_url readonly property real proportion: thumbnail.sourceSize.width>1 ? thumbnail.sourceSize.height/thumbnail.sourceSize.width : 1 width: Math.max(50, height/proportion) height: screenshotsLayout.height hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { root.currentIndex = index overlay.open() } DropShadow { source: thumbnail anchors.fill: thumbnail verticalOffset: 3 horizontalOffset: 0 radius: 12.0 samples: 25 color: Kirigami.Theme.disabledTextColor cached: true } BusyIndicator { visible: running running: thumbnail.status == Image.Loading - anchors.centerIn: thumbnail + anchors.centerIn: parent } Image { id: thumbnail source: small_image_url height: parent.height fillMode: Image.PreserveAspectFit smooth: true } } } } clip: true readonly property var leftShadow: Shadow { parent: root anchors { left: parent.left top: parent.top bottom: parent.bottom } edge: Qt.LeftEdge width: Math.max(0, Math.min(root.width/5, root.contentX)) } readonly property var rightShadow: Shadow { parent: root anchors { right: parent.right top: parent.top bottom: parent.bottom } edge: Qt.RightEdge width: Math.max(0, Math.min(root.contentWidth - root.contentX - root.width)/5) } } diff --git a/discover/qml/ProgressView.qml b/discover/qml/ProgressView.qml index 3506c7f0..522f5d72 100644 --- a/discover/qml/ProgressView.qml +++ b/discover/qml/ProgressView.qml @@ -1,136 +1,141 @@ import QtQuick 2.1 import QtQuick.Controls 1.1 import QtQuick.Controls 2.1 as QQC2 import QtQuick.Layouts 1.1 import org.kde.kquickcontrolsaddons 2.0 import org.kde.discover 2.0 import org.kde.kirigami 2.0 as Kirigami import "navigation.js" as Navigation Kirigami.BasicListItem { id: listItem label: TransactionModel.count ? i18n("Tasks (%1%)", TransactionModel.progress) : i18n("Tasks") visible: progressModel.count > 0 background: Item { Rectangle { anchors { fill: parent rightMargin: TransactionModel.count>=1 ? listItem.width*(1-TransactionModel.progress/100) : 0 } color: TransactionModel.count>=1 || listItem.hovered || listItem.highlighted || listItem.pressed || listItem.checked ? listItem.activeBackgroundColor : listItem.backgroundColor opacity: listItem.hovered || listItem.highlighted ? 0.2 : 1 } } + property QtObject sheetObject: null onClicked: { - sheet.open() + sheetObject = sheet.createObject() + sheetObject.open() } - onVisibleChanged: if (!visible) { - sheet.close() + onVisibleChanged: if (!visible && sheetObject) { + sheetObject.close() + sheetObject.destroy(100) } readonly property var v1: Connections { target: TransactionModel onTransactionAdded: { if(listItem.enabled && trans.visible && progressModel.applicationAt(trans.resource)<0) { progressModel.append({ transaction: trans }) } } onTransactionRemoved: { if (!trans.resource) { var id = progressModel.applicationAt(trans.resource) if(id>=0) progressModel.remove(id) } } } readonly property var v2: ListModel { id: progressModel function applicationAt(app) { for(var i=0; i