diff --git a/CMakeLists.txt b/CMakeLists.txt index 539f26d..889b0e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,33 +1,33 @@ project(Koko) cmake_minimum_required(VERSION 2.8.12) find_package(ECM 0.0.9 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${ECM_MODULE_PATH}) find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Qml Quick Widgets Test Sql Positioning) -find_package(KF5 5.5 REQUIRED COMPONENTS I18n Declarative Config DBusAddons KIO GuiAddons CoreAddons) +find_package(KF5 5.5 REQUIRED COMPONENTS I18n Declarative Config DBusAddons KIO GuiAddons CoreAddons Notifications) find_package(Exiv2 0.21 REQUIRED) include(FeatureSummary) include(ECMAddTests) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings) include(GenerateExportHeader) include(ECMInstallIcons) include_directories( ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_BINARY_DIR}/src ${EXIV2_INCLUDE_DIR} ) kde_enable_exceptions() add_subdirectory(src) add_subdirectory(autotests) add_subdirectory(qmlUiKirigami) add_subdirectory(icons) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/qmlUiKirigami/ImageViewer.qml b/qmlUiKirigami/ImageViewer.qml index 92a0e38..d12c0fe 100644 --- a/qmlUiKirigami/ImageViewer.qml +++ b/qmlUiKirigami/ImageViewer.qml @@ -1,364 +1,412 @@ /* * Copyright (C) 2017 Marco Martin * Copyright (C) 2017 Atul Sharma * Copyright (C) 2015 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ import QtQuick 2.7 import QtQuick.Window 2.2 import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.0 as Kirigami import org.kde.koko 0.1 as Koko import org.kde.kquickcontrolsaddons 2.0 as KQA Kirigami.Page { id: root property alias sourceModel: imagesListModel.sourceModel property int indexValue property int imageWidth property int imageHeight leftPadding: 0 rightPadding: 0 + + KQA.MimeDatabase { + id: mimeDB + } + + actions { + main: Kirigami.Action { + iconName: "document-share" + tooltip: i18n("Share Image") + onTriggered: { + shareDialog.sheetOpen = true + shareDialog.inputData = { + "urls": [ listView.currentItem.currentImageSource.toString() ], + "mimeType": mimeDB.mimeTypeForUrl( listView.currentItem.currentImageSource).name + } + } + } + left: Kirigami.Action { + iconName: "view-close" + tooltip: i18n("Close Image") + onTriggered: root.state = "closed" + } + right: Kirigami.Action { + iconName: "editimage" + tooltip: i18n("Edit Image") + } + } states: [ State { name: "open" PropertyChanges { target: root visible: true } PropertyChanges { target: root opacity: 1 } PropertyChanges { target: root focus: true } PropertyChanges { target: listView focus: true } PropertyChanges { target: applicationWindow() visibility: Window.Windowed } }, State { name: "closed" PropertyChanges { target: root opacity: 0 } PropertyChanges { target: root visible: false } + PropertyChanges { + target: shareDialog + sheetOpen: false + } }, State { name: "fullscreen" PropertyChanges { target: root focus: true } PropertyChanges { target: listView focus: true } PropertyChanges { target: applicationWindow() visibility: Window.FullScreen } } ] transitions: [ Transition { from: "*" to: "closed" SequentialAnimation { OpacityAnimator { target: root duration: Kirigami.Units.longDuration easing.type: Easing.InQuad } PropertyAnimation { target: root property: "visible" duration: Kirigami.Units.longDuration } ScriptAction { script: applicationWindow().pageStack.forceActiveFocus(); } } }, Transition { from: "closed" to: "open" OpacityAnimator { target: root duration: Kirigami.Units.longDuration easing.type: Easing.OutQuad } } ] background: Rectangle { color: "black" } Keys.onPressed: { switch(event.key) { case Qt.Key_Escape: root.state = "closed" break; case Qt.Key_F: root.state = root.state == "open" ? "fullscreen" : "open" break; default: break; } } ListView { id: listView anchors.fill: parent orientation: Qt.Horizontal snapMode: ListView.SnapOneItem onMovementEnded: currentImage.index = model.sourceIndex(indexAt(contentX+1, 1)) model: Koko.SortModel { id: imagesListModel filterRole: Koko.Roles.MimeTypeRole filterRegExp: /image\// } currentIndex: model.proxyIndex( indexValue) Timer { id: timer interval: 2000 onTriggered: footerList.opacity = 0 } onCurrentIndexChanged: { currentImage.index = model.sourceIndex( currentIndex) listView.positionViewAtIndex(currentIndex, ListView.Beginning) footerList.opacity = 1.0 timer.restart() + shareDialog.sheetOpen = false } delegate: Flickable { id: flick + property alias currentImageSource: image.source width: imageWidth height: imageHeight contentWidth: imageWidth contentHeight: imageHeight interactive: contentWidth > width || contentHeight > height onInteractiveChanged: listView.interactive = !interactive; clip: true z: index == listView.currentIndex ? 1000 : 0 Controls.ScrollBar.vertical: Controls.ScrollBar {} Controls.ScrollBar.horizontal: Controls.ScrollBar {} PinchArea { width: Math.max(flick.contentWidth, flick.width) height: Math.max(flick.contentHeight, flick.height) property real initialWidth property real initialHeight onPinchStarted: { initialWidth = flick.contentWidth initialHeight = flick.contentHeight } onPinchUpdated: { // adjust content pos due to drag flick.contentX += pinch.previousCenter.x - pinch.center.x flick.contentY += pinch.previousCenter.y - pinch.center.y // resize content flick.resizeContent(Math.max(imageWidth*0.7, initialWidth * pinch.scale), Math.max(imageHeight*0.7, initialHeight * pinch.scale), pinch.center) } onPinchFinished: { // Move its content within bounds. if (flick.contentWidth < root.imageWidth || flick.contentHeight < root.imageHeight) { zoomAnim.x = 0; zoomAnim.y = 0; zoomAnim.width = root.imageWidth; zoomAnim.height = root.imageHeight; zoomAnim.running = true; } else { flick.returnToBounds(); } } ParallelAnimation { id: zoomAnim property real x: 0 property real y: 0 property real width: root.imageWidth property real height: root.imageHeight NumberAnimation { target: flick property: "contentWidth" from: flick.contentWidth to: zoomAnim.width duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } NumberAnimation { target: flick property: "contentHeight" from: flick.contentHeight to: zoomAnim.height duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } NumberAnimation { target: flick property: "contentY" from: flick.contentY to: zoomAnim.y duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } NumberAnimation { target: flick property: "contentX" from: flick.contentX to: zoomAnim.x duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } Image { id: image width: flick.contentWidth height: flick.contentHeight source: model.imageurl fillMode: Image.PreserveAspectFit asynchronous: true autoTransform: true sourceSize.width: imageWidth * 2 sourceSize.height: imageHeight * 2 MouseArea { anchors.fill: parent onDoubleClicked: { if (flick.interactive) { zoomAnim.x = 0; zoomAnim.y = 0; zoomAnim.width = root.imageWidth; zoomAnim.height = root.imageHeight; zoomAnim.running = true; } else { zoomAnim.x = mouse.x * 2; zoomAnim.y = mouse.y *2; zoomAnim.width = root.imageWidth * 3; zoomAnim.height = root.imageHeight * 3; zoomAnim.running = true; } } onWheel: { if (wheel.modifiers & Qt.ControlModifier) { if (wheel.angleDelta.y != 0) { var factor = 1 + wheel.angleDelta.y / 600; zoomAnim.running = false; zoomAnim.width = Math.min(Math.max(root.imageWidth, zoomAnim.width * factor), root.imageWidth * 4); zoomAnim.height = Math.min(Math.max(root.imageHeight, zoomAnim.height * factor), root.imageHeight * 4); //actual factors, may be less than factor var xFactor = zoomAnim.width / flick.contentWidth; var yFactor = zoomAnim.height / flick.contentHeight; zoomAnim.x = flick.contentX * xFactor + (((wheel.x - flick.contentX) * xFactor) - (wheel.x - flick.contentX)) zoomAnim.y = flick.contentY * yFactor + (((wheel.y - flick.contentY) * yFactor) - (wheel.y - flick.contentY)) zoomAnim.running = true; } else if (wheel.pixelDelta.y != 0) { flick.resizeContent(Math.min(Math.max(root.imageWidth, flick.contentWidth + wheel.pixelDelta.y), root.imageWidth * 4), Math.min(Math.max(root.imageHeight, flick.contentHeight + wheel.pixelDelta.y), root.imageHeight * 4), wheel); } } } } } } } } PathView { id: footerList height: Kirigami.Units.gridUnit * 4 model: listView.model currentIndex: listView.currentIndex pathItemCount: applicationWindow().width / (Kirigami.Units.gridUnit * 5) interactive: false preferredHighlightBegin: 0.5 preferredHighlightEnd: 0.5 highlightRangeMode: PathView.StrictlyEnforceRange Behavior on opacity { OpacityAnimator { duration: 500}} path: Path { startX: 0 startY: applicationWindow().height - (Kirigami.Units.gridUnit * 5) PathAttribute { name: "iconScale"; value: 0.5 } PathLine { x: applicationWindow().width / 2 y: applicationWindow().height - (Kirigami.Units.gridUnit * 5) } PathAttribute { name: "iconScale"; value: 1.5 } PathLine { x: applicationWindow().width y: applicationWindow().height - (Kirigami.Units.gridUnit * 5) } PathAttribute { name: "iconScale"; value: 0.5 } } delegate: Item { scale: PathView.iconScale height: Kirigami.Units.gridUnit * 4 width: height KQA.QImageItem { height: Kirigami.Units.gridUnit * 3.8 width: height anchors.centerIn: parent image: model.thumbnail } } } + + ShareDialog { + id: shareDialog + inputData: { urls: [] } + sheetOpen: false + onFinished: { + if (error==0 && output.url !== "") { + console.assert(output.url !== undefined); + var resultUrl = output.url; + console.log("Received", resultUrl) + //Qt.openUrlExternally(resultUrl) + notificationManager.showNotification( true, resultUrl); + } else { + notificationManager.showNotification( false); + } + } + } - //FIXME: placeholder, will have to use the state machine - Controls.Button { - text: i18n("Back") - onClicked: root.state = "closed" + Koko.NotificationManager { + id: notificationManager } } diff --git a/qmlUiKirigami/Main.qml b/qmlUiKirigami/Main.qml index eaa6947..42b4a1b 100644 --- a/qmlUiKirigami/Main.qml +++ b/qmlUiKirigami/Main.qml @@ -1,206 +1,206 @@ /* * Copyright (C) 2017 Atul Sharma * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ import QtQuick 2.1 import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.0 as Kirigami import org.kde.koko 0.1 as Koko Kirigami.ApplicationWindow { id: root header: Kirigami.ApplicationHeader {} /* * currentImage now stores the information related to the source model */ QtObject { id: currentImage property int index property var model property GridView view : pageStack.currentItem.flickable onIndexChanged: { view.currentIndex = view.model.proxyIndex(currentImage.index) } } pageStack.initialPage: AlbumView { id: albumView model: imageFolderModel title: i18n("Folders") } globalDrawer: Sidebar { id: sideBar onFilterBy: { pageStack.pop(albumView) albumView.title = i18n(value) previouslySelectedAction.checked = false switch( value){ case "Countries": { albumView.model = imageLocationModelCountry; imageListModel.locationGroup = Koko.Types.Country; break; } case "States": { albumView.model = imageLocationModelState; imageListModel.locationGroup = Koko.Types.State; break; } case "Cities": { albumView.model = imageLocationModelCity; imageListModel.locationGroup = Koko.Types.City; break; } case "Years": { albumView.model = imageTimeModelYear; imageListModel.timeGroup = Koko.Types.Year; break; } case "Months": { albumView.model = imageTimeModelMonth; imageListModel.timeGroup = Koko.Types.Month; break; } case "Weeks": { albumView.model = imageTimeModelWeek; imageListModel.timeGroup = Koko.Types.Week; break; } case "Days": { albumView.model = imageTimeModelDay; imageListModel.timeGroup = Koko.Types.Day; break; } case "Folders": { albumView.model = imageFolderModel; imageListModel.locationGroup = -1; imageListModel.timeGroup = -1; break; } } } } Koko.SortModel { id: imageFolderModel sourceModel: Koko.ImageFolderModel { /** * imagePathArgument[0] sets the column 0 of the pageStack to reflect either a foreign path or ~/Pictures */ url: imagePathArgument == "" ? "" : imagePathArgument[0] /** * makes sure that operation only occurs after the model is populated */ onRowsInserted: { for( var i = 1; i < imagePathArgument.length -1 ; i++) { pageStack.push( Qt.resolvedUrl("ImageFolderAlbumView.qml"), { "sourceUrl": imagePathArgument[i] }) } /** * To set the currentImage when no folder is pushed */ if ( (currentImage.view.model.sourceModel == this) && (indexForUrl(imagePathArgument[imagePathArgument.length - 1]) != -1) ) { currentImage.model = this currentImage.index = indexForUrl(imagePathArgument[imagePathArgument.length - 1]) } } } /* * filterRole is an Item property exposed by the QSortFilterProxyModel */ filterRole: Koko.Roles.MimeTypeRole } Koko.SortModel { id: imageTimeModelYear sourceModel: Koko.ImageTimeModel { group: Koko.Types.Year } sortRoleName: "date" } Koko.SortModel { id: imageTimeModelMonth sourceModel: Koko.ImageTimeModel { group: Koko.Types.Month } sortRoleName: "date" } Koko.SortModel { id: imageTimeModelWeek sourceModel: Koko.ImageTimeModel { group: Koko.Types.Week } sortRoleName: "date" } Koko.SortModel { id: imageTimeModelDay sourceModel: Koko.ImageTimeModel { group: Koko.Types.Day } sortRoleName: "date" } Koko.SortModel { id: imageLocationModelCountry sourceModel: Koko.ImageLocationModel { group: Koko.Types.Country } } Koko.SortModel { id: imageLocationModelState sourceModel: Koko.ImageLocationModel { group: Koko.Types.State } } Koko.SortModel { id: imageLocationModelCity sourceModel: Koko.ImageLocationModel { group: Koko.Types.City } } Koko.ImageListModel { id: imageListModel } ImageViewer { id: imageViewer //go on top of the overlay drawer //HACK on the parent and z to go on top of the handle as well - z: 2000002 + z: 1999999 parent: root.overlay.parent width: overlay.width height: overlay.height indexValue: currentImage.index sourceModel: currentImage.model imageWidth: root.width imageHeight: root.height state: imagePathArgument == "" ? "closed" : "open" } } diff --git a/qmlUiKirigami/ShareDialog.qml b/qmlUiKirigami/ShareDialog.qml new file mode 100644 index 0000000..2466727 --- /dev/null +++ b/qmlUiKirigami/ShareDialog.qml @@ -0,0 +1,64 @@ +/* + * Copyright 2017 by Atul Sharma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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.7 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.1 as Controls +import org.kde.purpose 1.0 as Purpose +import org.kde.kirigami 2.1 as Kirigami + +Kirigami.OverlaySheet +{ + id: window + property alias inputData: view.inputData + property bool running: false + signal finished(var output, int error, string message) + + Controls.BusyIndicator { + visible: window.running + anchors.fill: parent + } + + contentItem: ColumnLayout { + height: Kirigami.Units.gridUnit * 16 + + Kirigami.Heading { + text: window.inputData.mimeType ? i18n("Shares for '%1'", window.inputData.mimeType) : "" + } + Purpose.AlternativesView { + id: view + Layout.fillWidth: true + Layout.fillHeight: true + pluginType: "Export" + + delegate: Kirigami.BasicListItem { + label: model.display + icon: "arrow-right" + onClicked: view.createJob (model.index) + Keys.onReturnPressed: view.createJob (model.index) + Keys.onEnterPressed: view.createJob (model.index) + } + + onRunningChanged: window.running = running + onFinished: { + window.finished(output, error, message) + } + } + } +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4d94059..3591fdc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,131 +1,134 @@ # # Common Library # set(LIB_SRCS imagestorage.cpp filesystemimagefetcher.cpp ${LIB_SRCS} ) add_library(kokocommon SHARED ${LIB_SRCS}) target_link_libraries(kokocommon Qt5::Core Qt5::Positioning Qt5::Sql KF5::CoreAddons ) generate_export_header(kokocommon BASE_NAME KOKO EXPORT_FILE_NAME koko_export.h) install(TARGETS kokocommon EXPORT KokoLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) # # Application # add_executable(koko main.cpp reversegeocoder.cpp filesystemtracker.cpp processor.cpp committimer.cpp imageprocessorrunnable.cpp exiv2extractor.cpp kokoconfig.cpp kdtree.c ) target_link_libraries(koko Qt5::Quick Qt5::Widgets Qt5::Qml Qt5::Positioning KF5::ConfigCore KF5::DBusAddons KF5::I18n KF5::CoreAddons KF5::KIOCore kokocommon ${EXIV2_LIBRARIES} ) install(TARGETS koko ${INSTALL_TARGETS_DEFAULT_ARGS}) # # QML Plugin # set (qml_plugin_SRCS qmlplugins.cpp tagmodel.cpp imagelocationmodel.cpp imagetimemodel.cpp imagefoldermodel.cpp sortmodel.cpp allimagesmodel.cpp fileinfo.cpp imagelistmodel.cpp + notificationmanager.cpp types.cpp roles.cpp ) add_library (kokoqmlplugin SHARED ${qml_plugin_SRCS}) target_link_libraries (kokoqmlplugin Qt5::Qml KF5::KIOCore KF5::KIOFileWidgets KF5::KIOWidgets KF5::GuiAddons + KF5::Notifications kokocommon ) install (TARGETS kokoqmlplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/koko) install (FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/koko) install (FILES org.kde.koko.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) # # Reverse GeoLookup Data # # Packagers can download the file and put it in the tarball if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cities1000.zip) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/cities1000.zip DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) endif() if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/cities1000.zip) file (DOWNLOAD "http://download.geonames.org/export/dump/cities1000.zip" ${CMAKE_CURRENT_BINARY_DIR}/cities1000.zip SHOW_PROGRESS ) endif() execute_process( COMMAND ${CMAKE_COMMAND} -E tar -xzf ${CMAKE_CURRENT_BINARY_DIR}/cities1000.zip WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/admin1CodesASCII.txt) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/admin1CodesASCII.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) endif() if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/admin1CodesASCII.txt) file (DOWNLOAD "http://download.geonames.org/export/dump/admin1CodesASCII.txt" ${CMAKE_CURRENT_BINARY_DIR}/admin1CodesASCII.txt SHOW_PROGRESS ) endif() file(RENAME ${CMAKE_CURRENT_BINARY_DIR}/admin1CodesASCII.txt ${CMAKE_CURRENT_BINARY_DIR}/admin1Codes.txt) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/admin2Codes.txt) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/admin2Codes.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) endif() if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/admin2Codes.txt) file (DOWNLOAD "http://download.geonames.org/export/dump/admin2Codes.txt" ${CMAKE_CURRENT_BINARY_DIR}/admin2Codes.txt SHOW_PROGRESS ) endif() install (FILES ${CMAKE_CURRENT_BINARY_DIR}/cities1000.txt DESTINATION ${DATA_INSTALL_DIR}/koko) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/admin1Codes.txt DESTINATION ${DATA_INSTALL_DIR}/koko) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/admin2Codes.txt DESTINATION ${DATA_INSTALL_DIR}/koko) install (FILES countries.csv DESTINATION ${DATA_INSTALL_DIR}/koko) +install (FILES koko.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR}) diff --git a/src/koko.notifyrc b/src/koko.notifyrc new file mode 100644 index 0000000..703aebc --- /dev/null +++ b/src/koko.notifyrc @@ -0,0 +1,13 @@ +[Global] +IconName=koko +Name=Koko + +[Event/sharingSuccess] +Name=Sharing success +Comment=Image Shared Successfully +Action=Popup + +[Event/sharingFailed] +Name=Sharing failed +Comment=Image Sharing failed +Action=Popup diff --git a/src/notificationmanager.cpp b/src/notificationmanager.cpp new file mode 100644 index 0000000..606aa37 --- /dev/null +++ b/src/notificationmanager.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2017 by Atul Sharma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +#include "notificationmanager.h" + +NotificationManager::NotificationManager(QObject* parent) +{ + Q_UNUSED(parent) + m_sharingSuccess = new KNotification( "sharingSuccess", KNotification::Persistent); + + m_sharingFailed = new KNotification( "sharingFailed", KNotification::CloseOnTimeout); + m_sharingFailed->setText("Sharing failed"); +} + +NotificationManager::~NotificationManager() +{ + delete m_sharingFailed; + delete m_sharingSuccess; +} + +void NotificationManager::showNotification(bool valid, QVariant url) +{ + if (valid) { + m_sharingSuccess->setText("Shared url for image is " + url.toString()); + m_sharingSuccess->sendEvent(); + } else { + m_sharingFailed->sendEvent(); + } +} + +#include "moc_notificationmanager.cpp" diff --git a/src/notificationmanager.h b/src/notificationmanager.h new file mode 100644 index 0000000..73dcd52 --- /dev/null +++ b/src/notificationmanager.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 by Atul Sharma + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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. + */ + +#ifndef NOTIFICATION_MANAGER_H +#define NOTIFICATION_MANAGER_H + +#include +#include + +class NotificationManager: public QObject +{ + Q_OBJECT +public: + explicit NotificationManager(QObject *parent = 0); + ~NotificationManager(); + + /** + * @argument valid: to check whether the returned url after sharing is valid or not + * @argument url: the valid url returned after sharing the image + */ + Q_INVOKABLE void showNotification(bool valid, QVariant url = QVariant()); + +private: + KNotification *m_sharingSuccess; + KNotification *m_sharingFailed; + +}; +#endif diff --git a/src/qmlplugins.cpp b/src/qmlplugins.cpp index 4f594b3..32ceb97 100644 --- a/src/qmlplugins.cpp +++ b/src/qmlplugins.cpp @@ -1,54 +1,56 @@ /* * Copyright (C) 2014 Vishesh Handa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #include "qmlplugins.h" #include "tagmodel.h" #include "imagelocationmodel.h" #include "imagetimemodel.h" #include "imagefoldermodel.h" #include "sortmodel.h" #include "allimagesmodel.h" #include "fileinfo.h" #include "imagelistmodel.h" +#include "notificationmanager.h" #include "types.h" #include "roles.h" #include void QmlPlugins::initializeEngine(QQmlEngine *, const char *) { } void QmlPlugins::registerTypes(const char *uri) { qmlRegisterType (); qmlRegisterType (uri, 0, 1, "TagModel"); qmlRegisterType (uri, 0, 1, "ImageLocationModel"); qmlRegisterType (uri, 0, 1, "ImageTimeModel"); qmlRegisterType (uri, 0, 1, "ImageFolderModel"); qmlRegisterType (uri, 0, 1, "AllImagesModel"); qmlRegisterType (uri, 0, 1, "SortModel"); qmlRegisterType (uri, 0, 1, "FileInfo"); qmlRegisterType (uri, 0, 1, "ImageListModel"); + qmlRegisterType (uri, 0, 1, "NotificationManager"); qmlRegisterUncreatableType(uri, 0, 1, "Types", "Cannot instantiate the Types class"); qmlRegisterUncreatableType(uri, 0, 1, "Roles", "Cannot instantiate the Roles class"); }