Skip to content

Commit a440f27

Browse files
committed
First pass improvements to the automapper GUI
1 parent c73b905 commit a440f27

3 files changed

Lines changed: 137 additions & 99 deletions

File tree

qml/DialogAutoMapper.qml

Lines changed: 101 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@ import Gremlin.UI
2929

3030

3131
Window {
32-
id: _root
33-
3432
minimumWidth: 900
35-
minimumHeight: 300
33+
minimumHeight: 400
3634

37-
title: "Auto Mapper"
35+
title: "Auto Mapper: Maps your physical controls to vJoy inputs"
3836

3937
DeviceListModel {
4038
id: physicalDevices
@@ -46,157 +44,164 @@ Window {
4644
deviceType: "virtual"
4745
}
4846

49-
property AutoMapper autoMapper: backend.getAutoMapper()
47+
AutoMapper {
48+
id: autoMapper
49+
}
5050

51-
// Properties to track the selected devices
51+
// Properties to track the selected devices and user selections.
5252
property var selectedPhysicalDevices: ({})
5353
property var selectedVJoyDevices: ({})
5454
property bool overwriteNonEmpty: false
5555
property bool repeatVJoy: false
5656

57+
property string statusMessage: "Select devices, options and click the Create button"
58+
5759
Rectangle {
58-
id: mainWindow
5960
anchors.fill: parent
6061
anchors.margins: 10
6162

62-
Column {
63-
id: mainColumn
63+
ColumnLayout {
6464
anchors.fill: parent
6565
spacing: 10
6666

67-
Row {
68-
id: devicesRow
69-
width: parent.width
70-
height: parent.height - 60 // Leave space for the button
71-
spacing: 20
67+
// Description/Manual Section
68+
TextOutputBox {
69+
Layout.fillWidth: true
70+
Layout.preferredHeight: 100
71+
text: qsTr("<ul>" +
72+
"<li>Select source physical devices and target vJoy devices" +
73+
"<li>Click 'Create 1:1 mappings' to map from physical to virtual inputs" +
74+
"<li>Enable 'Overwrite non-empty' to replace existing mappings in the profile" +
75+
"<li>Enable 'Repeat vJoy' to cycle through vJoy inputs, if needed to map all physical inputs" +
76+
"</ul>")
77+
}
7278

73-
Column {
74-
id: physicalDevicesColumn
75-
width: parent.width * 0.45
76-
height: parent.height
77-
spacing: 5
79+
// Main content area with device lists
80+
RowLayout {
81+
Layout.fillWidth: true
82+
Layout.fillHeight: true
83+
spacing: 10
7884

79-
CheckBox {
80-
id: overwriteNonEmptyPhysicalInputsCheckbox
81-
width: parent.width
82-
text: qsTr("Overwrite non-empty physical inputs")
83-
checked: overwriteNonEmpty
84-
onCheckedChanged: overwriteNonEmpty = checked
85-
}
85+
// Physical Devices Column
86+
ColumnLayout {
87+
Layout.fillWidth: true
88+
Layout.fillHeight: true
89+
spacing: 5
8690

8791
GroupBox {
88-
id: physicalDevicesGroupBox
89-
width: parent.width
90-
height: parent.height - overwriteNonEmptyPhysicalInputsCheckbox.height - 5
92+
Layout.fillWidth: true
93+
Layout.fillHeight: true
9194
title: qsTr("Physical Devices")
9295

9396
ScrollView {
94-
id: physicalDevicesScroll
97+
id: _physicalScroll
9598
anchors.fill: parent
9699
clip: true
97100

98-
Column {
99-
width: physicalDevicesScroll.width - 20
101+
ListView {
102+
model: physicalDevices
100103
spacing: 5
101-
padding: 5
102-
103-
Repeater {
104-
model: physicalDevices
105-
delegate: CheckBox {
106-
width: parent.width - 10
107-
text: model.name
108-
checked: false
109-
onCheckedChanged: {
110-
selectedPhysicalDevices[model.guid] = checked;
111-
}
104+
delegate: CheckBox {
105+
width: ListView.view.width - 10
106+
text: model.name
107+
checked: false
108+
onCheckedChanged: {
109+
selectedPhysicalDevices[model.guid] = checked;
112110
}
113111
}
114112
}
115113
}
116114
}
117-
}
118115

119-
Column {
120-
id: vjoyDevicesColumn
121-
width: parent.width * 0.45
122-
height: parent.height
123-
spacing: 5
116+
Switch {
117+
id: _overwriteSwitch
118+
Layout.fillWidth: true
119+
text: qsTr("Overwrite non-empty physical inputs")
124120

125-
CheckBox {
126-
id: repeatVJoyCheckbox
127-
width: parent.width
128-
text: qsTr("Repeat vJoy devices")
129-
checked: repeatVJoy
130-
onCheckedChanged: repeatVJoy = checked
121+
ToolTip {
122+
visible: parent.hovered
123+
text: qsTr("Overwrite non-empty physical inputs")
124+
delay: 500
125+
}
126+
127+
onToggled: function() {
128+
overwriteNonEmpty = position ? true : false;
129+
}
131130
}
131+
}
132+
133+
// vJoy Devices Column
134+
ColumnLayout {
135+
Layout.fillWidth: true
136+
Layout.fillHeight: true
137+
spacing: 5
132138

133139
GroupBox {
134-
id: vjoyDevicesGroupBox
135-
width: parent.width
136-
height: parent.height - repeatVJoyCheckbox.height - 5
140+
Layout.fillWidth: true
141+
Layout.fillHeight: true
137142
title: qsTr("vJoy Devices")
138143

139144
ScrollView {
140-
id: vjoyDevicesScroll
145+
id: _vjoyScroll
141146
anchors.fill: parent
142147
clip: true
143148

144-
Column {
145-
width: vjoyDevicesScroll.width - 20
149+
ListView {
150+
model: virtualDevices
146151
spacing: 5
147-
padding: 5
148-
149-
Repeater {
150-
model: virtualDevices
151-
delegate: CheckBox {
152-
width: parent.width - 10
153-
text: model.name
154-
checked: false
155-
onCheckedChanged: {
156-
selectedVJoyDevices[model.vjoy_id] = checked;
157-
}
152+
delegate: CheckBox {
153+
width: ListView.view.width - 10
154+
text: model.name
155+
checked: false
156+
onCheckedChanged: {
157+
selectedVJoyDevices[model.vjoy_id] = checked;
158158
}
159159
}
160160
}
161161
}
162162
}
163+
164+
Switch {
165+
id: _repeatSwitch
166+
Layout.fillWidth: true
167+
text: qsTr("Repeat vJoy devices")
168+
169+
ToolTip {
170+
visible: parent.hovered
171+
text: qsTr("Repeat vJoy devices")
172+
delay: 500
173+
}
174+
175+
onToggled: function() {
176+
repeatVJoy = position ? true : false;
177+
}
178+
}
163179
}
164180
}
165181

166-
Row {
167-
id: buttonRow
168-
width: Math.min(600, parent.width * 0.8)
169-
height: 60
182+
// Action bar with button and status
183+
RowLayout {
184+
Layout.fillWidth: true
185+
Layout.preferredHeight: 35
170186
spacing: 10
171-
anchors.horizontalCenter: parent.horizontalCenter
172187

173188
Button {
174-
id: createButton
189+
id: _createButton
175190
text: qsTr("Create 1:1 mappings")
191+
Layout.preferredWidth: implicitWidth + 20
192+
Layout.preferredHeight: 30
176193
onClicked: {
177-
var result = autoMapper.create_mappings(
194+
statusMessage = autoMapper.create_mappings(
178195
selectedPhysicalDevices, selectedVJoyDevices,
179196
overwriteNonEmpty, repeatVJoy);
180-
resultText.text = result ? result : "";
181197
}
182-
height: parent.height
183-
width: 200
184198
}
185199

186-
TextArea {
187-
id: resultText
188-
width: parent.width - createButton.width - parent.spacing
189-
height: parent.height
190-
readOnly: true
191-
wrapMode: Text.WordWrap
192-
horizontalAlignment: Text.AlignRight
193-
placeholderText: qsTr("Awaiting user selections and button press")
194-
background: Rectangle {
195-
color: "#f5f5f5"
196-
border.color: "#cccccc"
197-
border.width: 1
198-
radius: 2
199-
}
200+
TextOutputBox {
201+
id: _statusNotification
202+
Layout.fillWidth: true
203+
Layout.preferredHeight: 30
204+
text: statusMessage
200205
}
201206
}
202207
}

qml/Main.qml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,6 @@ ApplicationWindow {
294294

295295
ToolButton {
296296
text: "1:1"
297-
font.family: "bootstrap-icons"
298-
font.pixelSize: 20
299-
font.weight: 900
300297

301298
ToolTip {
302299
visible: parent.hovered

qml/TextOutputBox.qml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// -*- coding: utf-8; -*-
2+
//
3+
// Copyright (C) 2015 - 2025 Lionel Ott
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
import QtQuick
19+
import QtQuick.Controls
20+
import QtQuick.Controls.Universal
21+
22+
Rectangle {
23+
id: root
24+
property alias text: _notificationLabel.text
25+
26+
color: Universal.background
27+
border.color: Universal.accent
28+
29+
Label {
30+
id: _notificationLabel
31+
anchors.fill: parent
32+
anchors.margins: 8
33+
verticalAlignment: Text.AlignVCenter
34+
elide: Text.ElideRight
35+
}
36+
}

0 commit comments

Comments
 (0)