diff --git a/src/qml/ImagesView.qml b/src/qml/ImagesView.qml index 06c4091..6b84588 100644 --- a/src/qml/ImagesView.qml +++ b/src/qml/ImagesView.qml @@ -1,210 +1,207 @@ import QtQml 2.2 import QtQuick 2.0 import QtQuick.Controls 1.2 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.2 import org.kde.kamoso 3.0 import org.kde.purpose 1.0 StackView { id: stack property string mimeFilter property alias nameFilter: view.nameFilter clip: true Menu { id: menu Instantiator { id: inst model: PurposeAlternativesModel { id: altsModel pluginType: "Export" inputData: { "urls": view.selection, "mimeType": stack.mimeFilter } } MenuItem { text: display iconName: model.iconName onTriggered: { var config = altsModel.configureJob(index) if (config.isReady) startShareJob(config) else { stack.push({ item: shareWizardComponent, properties: { configuration: config } }) } view.selection = [] } } onObjectAdded: menu.insertItem(menu.items.count, object) onObjectRemoved: menu.removeItem(object) } } initialItem: Item { ColumnLayout { anchors.fill: parent DirectoryView { id: view Layout.fillWidth: true Layout.fillHeight: true mimeFilter: [stack.mimeFilter] } - ToolBar { + RowLayout { Layout.fillWidth: true - RowLayout { - anchors.fill: parent - Label { - Layout.fillWidth: true - text: view.selection.length==0 ? i18n("Gallery") : i18n("%1 selected", view.selection.length) + Label { + Layout.fillWidth: true + text: view.selection.length==0 ? i18n("Gallery") : i18n("%1 selected", view.selection.length) + } + ToolButton { + iconName: "user-trash" + tooltip: i18n("Move to trash...") + enabled: view.selection.length>0 + onClicked: { + trashDialog.visible = true } - ToolButton { - iconName: "user-trash" - tooltip: i18n("Move to trash...") - enabled: view.selection.length>0 - onClicked: { - trashDialog.visible = true + + Dialog { + id: trashDialog + title: i18n("Move to trash...") + + Label { + text: i18np("Are you sure you want to remove %1 file?", "Are you sure you want to remove %1 files?", view.selection.length) } - Dialog { - id: trashDialog - title: i18n("Move to trash...") - - Label { - text: i18np("Are you sure you want to remove %1 file?", "Are you sure you want to remove %1 files?", view.selection.length) - } - - standardButtons: StandardButton.Ok | StandardButton.Cancel - onAccepted: { - console.log("Trash, FFS!!", view.selection); - webcam.trashFiles(view.selection); - } - onVisibleChanged: if (!visible) { - view.selection = [] - } + standardButtons: StandardButton.Ok | StandardButton.Cancel + onAccepted: { + console.log("Trash, FFS!!", view.selection); + webcam.trashFiles(view.selection); + } + onVisibleChanged: if (!visible) { + view.selection = [] } } - ToolButton { - iconName: "document-share" - menu: menu - tooltip: i18n("Share...") - enabled: view.selection.length>0 - } - ToolButton { - iconName: "folder-open" - tooltip: i18n("Open Folder") - onClicked: Qt.openUrlExternally(config.saveUrl) - } + } + ToolButton { + iconName: "document-share" + menu: menu + tooltip: i18n("Share...") + enabled: view.selection.length>0 + } + ToolButton { + iconName: "folder-open" + tooltip: i18n("Open Folder") + onClicked: Qt.openUrlExternally(config.saveUrl) } } } } function startShareJob(config) { var job = config.createJob(); stack.push({ item: busyComponent, properties: { job: job } }); job.start(); job.result.connect(function(job) { if (job.output.url=="") return; stack.replace({ item: sharedComponent, properties: { text: job.output.url }, replace: true }) }); } Component { id: sharedComponent ColumnLayout { property alias text: field.text TextField { id: field Layout.fillWidth: true readOnly: true focus: true onTextChanged: { selectAll(); copy(); } } Label { Layout.fillHeight: true text: i18n("The URL was just shared") } Button { text: i18n("Back") onClicked: { stack.pop() } } } } Component { id: shareWizardComponent ColumnLayout { property alias configuration: wiz.configuration PurposeWizard { id: wiz Layout.fillHeight: true Layout.fillWidth: true } RowLayout { Button { text: i18n("Run") enabled: wiz.configuration && wiz.configuration.isReady onClicked: { stack.pop(); startShareJob(wiz.configuration); } } Button { text: i18n("Back") onClicked: { stack.pop(); wiz.cancel() } } } } } Component { id: busyComponent ColumnLayout { property QtObject job BusyIndicator { Layout.fillWidth: true Layout.fillHeight: true running: true } Button { anchors.right: parent.right text: i18n("Cancel") enabled: parent.job && (parent.job.capabilities & KJob.Killable) onClicked: { if (parent.job.kill()) { stack.pop() } } } } } } diff --git a/src/qml/Main.qml b/src/qml/Main.qml index b47a63f..49204fd 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -1,313 +1,250 @@ import QtQuick 2.0 import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGStreamer 1.0 +import org.kde.kirigami 2.0 as Kirigami import org.kde.kquickcontrolsaddons 2.0 import org.kde.kamoso 3.0 -ApplicationWindow +Kirigami.ApplicationWindow { + id: root width: 700 height: 450 visible: true title: i18n("Kamoso") + header: Item {} function awesomeAnimation(path) { // tada.x = visor.x // tada.y = 0 // tada.width = visor.width // tada.height = visor.height tada.source = "file://"+path tada.state = "go" tada.state = "done" // tada.visible = true } - Connections { - target: webcam - onPhotoTaken: awesomeAnimation(path) - } Image { id: tada z: 10 width: 10 height: 10 fillMode: Image.PreserveAspectFit states: [ State { name: "go" PropertyChanges { target: tada; x: visor.x } PropertyChanges { target: tada; y: visor.y } PropertyChanges { target: tada; width: visor.width } PropertyChanges { target: tada; height: visor.height } PropertyChanges { target: tada; opacity: 1 } }, State { name: "done" - PropertyChanges { target: tada; x: visor.width-10 } - PropertyChanges { target: tada; y: visor.height+controls.height } + PropertyChanges { target: tada; x: 0 } + PropertyChanges { target: tada; y: root.height } PropertyChanges { target: tada; width: deviceSelector.height } PropertyChanges { target: tada; height: deviceSelector.height } PropertyChanges { target: tada; opacity: 0.5 } } ] transitions: [ Transition { from: "go"; to: "done" NumberAnimation { target: tada - properties: "width,height"; duration: 300; easing.type: Easing.InCubic } + properties: "width,height"; duration: 700; easing.type: Easing.InCubic } NumberAnimation { target: tada - properties: "x,y"; duration: 300; easing.type: Easing.InCubic } + properties: "x,y"; duration: 700; easing.type: Easing.InCubic } NumberAnimation { target: tada properties: "opacity"; duration: 300 } } ] } - property list actions: [ - Mode { - mimes: "image/jpeg" - checkable: false - icon: "shoot" - text: i18n("Shoot") - property int photosTaken: 0 - modeInfo: i18np("1 photo", "%1 photos", photosTaken) - nameFilter: "picture_*" + Mode { + id: photoMode + mimes: "image/jpeg" + checkable: false + iconName: "shoot" + text: i18n("Shoot") + property int photosTaken: 0 + modeInfo: i18np("1 photo", "%1 photos", photosTaken) + nameFilter: "picture_*" + + onTriggered: { + if (config.useFlash) + whites.showAll() + webcam.takePhoto() + photosTaken++; + } - onTrigger: { + Connections { + target: webcam + onPhotoTaken: awesomeAnimation(path) + } + } + Mode { + id: burstMode + mimes: "image/jpeg" + checkable: true + iconName: "burst" + text: i18n("Burst") + property int photosTaken: 0 + modeInfo: i18np("1 photo", "%1 photos", photosTaken) + nameFilter: "picture_*" + + readonly property var smth: Timer { + id: burstTimer + running: burstMode.checked + interval: 1000 + repeat: true + onTriggered: { if (config.useFlash) whites.showAll() webcam.takePhoto() - photosTaken++; - } - }, - Mode { - mimes: "image/jpeg" - checkable: true - icon: "burst" - text: i18n("Burst") - property int photosTaken: 0 - modeInfo: i18np("1 photo", "%1 photos", photosTaken) - nameFilter: "picture_*" - - onTrigger: { - burstTimer.running = checked; - } - - readonly property var smth: Timer { - id: burstTimer - interval: 1000 - repeat: true - onTriggered: { - if (config.useFlash) - whites.showAll() - webcam.takePhoto() - photosTaken++; - } + burstMode.photosTaken++; } - }, - Mode { - mimes: "video/x-matroska" - checkable: true - icon: "record" - text: i18n("Record") - modeInfo: webcam.recordingTime - nameFilter: "video_*" + } + } + Mode { + id: videoMode + mimes: "video/x-matroska" + checkable: true + iconName: "record" + text: i18n("Record") + modeInfo: webcam.recordingTime + nameFilter: "video_*" + + onTriggered: { + webcam.isRecording = checked; + } + } - onTrigger: { - webcam.isRecording = checked; - } + globalDrawer: Kirigami.GlobalDrawer { + bannerImageSource: "https://images.unsplash.com/photo-1481933236927-d92e97e3194c?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=25a62a567881e623a7a9cd5819ed0910" + drawerOpen: false + handleVisible: true + modal: true + ImagesView { + Layout.fillHeight: true + Layout.fillWidth: true +// mimeFilter: buttonGroup.current.mimes +// nameFilter: buttonGroup.current.nameFilter } - ] + } - Item { - id: mainButtonBar - anchors { - left: parent.left - right: settingsDialog.left - bottom: parent.bottom + contextDrawer: Kirigami.OverlayDrawer { + edge: Qt.RightEdge + drawerOpen: false + handleVisible: true + modal: true + contentItem: Config { + implicitWidth: Math.min (Kirigami.Units.gridUnit * 20, root.width * 0.8) + anchors.fill: parent } - height: controls.height - Item { - anchors { - left: parent.left - right: controls.left - top: controls.top - bottom: parent.bottom - } - RowLayout { - anchors.centerIn: parent - spacing: 0 + } - ExclusiveGroup { id: buttonGroup } - Repeater { - model: actions - delegate: Button { - readonly property QtObject stuff: modelData - exclusiveGroup: buttonGroup - isDefault: true - tooltip: model.text ? i18n("Switch to '%1' mode", model.text) : "" - checkable: true - checked: index==0 - text: (checked ? model.text : "") + pageStack.initialPage: Kirigami.Page { + id: visor + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 - iconName: model.icon + state: "shoot" + states: [ + State { + name: "shoot" + PropertyChanges { + target: visor + actions { + left: videoMode.adoptAction + main: photoMode + right: burstMode.adoptAction } } - } - } - - Button { - id: controls - width: 100 - height: 40 - checkable: buttonGroup.current.stuff.checkable - tooltip: buttonGroup.current.stuff.text - focus: true - - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom + }, + State { + name: "record" + PropertyChanges { + target: visor + actions { + left: photoMode.adoptAction + main: videoMode + right: burstMode.adoptAction + } + } + }, - QIconItem { - anchors { - centerIn: parent + State { + name: "burst" + PropertyChanges { + target: visor + actions { + left: videoMode.adoptAction + main: burstMode + right: photoMode.adoptAction + } } - height: parent.height*0.75 - width: height - icon: buttonGroup.current.stuff.icon } + ] - onClicked: { - buttonGroup.current.stuff.trigger(checked) - } + Rectangle { + anchors.fill: parent + color: "black" + z: -1 } - Item { - anchors { - top: controls.top - left: controls.right - right: parent.right - bottom: parent.bottom - } - - RowLayout { - anchors.centerIn: parent - spacing: 0 - Button { - id: galleryButton - checkable: true - checked: false - iconName: "folder-images" - tooltip: i18n("Show gallery...") - onClicked: settingsButton.checked = false; - } - - Button { - id: settingsButton + ColumnLayout { + id: deviceSelector + spacing: 10 + anchors.margins: 10 + anchors.top: parent.top + anchors.left: parent.left + visible: devicesModel.count>1 + + Repeater { + model: devicesModel + delegate: Button { width: 30 - iconName: "preferences-other" - checkable: true - tooltip: i18n("Show settings...") - onClicked: galleryButton.checked = false; + iconName: "camera-web" + tooltip: display + onClicked: devicesModel.playingDeviceUdi = udi } } } - } - - Item { - id: settingsDialog - anchors { - top: parent.top - right: parent.right - bottom: parent.bottom - } - width: (settingsButton.checked || galleryButton.checked) ? parent.width / 2.5 : 0 - Behavior on width { - PropertyAnimation { - duration: 200 - easing.type: Easing.OutExpo - } - } - Config { - anchors { - fill: parent - margins: 5 - } - visible: settingsButton.checked - } - - ImagesView { - anchors { - fill: parent - margins: 5 - } - - visible: galleryButton.checked - mimeFilter: buttonGroup.current.stuff.mimes - nameFilter: buttonGroup.current.stuff.nameFilter - } - } - - Rectangle { - id: visor - color: "black" - - anchors { - right: settingsDialog.left - left: parent.left - top: parent.top - bottom: mainButtonBar.top - } VideoItem { id: video visible: devicesModel.count>0 surface: videoSurface1 anchors.fill: parent } AnimatedImage { anchors.fill: video visible: !video.visible source: visible ? "http://i.imgur.com/OEiQ6k9.gif" : "" } Text { anchors { left: parent.left bottom: parent.bottom margins: 20 } - text: buttonGroup.current.stuff.modeInfo + text: root.pageStack.currentItem.modeInfo || "" visible: config.showOsd color: "white" styleColor: "black" font.pointSize: 20 style: Text.Outline } } - - ColumnLayout { - id: deviceSelector - height: 30 - spacing: 10 - anchors.margins: 10 - anchors.top: parent.top - anchors.left: parent.left - visible: devicesModel.count>1 - - Repeater { - model: devicesModel - delegate: Button { - width: 30 - iconName: "camera-web" - tooltip: display - onClicked: devicesModel.playingDeviceUdi = udi - } - } - } } diff --git a/src/qml/Mode.qml b/src/qml/Mode.qml index 90c3521..5f54507 100644 --- a/src/qml/Mode.qml +++ b/src/qml/Mode.qml @@ -1,14 +1,19 @@ -import QtQml 2.1 +import org.kde.kirigami 2.0 -QtObject { - property var mimes: null - property bool checkable: false - property string icon: "" - property string text: "" +Action { + id: modeAction + property string mimes: null + property string name: "" property string modeInfo: "" property string nameFilter: "" - signal trigger(bool checked) + readonly property Action adoptAction: Action { + iconName: modeAction.iconName + tooltip: modeAction.tooltip + onTriggered: { + visor.state = modeAction.iconName + } + } default property var things: [] }