diff --git a/XmlData.xml b/XmlData.xml
index 2758858..2f53b76 100644
--- a/XmlData.xml
+++ b/XmlData.xml
@@ -6,6 +6,7 @@
SingleNoPrint.svg
WhiteBackground.png
ExampleForeground.png
+
@@ -14,6 +15,7 @@
Single Image
Single.svg
WhiteBackground.png
+
@@ -22,6 +24,7 @@
Two Images
Double.svg
WhiteBackground.png
+
@@ -38,6 +41,7 @@
Four Images
Four.svg
WhiteBackground.png
+
@@ -45,10 +49,23 @@
+
+ Four Images Rotation
+ Four.svg
+ WhiteBackground.png
+
+
+ 0.0
+ 10.0
+ 20.0
+ 30.0
+
+
Four Images with Background
FourStars.svg
StarsBackground.jpg
+
@@ -60,6 +77,7 @@
Four Images Border
FourBorder.svg
WhiteBackground.png
+
diff --git a/qml.qrc b/qml.qrc
index 55d1423..1e93844 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -74,5 +74,9 @@
qml/content/PrinterPopup.qml
images/ExampleForeground.png
images/icon/SingleNoPrint.svg
+ qml/GalleryMenu.qml
+ qml/GalleryMenuForm.ui.qml
+ qml/content/DelegateGalleryItem.qml
+ qml/styles/RoundProgressBarStyle.qml
diff --git a/qml/Application.qml b/qml/Application.qml
index 5aca03a..71133f4 100644
--- a/qml/Application.qml
+++ b/qml/Application.qml
@@ -66,6 +66,7 @@ ApplicationWindow {
onPrinterChanged:
{
flow.collageMenu.printer = printer
+ flow.galleryMenu.printer = printer
}
ApplicationFlow
@@ -85,6 +86,11 @@ ApplicationWindow {
applicationSettings.multiplePrints = mainMenu.settingsPopup.switchMultiplePrints.checked
}
+ mainMenu.settingsPopup.switchPrintFromGallery.onCheckedChanged:
+ {
+ applicationSettings.printFromGallery = mainMenu.settingsPopup.switchPrintFromGallery.checked
+ }
+
mainMenu.settingsPopup.switchHideSnapshotSettings.onCheckedChanged:
{
applicationSettings.disableSnapshotSettingsPane = mainMenu.settingsPopup.switchHideSnapshotSettings.checked
@@ -136,7 +142,12 @@ ApplicationWindow {
applicationSettings.cameraName = mainMenu.settingsPopup.comboBoxCamera.currentText
}
- mainMenu.printerBusy: printer.busy
+ mainMenu.settingsPopup.switchEnableSettingsPassword.onCheckedChanged:
+ {
+ applicationSettings.enableSettingsPassword = mainMenu.settingsPopup.switchEnableSettingsPassword.checked
+ }
+
+ mainMenu.printerBusy: printer ? printer.busy : false
}
Settings
@@ -154,15 +165,19 @@ ApplicationWindow {
property bool disableSnapshotSettingsPane: false
property bool disableEffectPopup: false
property string cameraName: ""
+ property bool printFromGallery: true
+ property bool enableSettingsPassword: true
Component.onCompleted:
{
flow.mainMenu.settingsPopup.printerEnabled.checked = printEnable
+ flow.mainMenu.settingsPopup.switchPrintFromGallery.checked = printFromGallery
flow.mainMenu.settingsPopup.switchMultiplePrints.checked = multiplePrints
flow.mainMenu.settingsPinCode = password
flow.mainMenu.settingsPopup.mirrorCamera.checked = cameraMirrored
flow.mainMenu.settingsPopup.switchHideSnapshotSettings.checked = disableSnapshotSettingsPane
flow.mainMenu.settingsPopup.switchHideEffectPopup.checked = disableEffectPopup
+ flow.mainMenu.settingsPopup.switchEnableSettingsPassword.checked = enableSettingsPassword
flow.mainMenuModel.setShowPrintable(printEnable)
flow.collageMenu.multiplePrints = multiplePrints
flow.snapshotMenu.hideSnapshotSettingsPane = disableSnapshotSettingsPane
diff --git a/qml/ApplicationFlow.qml b/qml/ApplicationFlow.qml
index 42b1d2e..2975865 100644
--- a/qml/ApplicationFlow.qml
+++ b/qml/ApplicationFlow.qml
@@ -29,6 +29,11 @@ ApplicationFlowForm {
mainMenu.selectedCollageName = ""
}
+ mainMenu.onGalleryEnter:
+ {
+ state = "gallery"
+ }
+
snapshotMenu.onCaptured:
{
state = "imagePreview"
@@ -79,6 +84,16 @@ ApplicationFlowForm {
state = "collageSelection"
}
+ collageMenu.collageImage.onCollageImagesChanged:
+ {
+ snapshotMenu.snapshotTimeoutEnable = (count == 0)
+ }
+
+ galleryMenu.onExitGallery:
+ {
+ state = "collageSelection"
+ }
+
Behavior on slideValueCollageSelection {
PropertyAnimation {
duration: flow.animationDuration
@@ -106,6 +121,13 @@ ApplicationFlowForm {
easing.type: Easing.InOutQuad
}
}
+
+ Behavior on slideValueGalleryMenu {
+ PropertyAnimation {
+ duration: flow.animationDuration
+ easing.type: Easing.InOutQuad
+ }
+ }
}
diff --git a/qml/ApplicationFlowForm.ui.qml b/qml/ApplicationFlowForm.ui.qml
index dcad932..ba5d008 100644
--- a/qml/ApplicationFlowForm.ui.qml
+++ b/qml/ApplicationFlowForm.ui.qml
@@ -9,11 +9,13 @@ Item {
property alias snapshotMenu: snapshotMenu
property alias imagePreview: imagePreview
property alias collageMenu: collageMenu
+ property alias galleryMenu: galleryMenu
property real slideValueCollageSelection: 0.0
property real slideValueSnapshotMenu: 1.0
property real slideValuePreviewMenu: 1.0
property real slideValueCollageMenu: 1.0
+ property real slideValueGalleryMenu: 1.0
MainMenu {
id: mainMenu
@@ -47,6 +49,16 @@ Item {
width: root.width
height: root.height
}
+
+ GalleryMenu
+ {
+ id: galleryMenu
+ x: root.width * slideValueGalleryMenu
+ y: 0
+ width: root.width
+ height: root.height
+ }
+
states: [
State {
name: "collageSelection"
@@ -108,6 +120,33 @@ Item {
target: snapshotMenu
visible: false
}
+ },
+ State {
+ name: "gallery"
+
+ PropertyChanges {
+ target: root
+ slideValueCollageSelection: -1.0
+ slideValueSnapshotMenu: -1.0
+ slideValuePreviewMenu: -1.0
+ slideValueCollageMenu: -1.0
+ slideValueGalleryMenu: 0.0
+ }
+
+ PropertyChanges {
+ target: snapshotMenu
+ visible: false
+ }
+
+ PropertyChanges {
+ target: imagePreview
+ visible: false
+ }
+
+ PropertyChanges {
+ target: collageMenu
+ visible: false
+ }
}
]
}
diff --git a/qml/CollageMenu.qml b/qml/CollageMenu.qml
index c3141c2..e7aa90a 100644
--- a/qml/CollageMenu.qml
+++ b/qml/CollageMenu.qml
@@ -12,9 +12,9 @@ CollageMenuForm {
signal next
signal exit
- printButton.enabled: !printer.busy
- property real printerHeight : printer.getPrintSize().height
- property real printerWidth : printer.getPrintSize().width
+ printButton.enabled: printer ? !printer.busy : false
+ property real printerHeight : form.collageImage.imageModel ? form.collageImage.imageModel.collagePixelSize.height : 0
+ property real printerWidth : form.collageImage.imageModel ? form.collageImage.imageModel.collagePixelSize.width : 0
printerRatio: printerHeight / printerWidth
nextButton.onClicked:
@@ -31,10 +31,11 @@ CollageMenuForm {
var path = applicationSettings.foldername.toString()
path = path.replace(/^(file:\/{2})/,"");
var cleanPath = decodeURIComponent(path);
- console.log(cleanPath)
var filename = cleanPath + "/collage/Coll_"+ new Date().toLocaleString(locale, "dd_MM_yyyy_hh_mm_ss") + ".png"
- collageRenderer.saveImage(filename, printer.getPrintSize())
- console.log("Collage rendered")
+ console.log("Save files to: " + filename)
+ collageRenderer.saveImage(filename, form.collageImage.imageModel.collagePixelSize)
+ console.log("Collage rendered width: " + Number(form.collageImage.imageModel.collagePixelSize.width).toString()
+ + " height: " + form.collageImage.imageModel.collagePixelSize.height)
}
collageRenderer.onSavingChanged:
diff --git a/qml/CollageMenuForm.ui.qml b/qml/CollageMenuForm.ui.qml
index efbd402..46c3dc2 100644
--- a/qml/CollageMenuForm.ui.qml
+++ b/qml/CollageMenuForm.ui.qml
@@ -35,8 +35,11 @@ Item {
property double aimedRatio: printerRatio
// SIZING
- property double availableWidth: parent.width - rightMargin - leftMargin
- property double availableHeight: parent.height - bottomMargin - topMargin
+ property double calculatedWidth: parent.width - rightMargin - leftMargin
+ property double calculatedHeight: parent.height - bottomMargin - topMargin
+
+ property double availableWidth: calculatedWidth > 10 ? calculatedWidth : 10
+ property double availableHeight: calculatedHeight > 10 ? calculatedHeight : 10
property bool parentIsLarge: parentRatio > aimedRatio
diff --git a/qml/GalleryMenu.qml b/qml/GalleryMenu.qml
new file mode 100644
index 0000000..bdec22c
--- /dev/null
+++ b/qml/GalleryMenu.qml
@@ -0,0 +1,55 @@
+import QtQuick 2.5
+import Printer 1.0
+
+GalleryMenuForm {
+ property alias foldermodel: galleryForm.foldermodel
+ signal exitGallery
+ property alias printer: galleryForm.printer
+
+ id: galleryForm
+
+
+ scrollDownButton.onPressed:
+ {
+ scrollBar.increase()
+ }
+
+ scrollUpButton.onPressed:
+ {
+ scrollBar.decrease()
+ }
+
+ photosGrid.onCurrentIndexChanged: {
+ photoView.positionViewAtIndex(photosGrid.currentIndex, ListView.Contain)
+ }
+
+ photoView.onCurrentIndexChanged: {
+ photosGrid.positionViewAtIndex(photoView.currentIndex, GridView.Contain)
+ }
+
+ function resetGallery()
+ {
+ viewState = "inGrid"
+ }
+
+ exitButton.onClicked:
+ {
+ exitGallery()
+ }
+
+ photoButton.onClicked:
+ {
+ foldermodel.folder = applicationSettings.foldername
+ }
+
+ collageButton.onClicked:
+ {
+ foldermodel.folder = applicationSettings.foldername + "/collage"
+ }
+}
+
+
+/*##^## Designer {
+ D{i:0;autoSize:true;height:480;width:640}
+}
+ ##^##*/
diff --git a/qml/GalleryMenuForm.ui.qml b/qml/GalleryMenuForm.ui.qml
new file mode 100644
index 0000000..a48b344
--- /dev/null
+++ b/qml/GalleryMenuForm.ui.qml
@@ -0,0 +1,260 @@
+import QtQuick 2.5
+import Qt.labs.folderlistmodel 2.1
+import QtQuick.Layouts 1.2
+import QtQuick.Controls 2.1
+import QtQuick.Window 2.0
+import QtQml.Models 2.2
+import Printer 1.0
+import "content"
+
+Item {
+ property alias foldermodel: folderModel
+ property alias scrollUpButton: scrollBarUpButton
+ property alias scrollDownButton: scrollBarDownButton
+ property alias scrollBar: galleryScrollbar
+ property alias photosGrid: photosGridView
+ property alias photoView: photosListView
+ property alias viewState: root.state
+ property alias exitButton: exitButton
+ property alias photoButton: photoButton
+ property alias collageButton: collageButton
+ property Printer printer
+
+ Image {
+ id: root
+ anchors.fill: parent
+
+ source: "../images/cardboard.png"
+ fillMode: Image.Tile
+
+ property bool imageLoading: false
+
+ Rectangle
+ {
+ id: sidebar
+ width: 150
+ height: parent.height
+ color: "#4d60ea"
+
+ ColumnLayout
+ {
+ anchors.fill: parent
+ anchors.verticalCenter: parent.verticalCenter
+
+ Button
+ {
+ id: photoButton
+
+ Layout.alignment: Qt.AlignLeft
+ flat: true
+ implicitWidth: parent.width
+ implicitHeight: parent.height / 2
+
+ contentItem: Item {
+ anchors.fill: parent
+
+ Text {
+ text: qsTr("Photos")
+
+ color: "white"
+ font.family: "DejaVu Serif"
+ font.pixelSize: 50
+ anchors.centerIn: parent
+ font.capitalization: Font.AllUppercase
+
+ rotation: 270
+ }
+ }
+
+
+ }
+
+ Button
+ {
+ id: collageButton
+
+ Layout.alignment: Qt.AlignLeft
+ flat: true
+ implicitWidth: parent.width
+ implicitHeight: parent.height / 2
+
+ contentItem: Item {
+ anchors.fill: parent
+
+ Text {
+ text: qsTr("Collages")
+
+ color: "white"
+ font.family: "DejaVu Serif"
+ font.pixelSize: 50
+ anchors.centerIn: parent
+ font.capitalization: Font.AllUppercase
+
+ rotation: 270
+ }
+ }
+ }
+ }
+ }
+
+ FolderListModel {
+ id: folderModel
+ folder: applicationSettings.foldername
+ nameFilters: ["*.jpg", "*.JPG", "*.png", "*.PNG"]
+ showDirs: false
+ sortReversed: true //show newest photo first
+ }
+
+ DelegateModel {
+ id: visualModel
+ delegate: DelegateGalleryItem {
+ onPrintImage:
+ {
+ printerPopup.visible = true
+ printer.printImage(filename, 1)
+ printerPopup.visible = false
+ }
+ }
+ model: folderModel
+ }
+
+ GridView {
+ id: photosGridView
+
+ x: 0
+ y: 0
+ cellWidth: 320
+ cellHeight: 306
+ anchors.left: sidebar.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ model: visualModel.parts.grid
+ interactive: true
+ //displayMarginBeginning: 10000
+ //displayMarginEnd: 10000
+
+ //rightMargin: 100
+
+
+ /*Rectangle {
+ anchors.centerIn: parent
+ width: parent.width-10; height: parent.height-10
+ color: "transparent"
+ border.color: "red"
+ border.width: 5
+ }*/
+ ScrollBar.vertical: ScrollBar {
+ id: galleryScrollbar
+ contentItem.implicitWidth: 50
+ bottomPadding: 50
+ topPadding: 50
+ Button {
+ id: scrollBarUpButton
+ text: "\uE819" // icon-folder-open-empty
+ font.family: "fontello"
+ width: 50
+ height: 50
+ anchors.top: parent.top
+ font.pointSize: 30
+ }
+ Button {
+ id: scrollBarDownButton
+ text: "\uE81C" // icon-folder-open-empty
+ font.family: "fontello"
+ anchors.bottom: parent.bottom
+ width: 50
+ height: 50
+ font.pointSize: 30
+ }
+ }
+ }
+
+ ListView {
+ id: photosListView
+
+ width: root.width
+ height: root.height
+ orientation: Qt.Horizontal
+ model: visualModel.parts.list
+ interactive: false
+
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ snapMode: ListView.SnapOneItem
+
+ /*Rectangle {
+ anchors.centerIn: parent
+ width: parent.width-10; height: parent.height-10
+ color: "transparent"
+ border.color: "green"
+ border.width: 5
+ }*/
+ }
+
+ NavigationButton {
+ id: exitButton
+ y: 515
+ text: qsTr("Exit")
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 20
+ anchors.left: sidebar.right
+ anchors.leftMargin: 20
+ forward: false
+ }
+
+ PrinterPopup {
+ id: printerPopup
+ anchors.centerIn: parent
+ visible: false
+ isPrinting: true
+ }
+
+ state: 'inGrid'
+ states: [
+ State {
+ name: 'inGrid'
+ PropertyChanges {
+ target: photosGridView
+ interactive: true
+ visible: true
+ }
+ PropertyChanges {
+ target: photosListView
+ visible: false
+ }
+ },
+ State {
+ name: 'fullscreen'
+ extend: 'inGrid'
+ PropertyChanges {
+ target: photosGridView
+ interactive: false
+ visible: false
+ }
+ PropertyChanges {
+ target: photosListView
+ visible: true
+ }
+ }
+ ]
+
+ //MouseArea {
+ // anchors.fill: root
+ // z: root.state == 'inGrid' ? -1 : 0
+ // onClicked: {
+ // root.state = 'inGrid'
+ // }
+ //}
+ }
+
+ Item {
+ id: foreground
+ anchors.fill: parent
+ }
+}
+
+
+/*##^## Designer {
+ D{i:0;autoSize:true;height:480;width:640}
+}
+ ##^##*/
diff --git a/qml/MainMenu.qml b/qml/MainMenu.qml
index ed4a441..004f7f8 100644
--- a/qml/MainMenu.qml
+++ b/qml/MainMenu.qml
@@ -14,6 +14,7 @@ MainMenuForm {
property bool collageIsPrintable: true
state: "IconNotSelected"
signal collageSelected
+ signal galleryEnter
property real scrollPosition: 0.0
property real scrollDuration: 50000.0
@@ -39,6 +40,11 @@ MainMenuForm {
collageSelected()
}
+ galleryButton.onClicked:
+ {
+ galleryEnter()
+ }
+
backButton.onClicked:
{
state = "IconNotSelected"
@@ -86,7 +92,7 @@ MainMenuForm {
settingsButton.onClicked:
{
- if(applicationSettings.password.length == 0)
+ if(applicationSettings.password.length == 0 || applicationSettings.enableSettingsPassword == false)
{
settingsPopup.open()
}
diff --git a/qml/MainMenuForm.ui.qml b/qml/MainMenuForm.ui.qml
index 6082210..37465bc 100644
--- a/qml/MainMenuForm.ui.qml
+++ b/qml/MainMenuForm.ui.qml
@@ -15,6 +15,7 @@ Item {
property alias imageSlider: imageSlider
property alias collageSelector: collageSelector
property alias iconModel: collageSelector.iconModel
+ property alias galleryButton: galleryButton
CollageSelector {
id: collageSelector
@@ -173,6 +174,15 @@ Item {
anchors.rightMargin: 30
}
+ NavigationButton {
+ id: galleryButton
+ text: qsTr("Gallery")
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 30
+ }
+
NavigationButton {
id: backButton
text: qsTr("Back")
@@ -201,6 +211,11 @@ Item {
target: settingsButton
visible: true
}
+
+ PropertyChanges {
+ target: galleryButton
+ visible: true
+ }
},
State {
name: "IconSelected"
@@ -229,6 +244,11 @@ Item {
target: settingsButton
visible: false
}
+
+ PropertyChanges {
+ target: galleryButton
+ visible: false
+ }
}
]
}
diff --git a/qml/SettingsPopupForm.ui.qml b/qml/SettingsPopupForm.ui.qml
index 2022220..ad7d5fe 100644
--- a/qml/SettingsPopupForm.ui.qml
+++ b/qml/SettingsPopupForm.ui.qml
@@ -5,7 +5,7 @@ import QtQuick.Layouts 1.10
Popup {
id: popup
width: 400
- height: 500
+ height: 600
property alias switchHideSnapshotSettings: switchHideSnapshotSettings
property alias switchHideEffectPopup: switchHideEffectPopup
property alias switchMultiplePrints: switchMultiplePrints
@@ -19,11 +19,13 @@ Popup {
property alias buttonDeletePhotos: buttonDeletePhotos
property alias buttonClose: buttonClose
property alias switchPrinter: switchPrinter
+ property alias switchPrintFromGallery: switchPrintFromGallery
property alias buttonCopyPhotos: buttonCopyPhotos
property alias buttonSetTime: buttonSetTime
property alias switchMirrorCamera: switchMirrorCamera
property alias comboBoxPrinter: comboBoxPrinter
property alias comboBoxCamera: comboBoxCamera
+ property alias switchEnableSettingsPassword: switchEnableSettingsPassword
property alias versionText: labelVersionText.text
Button {
@@ -232,6 +234,22 @@ Popup {
text: qsTr("enabled")
}
}
+
+ Row {
+ id: printFromGallery
+ spacing: 5
+ Label {
+ id: labelPrintFromGallery
+ text: qsTr("Allow prints from Gallery")
+ anchors.verticalCenter: switchPrintFromGallery.verticalCenter
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ Switch {
+ id: switchPrintFromGallery
+ text: qsTr("enabled")
+ }
+ }
}
}
@@ -241,6 +259,23 @@ Popup {
Column {
spacing: 5
+ Row
+ {
+ spacing: 5
+
+ Label {
+ id: labelEnableSettingsPassword
+ text: qsTr("Enable Settings Password:")
+ anchors.verticalCenter: switchEnableSettingsPassword.verticalCenter
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ Switch {
+ id: switchEnableSettingsPassword
+ text: qsTr("enabled")
+ }
+ }
+
Row {
spacing: 5
diff --git a/qml/SnapshotMenu.qml b/qml/SnapshotMenu.qml
index 1cae643..8cf5bea 100644
--- a/qml/SnapshotMenu.qml
+++ b/qml/SnapshotMenu.qml
@@ -4,11 +4,25 @@ import GPIO 1.0
SnapshotMenuForm {
id: form
+ property bool snapshotTimeoutEnable : false
+
signal captured(string filename)
signal abort
countdown: snapshotSettings.countdown
+ Timer
+ {
+ id: snapshotTimeoutTimer
+ interval: 1000 * 60 * 10 //going inactive after 10 minutes
+ onTriggered:
+ {
+ console.log("Snapshot timeout return to main menu")
+ snapshotTimeoutTimer.stop()
+ abort()
+ }
+ }
+
cameraRenderer.onPhotoProcessingChanged:
{
console.log("photo processing: " + Boolean(cameraRenderer.photoProcessing).toString())
@@ -23,6 +37,19 @@ SnapshotMenuForm {
value: 0.0
}
+ onSnapshotTimeoutEnableChanged:
+ {
+ if(state == "activated" && snapshotTimeoutEnable == true)
+ {
+ snapshotTimeoutTimer.start()
+ console.log("Snapshot timeout timer started")
+ }
+ else
+ {
+ snapshotTimeoutTimer.stop()
+ }
+ }
+
onStateChanged:
{
console.log("Snapshot menu state changed: " + state)
@@ -32,6 +59,16 @@ SnapshotMenuForm {
}
else
{
+ if(state == "activated" && snapshotTimeoutEnable == true)
+ {
+ snapshotTimeoutTimer.start()
+ console.log("Snapshot timeout timer started")
+ }
+ else
+ {
+ snapshotTimeoutTimer.stop()
+ }
+
shutterButton.reset()
ledEnablePin.value = 1.0
}
diff --git a/qml/content/CollageRenderer.qml b/qml/content/CollageRenderer.qml
index d53bf4d..bf56f51 100644
--- a/qml/content/CollageRenderer.qml
+++ b/qml/content/CollageRenderer.qml
@@ -11,6 +11,7 @@ Item {
property int imagesLoading : 0
signal collageFull(bool full)
+ signal collageImagesChanged(int count)
Rectangle
{
@@ -57,10 +58,11 @@ Item {
y: imageRect.y * backgroundRect.height + (renderer.height - backgroundRect.height) / 2
width: imageRect.width * backgroundRect.width
height: imageRect.height * backgroundRect.height
+ transform: Rotation { origin.x: width/2; origin.y: height/2; axis { x: 0; y: 0; z: 1 } angle: imageRotation }
Component.onCompleted:
{
- console.log("Picture placed at: " + Number(x).toString() + " " + Number(y).toString())
+ console.log("Picture placed at: " + Number(x).toString() + " " + Number(y).toString() + " Rotation: " + Number(rotation).toString())
}
onImageSourceChanged:
@@ -132,6 +134,12 @@ Item {
collageFull(full)
console.log("Collage Full Changed to " + Boolean(full).toString());
}
+
+ onCountImagePathSetChanged:
+ {
+ collageImagesChanged(count)
+ console.log("Images in model set: " + Number(count).toString());
+ }
}
function saveImage(filename, size)
@@ -155,8 +163,18 @@ Item {
// TODO clip the image and bringing everything into right format...
renderer.grabToImage(function(result) {
- result.saveToFile(filename, Qt.size(backgroundRect.width, backgroundRect.height));
- savedFilename = filename;
+ if (result) {
+ console.log("Image grabbed with size " + result.image.width + "x" + result.image.height + " successfully");
+ var success = result.saveToFile(filename);
+ if (success) {
+ console.log("Image saved successfully to " + filename);
+ savedFilename = filename;
+ } else {
+ console.log("Failed to save image to " + filename);
+ }
+ } else {
+ console.log("Failed to grab image");
+ }
saving = false;
}, size);
}
diff --git a/qml/content/DelegateGalleryItem.qml b/qml/content/DelegateGalleryItem.qml
new file mode 100644
index 0000000..2036d31
--- /dev/null
+++ b/qml/content/DelegateGalleryItem.qml
@@ -0,0 +1,288 @@
+import QtQuick 2.5
+import QtQuick.Controls 2.0
+import QtQml 2.14
+import QtGraphicalEffects 1.0
+import QtQuick.Controls.Material 2.0
+import "../scripts/utils.js" as Script
+import "../styles" as Style
+
+Package {
+
+ signal printImage(string filename)
+
+ Item { Package.name: 'grid'
+ id: gridDelegate
+ width: root.width; height: root.height
+ }
+ Item { Package.name: 'list'
+ id: fullDelegate
+ width: root.width; height: root.height
+ }
+
+// ===================================================
+
+ Item {
+ width: 160; height: 153
+
+ Item {
+ id: photoWrapper
+
+ x: 0; y: 0
+ width: 280; height: 266
+
+ /*BorderImage {
+ anchors.fill: placeHolder
+ anchors {
+ leftMargin: -15
+ topMargin: -10
+ rightMargin: -15
+ bottomMargin: -15
+ }
+ source: '../../images/polaroid.svg.png'
+ border {
+ top: 25
+ left: 25
+ right: 25
+ bottom: 65
+ }
+ }*/
+
+ Rectangle {
+ id: placeHolder
+
+ property int w: 280
+ property int h: 180
+ property double s: Script.calculateScale(w, h, photoWrapper.width)
+
+ color: 'white'
+ anchors.centerIn: parent
+ antialiasing: true
+ width: w * s; height: h * s; z: -1
+ visible: originalImage.status != Image.Ready
+ Rectangle {
+ color: "#878787"
+ antialiasing: true
+ anchors {
+ fill: parent
+ topMargin: 3
+ bottomMargin: 3
+ leftMargin: 3
+ rightMargin: 3
+ }
+ }
+ }
+
+ BusyIndicator {
+ anchors.centerIn: parent
+ running: originalImage.status != Image.Ready
+ }
+ Image {
+ id: originalImage
+
+ sourceSize.width: 256 //save memory
+ sourceSize.height: 256
+
+ asynchronous: true
+ cache: true
+ anchors.fill: photoWrapper
+ antialiasing: true
+ source: foldermodel.folder + "/" + fileName
+
+ fillMode: Image.PreserveAspectFit
+ }
+ ProgressBar {
+ anchors.centerIn: parent
+ visible: hqImage.status == Image.Loading
+ value: hqImage.progress
+ //style: Style.RoundProgressBarStyle {}
+ }
+ Image {
+ id: hqImage
+
+ sourceSize.width: 1024
+ sourceSize.height: 1024
+
+ asynchronous: true
+ cache: false
+ anchors.fill: photoWrapper
+ antialiasing: true
+ source: ""
+ visible: false
+ fillMode: Image.PreserveAspectFit
+
+ onSourceChanged: {
+ console.log("hqImage source:", source)
+ }
+
+ Row {
+ id: printButtonRow
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 20
+
+ spacing: 10
+
+ visible: applicationSettings.printFromGallery && applicationSettings.printEnable
+
+ layer.enabled: true
+ layer.effect: Glow {
+ color: "black"
+ samples: 20
+ spread: 0.3
+ }
+
+ Text {
+ id: textLabel
+ color: "#ffffff"
+ text: galleryForm.printer ? (!galleryForm.printer.busy ? qsTr("Print") : qsTr("Printer busy")) : qsTr("Printer busy")
+ font.family: "DejaVu Serif"
+ wrapMode: Text.WrapAnywhere
+ font.pixelSize: 64
+ font.capitalization: Font.AllUppercase
+ }
+
+ ToolButton {
+ id: printButton
+ text: "\uE802" // icon-print
+ font.family: "fontello"
+ font.pixelSize: 64
+ enabled: galleryForm.printer ? !galleryForm.printer.busy : false
+
+ scale: hovered ? 1.1 : 1
+
+ layer.enabled: true
+ layer.effect: Glow {
+ color: "black"
+ samples: 20
+ spread: 0.3
+ }
+
+ onClicked:
+ {
+ console.log("Print image: " + hqImage.source)
+ printImage(hqImage.source)
+ root.state = 'inGrid'
+ galleryForm.exitGallery()
+ }
+ }
+ }
+
+ NavigationButton
+ {
+ id: closeButton
+
+ anchors.right: hqImage.right
+ anchors.top: hqImage.top
+ anchors.rightMargin: 20
+ anchors.topMargin: 20
+
+ text: qsTr("Overview")
+
+ onClicked:
+ {
+
+ root.state = 'inGrid'
+ }
+ }
+
+ BusyIndicator {
+ anchors.centerIn: parent
+ running: hqImage.status != Image.Ready
+ }
+
+ }
+
+ Binding {
+ target: root
+ property: "imageLoading"
+ value: (hqImage.status == Image.Loading) ? 1 : 0;
+ when: fullDelegate.ListView.isCurrentItem
+ restoreMode: Binding.RestoreBinding
+ }
+
+ MouseArea {
+ anchors.fill: photoWrapper
+ z: root.state == 'inGrid' ? 0 : -1
+ onClicked: {
+ gridDelegate.GridView.view.currentIndex = index;
+ if (root.state == 'inGrid') {
+ root.state = 'fullscreen'
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: 'inGrid'; when: root.state == 'inGrid' || root.state == ''
+ ParentChange {
+ target: photoWrapper
+ parent: gridDelegate;
+ x: 10; y: 0
+ }
+ PropertyChanges {
+ target: exitButton
+ visible: true
+ }
+ },
+ State {
+ name: 'fullscreen'; when: root.state == 'fullscreen'
+ ParentChange {
+ target: photoWrapper
+ parent: fullDelegate
+ x: 0; y: 0;
+ width: root.width; height: root.height
+ }
+ PropertyChanges {
+ target: hqImage
+ source: gridDelegate.GridView.isCurrentItem
+ ? foldermodel.folder + "/" + fileName
+ : ""
+ visible: true
+ }
+ PropertyChanges {
+ target: exitButton
+ visible: false
+ }
+ }
+ ]
+
+ onStateChanged: {
+ if(state == 'fullscreen' && gridDelegate.GridView.isCurrentItem)
+ console.log("State changed to 'fullscreen' for '"+fileName+"' record")
+ }
+
+ transitions: [
+ Transition {
+ from: 'inGrid'; to: 'fullscreen'
+ SequentialAnimation {
+ PauseAnimation {
+ duration: gridDelegate.GridView.isCurrentItem ? 0 : 600
+ }
+ ParentAnimation {
+ target: photoWrapper; via: foreground
+ NumberAnimation {
+ targets: photoWrapper
+ properties: 'x,y,width,height,opacity'
+ duration: gridDelegate.GridView.isCurrentItem ? 600 : 1
+ easing.type: Easing.OutQuart
+ }
+ }
+ }
+ },
+ Transition {
+ from: 'fullscreen'; to: 'inGrid'
+ ParentAnimation {
+ target: photoWrapper; via: foreground
+ NumberAnimation {
+ targets: photoWrapper
+ properties: 'x,y,width,height,opacity'
+ duration: gridDelegate.GridView.isCurrentItem ? 600 : 1
+ easing.type: Easing.OutQuart
+ }
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/qml/scripts/utils.js b/qml/scripts/utils.js
index 53685f5..28c2993 100644
--- a/qml/scripts/utils.js
+++ b/qml/scripts/utils.js
@@ -1,3 +1,17 @@
+.pragma library
+
+function calculateScale(width, height, cellSize) {
+ var widthScale = (cellSize * 1.0) / width
+ var heightScale = (cellSize * 1.0) / height
+ var scale = 0
+
+ if (widthScale <= heightScale) {
+ scale = widthScale;
+ } else if (heightScale < widthScale) {
+ scale = heightScale;
+ }
+ return scale;
+}
function shuffle(model){
var currentIndex = model.count, temporaryValue, randomIndex;
diff --git a/qml/styles/RoundProgressBarStyle.qml b/qml/styles/RoundProgressBarStyle.qml
new file mode 100644
index 0000000..a087c7f
--- /dev/null
+++ b/qml/styles/RoundProgressBarStyle.qml
@@ -0,0 +1,56 @@
+import QtQuick 2.5
+import QtQuick.Controls.Styles 1.4
+import QtGraphicalEffects 1.0
+
+ProgressBarStyle
+{
+ panel : Rectangle {
+ color: "transparent"
+ implicitWidth: 80
+ implicitHeight: implicitWidth
+
+ Rectangle
+ {
+ id: outerRing
+ z: 0
+ anchors.fill: parent
+ radius: Math.max(width, height) / 2
+ color: "transparent"
+ border.color: "gray"
+ border.width: 8
+ }
+
+ Rectangle
+ {
+ id: innerRing
+ z: 1
+ anchors.fill: parent
+ anchors.margins: (outerRing.border.width - border.width) / 2
+ radius: outerRing.radius
+ color: "transparent"
+ border.color: "darkgray"
+ border.width: 4
+
+ ConicalGradient
+ {
+ source: innerRing
+ anchors.fill: parent
+ gradient: Gradient
+ {
+ GradientStop { position: 0.00; color: "white" }
+ GradientStop { position: control.value; color: "white" }
+ GradientStop { position: control.value + 0.01; color: "transparent" }
+ GradientStop { position: 1.00; color: "transparent" }
+ }
+ }
+ }
+
+ Text
+ {
+ id: progressLabel
+ anchors.centerIn: parent
+ color: "gray"
+ text: (control.value * 100).toFixed() + "%"
+ }
+ }
+}
diff --git a/src/abstractprinter.h b/src/abstractprinter.h
index 85e7b75..a71cf48 100644
--- a/src/abstractprinter.h
+++ b/src/abstractprinter.h
@@ -18,7 +18,6 @@ class AbstractPrinter : public QObject
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
public:
explicit AbstractPrinter(QObject *parent = nullptr) : QObject(parent) {};
- Q_INVOKABLE virtual QSize getPrintSize() = 0;
Q_INVOKABLE virtual bool printerOnline() = 0;
virtual bool busy() = 0;
signals:
diff --git a/src/call_once.h b/src/call_once.h
index d882c48..9be2c48 100644
--- a/src/call_once.h
+++ b/src/call_once.h
@@ -9,13 +9,13 @@
#include
namespace CallOnce {
- enum ECallOnce {
- CO_Request,
- CO_InProgress,
- CO_Finished
- };
+enum ECallOnce {
+ CO_Request,
+ CO_InProgress,
+ CO_Finished
+};
- Q_GLOBAL_STATIC(QThreadStorage, once_flag)
+Q_GLOBAL_STATIC(QThreadStorage, once_flag)
}
template
@@ -32,7 +32,7 @@ inline static void qCallOnce(Function func, QBasicAtomicInt& flag)
if (protectFlag == CO_Finished)
return;
if (protectFlag == CO_Request && flag.testAndSetRelaxed(protectFlag,
- CO_InProgress)) {
+ CO_InProgress)) {
func();
flag.fetchAndStoreRelease(CO_Finished);
}
diff --git a/src/collageiconmodel.cpp b/src/collageiconmodel.cpp
index dd6c7df..2f670ce 100644
--- a/src/collageiconmodel.cpp
+++ b/src/collageiconmodel.cpp
@@ -138,11 +138,11 @@ void CollageIconModel::clear()
QString CollageIconModel::getIconName(int index)
{
- if (index < 0 || index >= mIcons.count())
- return QString();
+ if (index < 0 || index >= mIcons.count())
+ return QString();
- const CollageIcon &icon = mIcons[index];
- return icon.name();
+ const CollageIcon &icon = mIcons[index];
+ return icon.name();
}
bool CollageIconModel::showPrintable() const
diff --git a/src/collageiconmodel.h b/src/collageiconmodel.h
index acfd534..ae8a982 100644
--- a/src/collageiconmodel.h
+++ b/src/collageiconmodel.h
@@ -30,9 +30,9 @@ class CollageIconModel : public QAbstractListModel
Q_PROPERTY(bool showPrintable READ showPrintable WRITE setShowPrintable NOTIFY showPrintableChanged)
public:
enum IconRoles {
- NameRole = Qt::UserRole + 1,
- IconRole,
- PrintableRole
+ NameRole = Qt::UserRole + 1,
+ IconRole,
+ PrintableRole
};
CollageIconModel(QObject *parent = 0);
diff --git a/src/collageimagemodel.cpp b/src/collageimagemodel.cpp
index 7085dce..e473e78 100644
--- a/src/collageimagemodel.cpp
+++ b/src/collageimagemodel.cpp
@@ -1,5 +1,7 @@
#include "collageimagemodel.h"
#include "collagemodelfactory.h"
+#include
+#include
CollageImageModel::CollageImageModel(QObject *parent) : QAbstractListModel(parent)
{
@@ -37,6 +39,12 @@ bool CollageImageModel::parseXml(const QDomNode& node)
mLine = element.lineNumber();
return false;
}
+ else
+ {
+ mErrorMsg = "at least one background nodes required";
+ mLine = element.lineNumber();
+ return false;
+ }
QDomNodeList foregroundNode = element.elementsByTagName("foreground");
if(foregroundNode.count() == 1)
@@ -50,6 +58,44 @@ bool CollageImageModel::parseXml(const QDomNode& node)
return false;
}
+ QDomElement sizeElement = element.firstChildElement("size");
+ if(sizeElement.isElement())
+ {
+ if(sizeElement.hasAttributes() && sizeElement.toElement().hasAttribute("width") && sizeElement.toElement().hasAttribute("height"))
+ {
+ bool ok;
+ QString x = sizeElement.toElement().attribute("width");
+ mPixelSize.setWidth(x.toInt(&ok));
+ if(!ok)
+ {
+ mErrorMsg = "size 'width' must be defined as float";
+ mLine = sizeElement.lineNumber();
+ return false;
+ }
+
+ QString y = sizeElement.toElement().attribute("height");
+ mPixelSize.setHeight(y.toInt(&ok));
+ if(!ok)
+ {
+ mErrorMsg = "size 'height' must be defined as float";
+ mLine = sizeElement.lineNumber();
+ return false;
+ }
+ }
+ else
+ {
+ mErrorMsg = "size must be defined be 'width' and 'height' attributes";
+ mLine = sizeElement.lineNumber();
+ return false;
+ }
+ }
+ else
+ {
+ mErrorMsg = "at least one size nodes required";
+ mLine = element.lineNumber();
+ return false;
+ }
+
QDomNodeList imagesNode = element.elementsByTagName("images");
if(imagesNode.length() != 1)
{
@@ -72,7 +118,7 @@ bool CollageImageModel::parseXml(const QDomNode& node)
for(int i = 0; i < imageNodes.length(); i++)
{
bool result;
- CollageImage* image = new CollageImage();
+ CollageImage* image = new CollageImage(mPixelSize);
result = image->parseXml(imageNodes.item(i));
if(!result)
{
@@ -119,7 +165,7 @@ QHash CollageImageModel::roleNames() const
{
QHash roles;
roles[ImageRectRole] = "imageRect";
- roles[RotationRole] = "rotation";
+ roles[RotationRole] = "imageRotation";
roles[ImagePathRole] = "imagePath";
roles[BorderImageRole] = "borderImage";
roles[BorderRectRole] = "borderRect";
@@ -158,6 +204,7 @@ bool CollageImageModel::addImagePath(QUrl source, QString effect)
}
QModelIndex ii = index(i,0);
emit dataChanged(ii, ii);
+ emit countImagePathSetChanged(countImagePathSet());
if(collageFull())
{
emit collageFullChanged(true);
@@ -177,6 +224,7 @@ void CollageImageModel::clearImagePathes()
}
emit collageFullChanged(false);
+ emit countImagePathSetChanged(0);
emit dataChanged(this->index(0,0),this->index(rowCount()-1,0));
}
@@ -212,6 +260,7 @@ bool CollageImageModel::clearImagePath(int index)
}
#endif
emit dataChanged(this->index(0,0),this->index(rowCount()-1,0));
+ emit countImagePathSetChanged(countImagePathSet());
return true;
}
else {
@@ -231,6 +280,11 @@ bool CollageImageModel::collageFull()
return false;
}
+QSize CollageImageModel::collagePixelSize() const
+{
+ return mPixelSize;
+}
+
bool CollageImageModel::nextImageIsEffectSelectable()
{
if(!collageFull())
@@ -274,7 +328,7 @@ int CollageImageModel::countImagePathSet() const
return currentCount;
}
-CollageImage::CollageImage(QObject *parent) : QObject(parent), mEffect("")
+CollageImage::CollageImage(QSize collagePixelSize, QObject *parent) : QObject(parent), mEffect(""), mCollagePixelSize(collagePixelSize)
{
}
@@ -370,6 +424,25 @@ bool CollageImage::parseXml(const QDomNode &node)
return false;
}
+ QDomNodeList rotationNode = element.elementsByTagName("rotation");
+ if(rotationNode.count() == 1)
+ {
+ bool ok;
+ mAngle = rotationNode.item(0).toElement().text().toFloat(&ok);
+ if(!ok)
+ {
+ mErrorMsg = "rotation must be defined as float";
+ mLine = rotationNode.item(0).lineNumber();
+ return false;
+ }
+ }
+ else if(rotationNode.count() > 1)
+ {
+ mErrorMsg = "multiple rotations are defined";
+ mLine = element.lineNumber();
+ return false;
+ }
+
QDomNodeList borderImageNode = element.elementsByTagName("border");
if(borderImageNode.count() == 1)
{
@@ -389,10 +462,10 @@ bool CollageImage::parseXml(const QDomNode &node)
if(borderMarginNode.count() == 1)
{
if(borderMarginNode.item(0).hasAttributes() &&
- borderMarginNode.item(0).toElement().hasAttribute("top") &&
- borderMarginNode.item(0).toElement().hasAttribute("left") &&
- borderMarginNode.item(0).toElement().hasAttribute("right") &&
- borderMarginNode.item(0).toElement().hasAttribute("bottom"))
+ borderMarginNode.item(0).toElement().hasAttribute("top") &&
+ borderMarginNode.item(0).toElement().hasAttribute("left") &&
+ borderMarginNode.item(0).toElement().hasAttribute("right") &&
+ borderMarginNode.item(0).toElement().hasAttribute("bottom"))
{
bool ok;
QString top = borderMarginNode.item(0).toElement().attribute("top");
@@ -540,25 +613,38 @@ bool CollageImage::validateBoundary()
{
//test position and size parameter
bool result = true;
- if(mImageRect.x() < 0 || mImageRect.x() > 1.0)
+
+ // scale image rect to pixels
+ QRectF imageRect(mImageRect.x()*mCollagePixelSize.width(), mImageRect.y()*mCollagePixelSize.height(), mImageRect.width()*mCollagePixelSize.width(), mImageRect.height()*mCollagePixelSize.height());
+ // get center of rect
+ QPointF center = imageRect.center();
+ // rotate around center
+ QTransform transform;
+ transform.translate(center.x(), center.y());
+ transform.rotate(mAngle);
+ transform.translate(-center.x(), -center.y());
+ imageRect = transform.mapRect(imageRect);
+ qDebug() << "Bounding box of image: " << imageRect;
+
+ // now check if image will fit into collage
+ if(imageRect.x() < -std::numeric_limits::epsilon()|| imageRect.x() > mCollagePixelSize.width())
{
result = false;
}
- if(mImageRect.y() < 0 || mImageRect.x() > 1.0)
+ if(imageRect.y() < -std::numeric_limits::epsilon() || imageRect.y() > mCollagePixelSize.height())
{
result = false;
}
- if((mImageRect.x() + mImageRect.width()) > 1.0 || mImageRect.width() < 0)
+ if((imageRect.x() + imageRect.width()) > (mCollagePixelSize.width() + std::numeric_limits::epsilon() )|| imageRect.width() < 0)
{
result = false;
}
- if((mImageRect.y() + mImageRect.height()) > 1.0 || mImageRect.height() < 0)
+ if((imageRect.y() + imageRect.height()) > (mCollagePixelSize.height() + std::numeric_limits::epsilon()) || imageRect.height() < 0)
{
result = false;
}
- //TODO: Validate Border
- //TODO: Validate with rotation
+ //@TODO: Validate Border
return result;
}
diff --git a/src/collageimagemodel.h b/src/collageimagemodel.h
index c038818..633355f 100644
--- a/src/collageimagemodel.h
+++ b/src/collageimagemodel.h
@@ -21,7 +21,7 @@ class CollageImage : public QObject, public ModelParser
Q_PROPERTY(QString effectPreset READ effectPreset CONSTANT)
Q_PROPERTY(QString effect READ effect NOTIFY effectChanged)
public:
- CollageImage(QObject* parent = nullptr);
+ CollageImage(QSize collagePixelSize, QObject* parent = nullptr);
bool parseXml(const QDomNode& node) override;
QUrl imagePath() const;
QRectF imageRect() const;
@@ -47,15 +47,17 @@ class CollageImage : public QObject, public ModelParser
bool mEffectSelectable = true;
QString mEffectPreset = "";
QString mEffect = "";
+ const QSize mCollagePixelSize;
};
class CollageImageModel : public QAbstractListModel, public ModelParser
{
Q_OBJECT
- Q_PROPERTY(QUrl backgroundImage READ backgroundImage NOTIFY backgroundImageChanged)
- Q_PROPERTY(QUrl foregroundImage READ foregroundImage NOTIFY foregroundImageChanged)
- Q_PROPERTY(int countImagePathSet READ countImagePathSet NOTIFY countImagePatchSetChanged)
+ Q_PROPERTY(QUrl backgroundImage READ backgroundImage)
+ Q_PROPERTY(QUrl foregroundImage READ foregroundImage)
+ Q_PROPERTY(int countImagePathSet READ countImagePathSet NOTIFY countImagePathSet)
Q_PROPERTY(bool collageFull READ collageFull NOTIFY collageFullChanged)
+ Q_PROPERTY(QSize collagePixelSize READ collagePixelSize NOTIFY collagePixelSizeChanged)
public:
enum ImageRoles {
ImagePathRole = Qt::UserRole + 1,
@@ -81,16 +83,17 @@ class CollageImageModel : public QAbstractListModel, public ModelParser
Q_INVOKABLE bool collageFull();
Q_INVOKABLE bool nextImageIsEffectSelectable();
Q_INVOKABLE QString nextImageEffectPreset();
+ Q_INVOKABLE QSize collagePixelSize() const;
int countImagePathSet() const;
signals:
- void backgroundImageChanged(const QUrl &image);
- void foregroundImageChanged(const QUrl &image);
- void countImagePatchSetChanged(const int &count);
void collageFullChanged(bool full);
+ void countImagePathSetChanged(int count);
+ void collagePixelSizeChanged(QSize size);
protected:
QList mImages;
QUrl mBackgroundImage;
QUrl mForegroundImage;
+ QSize mPixelSize;
};
#endif // COLLAGEIMAGEMODEL_H
diff --git a/src/collagemodelfactory.cpp b/src/collagemodelfactory.cpp
index a2eea51..5fab7d8 100644
--- a/src/collagemodelfactory.cpp
+++ b/src/collagemodelfactory.cpp
@@ -99,6 +99,7 @@ void CollageModelFactory::loadModels()
{
clearModels();
mStatus = Error;
+ qCritical("%s", QString("Parser Error: " + errorLineMsg()).toStdString().c_str());
errorMsgChanged(errorLineMsg());
statusChanged(mStatus);
}else
@@ -125,9 +126,9 @@ bool CollageModelFactory::parseXml(const QDomNode &node)
if(rootElement.tagName() != "catalog")
{
- mErrorMsg = "Excepted 'catalog' root node";
- mLine = rootElement.lineNumber();
- return false;
+ mErrorMsg = "Excepted 'catalog' root node";
+ mLine = rootElement.lineNumber();
+ return false;
}
if(!rootElement.hasAttribute("version") || rootElement.attribute("version") != "1.0")
diff --git a/src/fakeprinter.cpp b/src/fakeprinter.cpp
index 58bf1d8..195646f 100644
--- a/src/fakeprinter.cpp
+++ b/src/fakeprinter.cpp
@@ -1,16 +1,13 @@
#include "fakeprinter.h"
#include
+#include
+#include
FakePrinter::FakePrinter(QObject *parent) : AbstractPrinter(parent)
{
QObject::connect(&mBusyTimer, SIGNAL(timeout()), this, SLOT(busyTimeout()));
};
-QSize FakePrinter::getPrintSize()
-{
- return QSize(3570,2380); //hard coded pixel size
-}
-
bool FakePrinter::printerOnline()
{
return true;
@@ -24,6 +21,11 @@ bool FakePrinter::busy()
int FakePrinter::printImage(const QString &filename, int copyCount)
{
qDebug() << "Fake printer starts printing " << copyCount << " copies." << filename;
+ QTime dieTime= QTime::currentTime().addSecs(1);
+ while (QTime::currentTime() < dieTime)
+ {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
+ }
mBusyTimer.start(1000 * 30); // 30 seconds;
emit busyChanged(true);
return 0;
diff --git a/src/fakeprinter.h b/src/fakeprinter.h
index 029b5ad..5e2d179 100644
--- a/src/fakeprinter.h
+++ b/src/fakeprinter.h
@@ -10,7 +10,6 @@ class FakePrinter : public AbstractPrinter, public PrinterList
Q_OBJECT
Q_INTERFACES(AbstractPrinter)
public:
- QSize getPrintSize() override;
bool printerOnline() override;
bool busy() override;
int printImage(const QString &filename, int copyCount) override;
diff --git a/src/fileio.cpp b/src/fileio.cpp
index 6a45be5..533a2fb 100644
--- a/src/fileio.cpp
+++ b/src/fileio.cpp
@@ -13,7 +13,7 @@ QByteArray FileIO::read()
}
else
{
- file.setFileName(mSource.toLocalFile());
+ file.setFileName(mSource.toLocalFile());
}
if (!file.open(QIODevice::ReadOnly))
diff --git a/src/filesystem.cpp b/src/filesystem.cpp
index 2a8c096..00d7b05 100644
--- a/src/filesystem.cpp
+++ b/src/filesystem.cpp
@@ -140,7 +140,7 @@ void FileSystem::startCopyFilesToRemovableDrive()
int progress = (100 * i + 1) / files.count();
qDebug() << "Copy file: " << imagePath + "/" + files[i] << " to: " << removableDrivePath + "/" + files[i] << " Progress: " << progress;
if(QFile::exists(removableDrivePath + "/" + files[i]))
- QFile::remove(removableDrivePath + "/" + files[i]);
+ QFile::remove(removableDrivePath + "/" + files[i]);
if(!QFile::copy(imagePath + "/" + files[i], removableDrivePath + "/" + files[i]))
{
diff --git a/src/main.cpp b/src/main.cpp
index 81e8228..dd55f16 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -15,6 +15,79 @@
#include "fileio.h"
#include "filesystem.h"
#include "system.h"
+#include
+
+//some constants to parameterize.
+const qint64 LOG_FILE_LIMIT = 3000000;
+const QString LOG_PATH = "/logs/";
+const QString LOG_FILENAME = "qtbooth.log";
+
+//thread safety
+QMutex mutex;
+
+void redirectDebugMessages(QtMsgType type, const QMessageLogContext & context, const QString & str)
+{
+ //thread safety
+ mutex.lock();
+ QString txt;
+
+ //prepend timestamp to every message
+ QString datetime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss");
+ //prepend a log level label to every message
+ switch (type) {
+ case QtDebugMsg:
+ txt = QString("[Debug*] ");
+ break;
+ case QtWarningMsg:
+ txt = QString("[Warning] ");
+ break;
+ case QtInfoMsg:
+ txt = QString("[Info] ");
+ break;
+ case QtCriticalMsg:
+ txt = QString("[Critical] ");
+ break;
+ case QtFatalMsg:
+ txt = QString("[Fatal] ");
+ }
+
+ QDir dir;
+
+ QString filePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + LOG_PATH;
+
+ if (!dir.exists(filePath))
+ dir.mkpath(filePath); // You can check the success if needed
+
+ filePath = filePath + LOG_FILENAME;
+
+ QFile outFile(filePath);
+
+ //if file reached the limit, rotate to filename.1
+ if(outFile.size() > LOG_FILE_LIMIT){
+ //roll the log file.
+ QFile::remove(filePath + ".1");
+ QFile::rename(filePath, filePath + ".1");
+ QFile::resize(filePath, 0);
+ }
+
+ //write message
+ outFile.open(QIODevice::WriteOnly | QIODevice::Append);
+ QTextStream ts(&outFile);
+ ts << datetime << txt << context.file << str << endl;
+
+ if(context.file != nullptr && context.line != 0)
+ {
+ std::cout << datetime.toStdString() << " - " << txt.toStdString() << " - " << context.file << "(" << context.line << ") - " << str.toStdString() << std::endl;
+ }
+ else
+ {
+ std::cout << datetime.toStdString() << " - " << txt.toStdString() << " - " << str.toStdString() << std::endl;
+ }
+
+ //close fd
+ outFile.close();
+ mutex.unlock();
+}
int main(int argc, char *argv[])
{
@@ -27,6 +100,8 @@ int main(int argc, char *argv[])
QGuiApplication::setOrganizationDomain("github.com");
QGuiApplication::setApplicationName("qtbooth");
+ qInstallMessageHandler(redirectDebugMessages);
+
QFontDatabase fontDatabase;
if (fontDatabase.addApplicationFont(":/font/fontello/fontello.ttf") == -1)
qWarning() << "Failed to load fontello.ttf";
diff --git a/src/noprinter.cpp b/src/noprinter.cpp
index 0253ffc..3378027 100644
--- a/src/noprinter.cpp
+++ b/src/noprinter.cpp
@@ -1,10 +1,5 @@
#include "noprinter.h"
-QSize NoPrinter::getPrintSize()
-{
- return QSize(3570,2380); //hard coded pixel size
-}
-
bool NoPrinter::printerOnline()
{
return false;
diff --git a/src/noprinter.h b/src/noprinter.h
index 0cfd6c5..bf9cb74 100644
--- a/src/noprinter.h
+++ b/src/noprinter.h
@@ -9,7 +9,6 @@ class NoPrinter : public AbstractPrinter, public PrinterList
Q_OBJECT
Q_INTERFACES(AbstractPrinter)
public:
- QSize getPrintSize() override;
bool printerOnline() override;
bool busy() override;
int printImage(const QString &filename, int copyCount) override;
diff --git a/src/selphyprinter.cpp b/src/selphyprinter.cpp
index dca7253..458dd7d 100644
--- a/src/selphyprinter.cpp
+++ b/src/selphyprinter.cpp
@@ -41,17 +41,21 @@ bool SelphyPrinter::printerOnline()
}
}
-
-QSize SelphyPrinter::getPrintSize()
-{
- return QSize(3570,2380); //hard coded pixel size
-}
-
int SelphyPrinter::printImage(const QString &filename, int copyCount)
{
if(mIp.length() > 0)
{
- QString imageMagickCommand = "convert " + filename + " -quality 100% " + filename + ".jpg";
+ QString imageMagickCommand;
+ if(filename.endsWith(".jpg") || filename.endsWith(".jpg"))
+ {
+ imageMagickCommand = ":"; // file is already a JPG. No conversion to be done
+ }
+ else
+ {
+ // file is not a JPG. First convert to JPG.
+ imageMagickCommand = "convert " + filename + " -quality 100% " + filename + ".jpg && rm " + filename;
+ }
+
QString selphyCommand = "selphy -printer_ip=" + mIp + " " + filename + ".jpg";
QString printCommand = imageMagickCommand;
for(int i = 0; i < copyCount; i++)
@@ -68,7 +72,7 @@ int SelphyPrinter::printImage(const QString &filename, int copyCount)
{
emit busyChanged(true);
mPrinterProcess.start("sh", shParameters);
- qDebug() << shParameters;
+ qDebug() << "Runnings sh with parameters: " << shParameters;
return 0;
}
else
diff --git a/src/selphyprinter.h b/src/selphyprinter.h
index cb13f45..8a400a0 100644
--- a/src/selphyprinter.h
+++ b/src/selphyprinter.h
@@ -10,7 +10,6 @@ class SelphyPrinter : public AbstractPrinter, public PrinterList
Q_OBJECT
Q_INTERFACES(AbstractPrinter)
public:
- Q_INVOKABLE QSize getPrintSize();
Q_INVOKABLE bool printerOnline();
bool busy();
public slots:
diff --git a/src/standardprinter.cpp b/src/standardprinter.cpp
index 4411792..3143e48 100644
--- a/src/standardprinter.cpp
+++ b/src/standardprinter.cpp
@@ -3,11 +3,6 @@
#include
#include
-QSize StandardPrinter::getPrintSize()
-{
- return QSize(3570,2380); //hard coded pixel size @TODO
-}
-
bool StandardPrinter::printerOnline()
{
return true; //cannot determine online state @TODO
@@ -68,11 +63,11 @@ StandardPrinter *StandardPrinter::createInternal(const QString &name)
auto printers = QPrinterInfo::availablePrinters();
for(auto printer: printers)
{
- if(printer.printerName() == name)
- {
+ if(printer.printerName() == name)
+ {
ptr = new StandardPrinter(printer);
break;
- }
+ }
}
return ptr;
}
diff --git a/src/standardprinter.h b/src/standardprinter.h
index 0fd0c1e..a1ae9a9 100644
--- a/src/standardprinter.h
+++ b/src/standardprinter.h
@@ -11,7 +11,6 @@ class StandardPrinter : public AbstractPrinter, public PrinterList
Application
-
+
QML Photo Booth
QML Photo Booth
@@ -12,17 +12,22 @@
CollageMenuForm.ui
-
+
Print
Drucken
-
+
+ Save
+ Speichern
+
+
+
Next Photo
Nächstes Foto
-
+
Exit
Zurück
@@ -35,6 +40,24 @@
Lächeln
+
+ DelegateGalleryItem
+
+
+ Print
+ Drucken
+
+
+
+ Printer busy
+ Drucker beschâftigt
+
+
+
+ Overview
+ Übersicht
+
+
EffectList
@@ -98,6 +121,24 @@
Gelbfilter
+
+ GalleryMenuForm.ui
+
+
+ Photos
+ Fotos
+
+
+
+ Collages
+ Collagen
+
+
+
+ Exit
+ Zurück
+
+
ImagePreviewForm.ui
@@ -114,12 +155,17 @@
MainMenuForm.ui
-
+
Continue
Weiter
-
+
+ Gallery
+ Gallerie
+
+
+
Back
Zurück
@@ -159,8 +205,8 @@
SettingsPopup
-
-
+
+
Time:
Zeit:
@@ -168,143 +214,160 @@
SettingsPopupForm.ui
-
+
Close
Schließen
-
+
Settings
Einstellungen
-
+
Photos
Fotos
-
+
Camera
Kamera
-
+
Printer
Drucker
-
+
System
System
-
+
Copy photos to removable disk
Kopiere Fotos auf USB Stick
-
+
Delete all photos
Alls Fotos löschen
-
+
+ Camera:
+ Kamera:
+
+
+
Mirror Camera
Kamera spiegeln
-
+
mirror
spiegeln
-
+
Snapshot Settings
Schnappschusseinstellungen
-
+
hide
verstecken
-
+
Effect Popup
Effekte Popuo
-
+
disable
deaktivieren
-
+
Enable Printing
Druck aktivieren
-
-
+
+
+
+
enabled
aktiviert
-
+
Printer:
Drucker:
-
+
Allow multiple prints
Erlaube mehrere Ausdrucke
-
+
+ Allow prints from Gallery
+ Erlaube Drucken aus Gallery
+
+
+
+ Enable Settings Password:
+ Aktiviere Einstellungspasswort:
+
+
+
Current time
Eingestellte Zeit
-
+
Set time
Setze Zeit
-
+
Language:
Sprache:
-
+
Window Mode:
Fenster Modus:
-
+
Window
Fenster
-
+
Fullscreen
Vollbildschirm
-
+
Copy layout templates from removable disk
Kopiere Vorlage von USB Stick
-
+
Shutdown
Herunterfahren
-
+
Restart
Neustart
-
+
Exit Photobooth
Photobooth schließen