Skip to content

Commit b5cdf4b

Browse files
authored
Merge pull request #214 from saeugetier/feature/207-selectable-photo-location
Feature/207 selectable photo location
2 parents a48d0b2 + c75969d commit b5cdf4b

8 files changed

Lines changed: 327 additions & 2 deletions

io.github.saeugetier.photobooth.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"--share=network",
1010
"--device=all",
1111
"--filesystem=home",
12+
"--filesystem=host:removable",
1213
"--socket=fallback-x11",
1314
"--socket=wayland"
1415
],
@@ -159,4 +160,4 @@
159160
]
160161
}
161162
]
162-
}
163+
}

qml.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,6 @@
9494
<file>shaders/previewshader.frag.qsb</file>
9595
<file>models/coco.names</file>
9696
<file>images/backgrounds/Stripes.png</file>
97+
<file>qml/content/CustomFolderDialog.qml</file>
9798
</qresource>
9899
</RCC>

qml/Application.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ ApplicationWindow {
167167
{
168168
id: applicationSettings
169169
category: "Application"
170-
property url foldername: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
170+
property url foldername: StandardPaths.writableLocation(StandardPaths.PicturesLocation) + "/photobooth"
171171
property bool printEnable: true
172172
property string password: "0815"
173173
property string language: "en"

qml/SettingsMenu.qml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import QtQuick
22
import QtMultimedia
33
import QtQuick.Controls
4+
import QtQuick.Dialogs
5+
import Qt.labs.platform
6+
import QtQml
7+
import "content"
48

59
SettingsMenuForm {
610
id: form
@@ -74,6 +78,50 @@ SettingsMenuForm {
7478
console.log("index: " + Number(index).toString())
7579
}
7680

81+
function delay(delayTime, cb) {
82+
timer = new Timer();
83+
timer.interval = delayTime;
84+
timer.repeat = false;
85+
timer.triggered.connect(cb);
86+
timer.start();
87+
}
88+
89+
CustomFolderDialog {
90+
id: pictureFolderDialog
91+
title: qsTr("Select Pictures Folder")
92+
anchors.centerIn: parent
93+
width: parent.width - 100
94+
height: parent.height - 100
95+
96+
Timer
97+
{
98+
id: folderCheckTimer
99+
interval: 1000
100+
running: false
101+
repeat: false
102+
onTriggered: function() {
103+
filesystem.checkImageFolders()
104+
console.log("Checked folder: " + applicationSettings.foldername)
105+
}
106+
}
107+
108+
onAccepted: function()
109+
{
110+
console.log("Selected folder: " + pictureFolderDialog.currentFolder)
111+
applicationSettings.foldername = pictureFolderDialog.currentFolder
112+
applicationSettings.sync()
113+
114+
folderCheckTimer.start()
115+
}
116+
}
117+
118+
buttonSelectPhotoDirectory.onClicked:
119+
{
120+
pictureFolderDialog.currentFolder = applicationSettings.foldername
121+
console.log("selecting pictures folder: " + pictureFolderDialog.currentFolder)
122+
pictureFolderDialog.open()
123+
}
124+
77125
buttonClose.onClicked:
78126
{
79127
exitSettings()

qml/SettingsMenuForm.ui.qml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Item {
2828
property alias versionText: labelVersionText.text
2929
property alias comboBoxCameraOrientation: comboBoxCameraOrientation
3030
property alias comboBoxNeuralNetworkRuntime: comboBoxNeuralNetworkRuntime
31+
property alias buttonSelectPhotoDirectory: buttonSelectPhotoDirectory
3132

3233
ColumnLayout {
3334
anchors.fill: parent
@@ -92,6 +93,25 @@ Item {
9293
anchors.topMargin: 20
9394
spacing: 20
9495

96+
RowLayout {
97+
spacing: 10
98+
Label {
99+
text: qsTr("Photo Directory: ")
100+
}
101+
Label {
102+
id: labelPhotoDirectory
103+
Layout.fillWidth: true
104+
text: applicationSettings.foldername
105+
}
106+
Item {
107+
Layout.fillWidth: true
108+
}
109+
Button {
110+
id: buttonSelectPhotoDirectory
111+
text: qsTr("Browse")
112+
}
113+
}
114+
95115
Button {
96116
id: buttonCopyPhotos
97117
text: qsTr("Copy photos to removable disk")

qml/content/CustomFolderDialog.qml

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// CustomFolderDialog.qml
2+
import QtQuick 6.5
3+
import QtQuick.Controls 6.5
4+
import QtQuick.Layouts 6.5
5+
import Qt.labs.folderlistmodel 2.2
6+
import QtQuick.VirtualKeyboard 6.5
7+
import QtCore
8+
9+
Dialog {
10+
id: root
11+
modal: true
12+
width: 800
13+
height: 600
14+
standardButtons: Dialog.NoButton
15+
16+
property url currentFolder: StandardPaths.writableLocation(StandardPaths.PicturesLocation)
17+
18+
signal canceled()
19+
20+
property bool createMode: false
21+
22+
Rectangle {
23+
anchors.fill: parent
24+
color: Material.background
25+
border.color: Material.foreground
26+
radius: 8
27+
28+
ColumnLayout {
29+
anchors.fill: parent
30+
spacing: 10
31+
32+
Text {
33+
text: qsTr("Select Folder")
34+
font.pixelSize: 20
35+
Layout.alignment: Qt.AlignHCenter
36+
}
37+
38+
RowLayout {
39+
id: breadcrumbBar
40+
Layout.fillWidth: true
41+
spacing: 4
42+
43+
// Root Button "/"
44+
Button {
45+
text: "/"
46+
font.pixelSize: 14
47+
onClicked: {
48+
root.currentFolder = "file:///"
49+
folderModel.folder = root.currentFolder
50+
}
51+
}
52+
53+
Repeater {
54+
model:{
55+
var path = root.currentFolder.toString().replace("file://", "")
56+
var segments = path.split("/").filter(s => s.length > 0)
57+
return segments
58+
}
59+
60+
delegate: RowLayout {
61+
spacing: 2
62+
63+
Button {
64+
text: modelData === "/" ? "/" : modelData
65+
font.pixelSize: 14
66+
onClicked: {
67+
let segments = root.currentFolder.toString().replace("file://", "").split("/").filter(s => s.length > 0)
68+
let newPath = "/" + segments.slice(0, index + 1).join("/")
69+
root.currentFolder = "file://" + newPath
70+
folderModel.folder = root.currentFolder
71+
72+
}
73+
}
74+
75+
Text {
76+
text: index < breadcrumbBarRepeater.count - 1 ? " / " : ""
77+
font.pixelSize: 14
78+
color: Material.foreground
79+
}
80+
}
81+
82+
id: breadcrumbBarRepeater
83+
}
84+
85+
Item {
86+
Layout.fillWidth: true
87+
}
88+
89+
Button {
90+
text: createMode ? qsTr("Cancel") : qsTr("New Folder")
91+
onClicked: {
92+
createMode = !createMode
93+
if (!createMode)
94+
newFolderNameField.text = ""
95+
}
96+
}
97+
}
98+
99+
RowLayout {
100+
ToolSeparator {
101+
Layout.fillWidth: true
102+
orientation: Qt.Horizontal
103+
}
104+
}
105+
106+
// Inline New Folder Creation
107+
RowLayout {
108+
visible: createMode
109+
Layout.fillWidth: true
110+
spacing: 10
111+
112+
TextField {
113+
id: newFolderNameField
114+
placeholderText: "New folder name"
115+
Layout.fillWidth: true
116+
inputMethodHints: Qt.ImhNoPredictiveText
117+
focus: createMode
118+
onActiveFocusChanged: {
119+
if (activeFocus && createMode) {
120+
Qt.inputMethod.show()
121+
} else {
122+
Qt.inputMethod.hide()
123+
}
124+
}
125+
}
126+
127+
Button {
128+
text: "Create"
129+
Button {
130+
text: "Create"
131+
onClicked: {
132+
const name = newFolderNameField.text.trim()
133+
if (name.length > 0) {
134+
var basePath = currentFolder.toString().replace("file://", "")
135+
var newPath = basePath + "/" + name
136+
var success = filesystem.createFolder(newPath)
137+
console.log("Folder created:", success, newPath)
138+
139+
if (success) {
140+
createMode = false
141+
newFolderNameField.text = ""
142+
Qt.inputMethod.hide()
143+
}
144+
}
145+
}
146+
}
147+
}
148+
}
149+
150+
ListView {
151+
id: folderList
152+
Layout.fillWidth: true
153+
Layout.fillHeight: true
154+
clip: true
155+
156+
ScrollBar.vertical: ScrollBar {
157+
policy: ScrollBar.AlwaysOn
158+
}
159+
160+
model: FolderListModel {
161+
id: folderModel
162+
folder: currentFolder
163+
showDirs: true
164+
showFiles: false
165+
sortField: FolderListModel.Name
166+
}
167+
168+
delegate: Rectangle {
169+
width: folderList.width
170+
height: 48
171+
color: model.fileURL === currentFolder ? "#ddeeff" : "transparent"
172+
173+
Text {
174+
text: fileName
175+
anchors.verticalCenter: parent.verticalCenter
176+
anchors.left: parent.left
177+
anchors.leftMargin: 12
178+
font.pixelSize: 16
179+
color: Material.foreground
180+
}
181+
182+
MouseArea {
183+
anchors.fill: parent
184+
onClicked: {
185+
root.currentFolder = model.fileURL
186+
folderModel.folder = model.fileURL
187+
}
188+
}
189+
}
190+
}
191+
192+
RowLayout {
193+
Layout.alignment: Qt.AlignHCenter
194+
spacing: 20
195+
196+
Button {
197+
text: "Select"
198+
onClicked: {
199+
root.accepted()
200+
root.close()
201+
}
202+
}
203+
204+
Button {
205+
text: "Cancel"
206+
onClicked: {
207+
root.close()
208+
root.canceled()
209+
}
210+
}
211+
}
212+
}
213+
214+
// Virtual Keyboard - only visible if TextField is active & createMode is on
215+
InputPanel {
216+
id: inputPanel
217+
y: parent.height - height
218+
width: parent.width > 600 ? 600 : parent.width
219+
visible: Qt.inputMethod.visible && createMode
220+
anchors.horizontalCenter: parent.horizontalCenter
221+
z: 100
222+
}
223+
}
224+
}

src/filesystem.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,42 @@ QUrl FileSystem::findFile(QString filename, QList<QUrl> searchPaths, bool search
7070
QString FileSystem::getImagePath()
7171
{
7272
QSettings settings("saeugetier", "qtbooth");
73+
settings.sync();
7374
if(settings.contains("Application/foldername"))
7475
return settings.value("Application/foldername").value<QString>();
7576
else
7677
return "file://" + QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
7778
}
7879

80+
bool FileSystem::createFolder(const QString &path)
81+
{
82+
if(path.length() == 0)
83+
{
84+
qDebug() << "Filesystem Error: path is empty!";
85+
return false;
86+
}
87+
88+
QDir dir(path);
89+
if(!dir.exists())
90+
{
91+
if(dir.mkpath("."))
92+
{
93+
qDebug() << "Created folder: " << path;
94+
return true;
95+
}
96+
else
97+
{
98+
qDebug() << "Filesystem Error: Could not create folder: " << path;
99+
return false;
100+
}
101+
}
102+
else
103+
{
104+
qDebug() << "Folder already exists: " << path;
105+
return true;
106+
}
107+
}
108+
79109
void FileSystem::checkImageFolders()
80110
{
81111
QString imagePath = getImagePath();

0 commit comments

Comments
 (0)