Improve visuals and usability
Usability has been improved when entering new rows into the database. The user is now only able to write in the input form when editing an exiting entry or creating a new entry. The warning message associated with entering invalid input will now disappear after a few seconds. The ListView delegate is now slightly larger, and looks slightly better. Task-number: QTBUG-90884 Change-Id: Idf7ca9c0bb8b86ac06fed80e945800603f7b03d9 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
This commit is contained in:
parent
e8edea4e95
commit
7b263f7bf5
|
@ -1,4 +1,3 @@
|
|||
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
|
@ -60,7 +59,8 @@ Item {
|
|||
height: Screen.height / 7
|
||||
|
||||
required property ListView listView
|
||||
required property Text statusText
|
||||
signal statusMessage(string msg)
|
||||
enabled: false
|
||||
|
||||
function insertrec() {
|
||||
var rowid = parseInt(JS.dbInsert(dateInput.text, descInput.text, distInput.text), 10)
|
||||
|
@ -125,19 +125,19 @@ Item {
|
|||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
text: "Date"
|
||||
text: qsTr("Date")
|
||||
font.pixelSize: 22
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Description"
|
||||
text: qsTr("Description")
|
||||
font.pixelSize: 22
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Label {
|
||||
text: "Distance"
|
||||
text: qsTr("Distance")
|
||||
font.pixelSize: 22
|
||||
}
|
||||
|
||||
|
@ -146,14 +146,29 @@ Item {
|
|||
font.pixelSize: 22
|
||||
activeFocusOnPress: true
|
||||
activeFocusOnTab: true
|
||||
validator: RegularExpressionValidator {
|
||||
regularExpression: /[0-9/,:.]+/
|
||||
|
||||
ToolTip {
|
||||
parent: dateInput
|
||||
x: parent.width + 3
|
||||
y: (parent.height - height) / 2
|
||||
text: qsTr("Date format = 'YYYY-MM-DD'")
|
||||
visible: parent.enabled && parent.hovered
|
||||
delay: 1000
|
||||
}
|
||||
onEditingFinished: {
|
||||
if (dateInput.text == "") {
|
||||
root.statusText.text = "Please fill in the date"
|
||||
dateInput.forceActiveFocus()
|
||||
}
|
||||
|
||||
validator: RegularExpressionValidator {
|
||||
regularExpression: /\d{4}[,.:/-]\d\d?[,.:/-]\d\d?/
|
||||
}
|
||||
|
||||
onFocusChanged: ()=> {
|
||||
if (!dateInput.focus && !acceptableInput && root.enabled)
|
||||
root.statusMessage(qsTr("Please fill in the date"));
|
||||
}
|
||||
|
||||
onEditingFinished: ()=> {
|
||||
let regex = /(\d+)[,.:/-](\d+)[,.:/-](\d+)/
|
||||
if (dateInput.text.match(regex))
|
||||
dateInput.text = dateInput.text.replace(regex, '$1-$2-$3')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,13 +177,11 @@ Item {
|
|||
font.pixelSize: 22
|
||||
activeFocusOnPress: true
|
||||
activeFocusOnTab: true
|
||||
onEditingFinished: {
|
||||
if (descInput.text.length < 8) {
|
||||
root.statusText.text = "Enter a description of minimum 8 characters"
|
||||
descInput.forceActiveFocus()
|
||||
} else {
|
||||
root.statusText.text = ""
|
||||
}
|
||||
property string oldString
|
||||
onFocusChanged: ()=> { if (focus) oldString = descInput.text; }
|
||||
onEditingFinished: ()=> {
|
||||
if (descInput.text.length < 8 && descInput.text != descInput.oldString && root.enabled)
|
||||
root.statusMessage(qsTr("Enter a description of minimum 8 characters"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,11 +193,11 @@ Item {
|
|||
validator: RegularExpressionValidator {
|
||||
regularExpression: /\d{1,3}/
|
||||
}
|
||||
onEditingFinished: {
|
||||
if (distInput.text == "") {
|
||||
root.statusText.text = "Please fill in the distance"
|
||||
distInput.forceActiveFocus()
|
||||
}
|
||||
property string oldString
|
||||
onFocusChanged: ()=> { if (focus) oldString = distInput.text; }
|
||||
onEditingFinished: ()=> {
|
||||
if (distInput.text == "" && distInput.text != distInput.oldString && root.enabled)
|
||||
root.statusMessage(qsTr("Please fill in the distance"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ import "Database.js" as JS
|
|||
Item {
|
||||
id: delegate
|
||||
|
||||
width: parent.width
|
||||
height: rDate.implicitHeight
|
||||
width: ListView.view.width
|
||||
implicitHeight: rDate.implicitHeight * 1.5
|
||||
|
||||
required property int index
|
||||
required property int distance
|
||||
|
@ -72,34 +72,43 @@ Item {
|
|||
anchors.fill: parent
|
||||
opacity: 0.8
|
||||
color: delegate.index % 2 ? "lightgrey" : "grey"
|
||||
border.width: 2
|
||||
border.color: Qt.lighter(color)
|
||||
radius: 5
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: delegate.clicked()
|
||||
}
|
||||
GridLayout {
|
||||
anchors.fill:parent
|
||||
columns: 3
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
id: rDate
|
||||
Layout.preferredWidth: 42
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: delegate.date
|
||||
font.pixelSize: 22
|
||||
Layout.preferredWidth: parent.width / 4
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Label {
|
||||
id: rDesc
|
||||
Layout.preferredWidth: 42
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: delegate.trip_desc
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 22
|
||||
color: "black"
|
||||
}
|
||||
|
||||
Label {
|
||||
id: rDistance
|
||||
Layout.preferredWidth: 42
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: delegate.distance
|
||||
font.pixelSize: 22
|
||||
Layout.alignment: Qt.AlignRight
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,16 +69,18 @@ Window {
|
|||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
|
||||
Header {
|
||||
id: input
|
||||
Layout.fillWidth: true
|
||||
listView: listView
|
||||
statusText: statustext
|
||||
enabled: window.creatingNewEntry || window.editingEntry
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Button {
|
||||
text: "New"
|
||||
text: qsTr("New")
|
||||
onClicked: {
|
||||
input.initrec_new()
|
||||
window.creatingNewEntry = true
|
||||
|
@ -88,7 +90,7 @@ Window {
|
|||
Button {
|
||||
id: saveButton
|
||||
enabled: (window.creatingNewEntry || window.editingEntry) && listView.currentIndex != -1
|
||||
text: "Save"
|
||||
text: qsTr("Save")
|
||||
onClicked: {
|
||||
var insertedRow = false;
|
||||
if (listView.model.get(listView.currentIndex).id < 1) {
|
||||
|
@ -99,7 +101,7 @@ Window {
|
|||
insertedRow = true
|
||||
} else {
|
||||
// Failed to insert a row; display an error message.
|
||||
statustext.text = "Failed to insert row"
|
||||
statustext.displayWarning(qsTr("Failed to insert row"))
|
||||
}
|
||||
} else {
|
||||
// edit mode
|
||||
|
@ -120,7 +122,7 @@ Window {
|
|||
}
|
||||
Button {
|
||||
id: editButton
|
||||
text: "Edit"
|
||||
text: qsTr("Edit")
|
||||
enabled: !window.creatingNewEntry && !window.editingEntry && listView.currentIndex != -1
|
||||
onClicked: {
|
||||
input.editrec(listView.model.get(listView.currentIndex).date,
|
||||
|
@ -133,7 +135,7 @@ Window {
|
|||
}
|
||||
Button {
|
||||
id: deleteButton
|
||||
text: "Delete"
|
||||
text: qsTr("Delete")
|
||||
enabled: !window.creatingNewEntry && listView.currentIndex != -1
|
||||
onClicked: {
|
||||
JS.dbDeleteRow(listView.model.get(listView.currentIndex).id)
|
||||
|
@ -147,7 +149,7 @@ Window {
|
|||
}
|
||||
Button {
|
||||
id: cancelButton
|
||||
text: "Cancel"
|
||||
text: qsTr("Cancel")
|
||||
enabled: (window.creatingNewEntry || window.editingEntry) && listView.currentIndex != -1
|
||||
onClicked: {
|
||||
if (listView.model.get(listView.currentIndex).id === 0) {
|
||||
|
@ -162,10 +164,19 @@ Window {
|
|||
}
|
||||
}
|
||||
Button {
|
||||
text: "Exit"
|
||||
text: qsTr("Exit")
|
||||
onClicked: Qt.quit()
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
height: 5
|
||||
}
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: qsTr("Saved activities")
|
||||
font.pointSize: 15
|
||||
}
|
||||
Component {
|
||||
id: highlightBar
|
||||
Rectangle {
|
||||
|
@ -180,7 +191,8 @@ Window {
|
|||
Layout.fillHeight: true
|
||||
model: MyModel {}
|
||||
delegate: MyDelegate {
|
||||
onClicked: listView.currentIndex = index
|
||||
width: listView.width
|
||||
onClicked: ()=> listView.currentIndex = index
|
||||
}
|
||||
// Don't allow changing the currentIndex while the user is creating/editing values.
|
||||
enabled: !window.creatingNewEntry && !window.editingEntry
|
||||
|
@ -188,20 +200,70 @@ Window {
|
|||
highlight: highlightBar
|
||||
highlightFollowsCurrentItem: true
|
||||
focus: true
|
||||
clip: true
|
||||
|
||||
header: Component {
|
||||
Text {
|
||||
text: "Saved activities"
|
||||
RowLayout {
|
||||
property var headerTitles: [qsTr("Date"), qsTr("Description"), qsTr("Distance")]
|
||||
width: ListView.view.width
|
||||
Repeater {
|
||||
model: headerTitles
|
||||
delegate: Label {
|
||||
id: headerTitleDelegate
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: 1
|
||||
text: modelData
|
||||
font.pointSize: 15
|
||||
font.bold: true
|
||||
font.underline: true
|
||||
padding: 12
|
||||
horizontalAlignment: Label.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Label {
|
||||
id: statustext
|
||||
color: "red"
|
||||
Layout.fillWidth: true
|
||||
font.bold: true
|
||||
font.pointSize: 20
|
||||
opacity: 0.0
|
||||
visible: opacity !== 0 // properly cull item if effectively invisible
|
||||
Layout.alignment: Layout.Center
|
||||
|
||||
function displayWarning(text) {
|
||||
statustext.text = text
|
||||
statusAnim.restart()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: input
|
||||
function onStatusMessage(msg) { statustext.displayWarning(msg); }
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: statusAnim
|
||||
|
||||
OpacityAnimator {
|
||||
target: statustext
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
duration: 50
|
||||
}
|
||||
|
||||
PauseAnimation {
|
||||
duration: 2000
|
||||
}
|
||||
|
||||
OpacityAnimator {
|
||||
target: statustext
|
||||
from: 1.0
|
||||
to: 0.0
|
||||
duration: 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue