503 lines
23 KiB
QML
503 lines
23 KiB
QML
|
import QtQuick 2.6
|
||
|
import Sailfish.Silica 1.0
|
||
|
|
||
|
|
||
|
MouseArea {
|
||
|
id: popup
|
||
|
z: 10
|
||
|
width: parent.width
|
||
|
height: parent.height
|
||
|
visible: opacity > 0
|
||
|
opacity: 0.0
|
||
|
onClicked: {
|
||
|
hide()
|
||
|
}
|
||
|
onOpacityChanged: {
|
||
|
//if needed
|
||
|
}
|
||
|
|
||
|
// UI variables
|
||
|
property var hideBackColor : Theme.rgba(Theme.overlayBackgroundColor, 0.9)
|
||
|
property int amountBeneficiaries : listModel_activeProjectMembersTEMP.count
|
||
|
property string modeEdit : "new"
|
||
|
property real editItemIndex : -1 // -1=new, otherwise gives index of list
|
||
|
|
||
|
property int tempProjectListIndex
|
||
|
property bool showTextfieldMemberName : false
|
||
|
property string timeStamp : ((new Date).getTime()).toString() // creates unix timestamp
|
||
|
|
||
|
property string backupFilePath : ""
|
||
|
|
||
|
// suppress blend to main window on this overlay, e.g. for context menu ...
|
||
|
// BUG: creates problems with _selectOrientation for context menus larger than 5 entries
|
||
|
property alias __silica_applicationwindow_instance: fakeApplicationWindow
|
||
|
Item {
|
||
|
id: fakeApplicationWindow
|
||
|
// suppresses warnings by context menu
|
||
|
property var _dimScreen
|
||
|
property var _undim
|
||
|
function _undim() {}
|
||
|
function _dimScreen() {}
|
||
|
}
|
||
|
Behavior on opacity {
|
||
|
FadeAnimator {}
|
||
|
}
|
||
|
ListModel {
|
||
|
id: listModel_activeProjectMembersTEMP
|
||
|
}
|
||
|
RemorsePopup {
|
||
|
z: 10
|
||
|
id: remorse_deleteProject
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
Rectangle {
|
||
|
anchors.fill: parent
|
||
|
color: hideBackColor
|
||
|
onColorChanged: opacity = 4
|
||
|
|
||
|
Rectangle {
|
||
|
id: idBackgroundRectProject
|
||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||
|
anchors.top: parent.top
|
||
|
width: parent.width
|
||
|
height: parent.height - anchors.topMargin - Theme.paddingLarge
|
||
|
radius: Theme.paddingLarge
|
||
|
|
||
|
SilicaFlickable {
|
||
|
anchors.fill: parent
|
||
|
contentHeight: addExpenseColumn.height
|
||
|
clip: true
|
||
|
|
||
|
Column {
|
||
|
id: addExpenseColumn
|
||
|
width: parent.width
|
||
|
|
||
|
Row {
|
||
|
x: Theme.paddingLarge
|
||
|
width: parent.width - 2*x
|
||
|
topPadding: Theme.paddingLarge
|
||
|
bottomPadding: Theme.paddingLarge
|
||
|
|
||
|
Column {
|
||
|
id: idColumnAddProject
|
||
|
width: parent.width /3*2 - Theme.paddingLarge /2
|
||
|
|
||
|
Label {
|
||
|
width: parent.width
|
||
|
text: qsTr("Project")
|
||
|
}
|
||
|
Label {
|
||
|
width: parent.width
|
||
|
font.pixelSize: Theme.fontSizeTiny
|
||
|
text: (modeEdit === "new") ? (qsTr("create")) : (qsTr("edit"))
|
||
|
}
|
||
|
}
|
||
|
Item {
|
||
|
width: Theme.paddingLarge
|
||
|
height: 1
|
||
|
}
|
||
|
Button {
|
||
|
id: idLabelHeaderAdd2
|
||
|
enabled: (idTextfieldProjectname.length > 0) && (amountBeneficiaries > 0)
|
||
|
width: parent.width /3 - Theme.paddingLarge /2
|
||
|
height: idColumnAddProject.height
|
||
|
text: (modeEdit === "new") ? qsTr("Add") : qsTr("Save")
|
||
|
onClicked: {
|
||
|
addProjectDB()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Row {
|
||
|
width: parent.width
|
||
|
topPadding: Theme.paddingLarge
|
||
|
bottomPadding: Theme.paddingLarge
|
||
|
|
||
|
TextField {
|
||
|
id: idTextfieldProjectname
|
||
|
width: parent.width /3 * 2 - Theme.paddingLarge
|
||
|
acceptableInput: text.length < 255
|
||
|
font.pixelSize: Theme.fontSizeMedium
|
||
|
EnterKey.onClicked: {
|
||
|
focus = false
|
||
|
}
|
||
|
Label {
|
||
|
anchors.top: parent.bottom
|
||
|
anchors.topMargin: Theme.paddingSmall
|
||
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||
|
color: Theme.secondaryColor
|
||
|
text: qsTr("name")
|
||
|
}
|
||
|
}
|
||
|
Item {
|
||
|
width: Theme.paddingLarge
|
||
|
height: 1
|
||
|
}
|
||
|
TextField {
|
||
|
id: idTextfieldCurrencyProject
|
||
|
width: parent.width /3
|
||
|
textLeftMargin: 0
|
||
|
horizontalAlignment: TextInput.AlignRight
|
||
|
acceptableInput: text.length > 0
|
||
|
EnterKey.enabled: text.length >= 0
|
||
|
EnterKey.onClicked: {
|
||
|
focus = false
|
||
|
}
|
||
|
onFocusChanged: {
|
||
|
if (text.length === 0) {
|
||
|
text = recentlyUsedCurrency
|
||
|
}
|
||
|
if (focus) {
|
||
|
selectAll()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Label {
|
||
|
anchors.right: parent.right
|
||
|
anchors.top: parent.bottom
|
||
|
anchors.topMargin: Theme.paddingSmall
|
||
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||
|
color: Theme.secondaryColor
|
||
|
text: qsTr("base currency")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Row {
|
||
|
x: Theme.paddingLarge
|
||
|
width: parent.width - 2*x
|
||
|
topPadding: Theme.paddingLarge
|
||
|
|
||
|
Label {
|
||
|
x: Theme.paddingLarge
|
||
|
width: parent.width/ 3*2 - Theme.paddingLarge / 2
|
||
|
height: idAddMemberButton.height
|
||
|
verticalAlignment: Text.AlignVCenter
|
||
|
font.pixelSize: Theme.fontSizeMedium
|
||
|
text: qsTr("Members")
|
||
|
}
|
||
|
Item {
|
||
|
width: Theme.paddingLarge
|
||
|
height: 1
|
||
|
}
|
||
|
Item {
|
||
|
id: idAddMemberButton
|
||
|
width: parent.width / 3 - Theme.paddingLarge/2
|
||
|
height: Theme.iconSizeMedium
|
||
|
|
||
|
Icon {
|
||
|
anchors.right: parent.right
|
||
|
anchors.verticalCenter: parent.verticalCenter
|
||
|
height: parent.height
|
||
|
width: height
|
||
|
source: !showTextfieldMemberName ? "image://theme/icon-m-add?" : "image://theme/icon-m-clear?"
|
||
|
}
|
||
|
MouseArea {
|
||
|
anchors.fill: parent
|
||
|
onClicked: {
|
||
|
showTextfieldMemberName ? showTextfieldMemberName=false : showTextfieldMemberName=true
|
||
|
if (showTextfieldMemberName) {
|
||
|
// clear field and set for new member
|
||
|
editItemIndex = -1 // -1=add new member
|
||
|
idTextfieldAddMember.text = ""
|
||
|
idTextfieldAddMember.forceActiveFocus()
|
||
|
} else {
|
||
|
idTextfieldAddMember.text = ""
|
||
|
idTextfieldAddMember.focus = false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Column {
|
||
|
visible: !showTextfieldMemberName
|
||
|
width: parent.width
|
||
|
|
||
|
Repeater {
|
||
|
model: listModel_activeProjectMembersTEMP
|
||
|
delegate: ListItem {
|
||
|
contentHeight: Theme.itemSizeExtraSmall
|
||
|
menu: ContextMenu {
|
||
|
MenuItem {
|
||
|
text: qsTr("rename")
|
||
|
onClicked: {
|
||
|
showTextfieldMemberName ? showTextfieldMemberName=false : showTextfieldMemberName=true
|
||
|
editItemIndex = index
|
||
|
idTextfieldAddMember.text = member_name
|
||
|
idTextfieldAddMember.forceActiveFocus()
|
||
|
}
|
||
|
}
|
||
|
MenuItem {
|
||
|
text: qsTr("remove")
|
||
|
onClicked: {
|
||
|
listModel_activeProjectMembersTEMP.remove(index)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Row {
|
||
|
x: Theme.paddingLarge
|
||
|
width: parent.width - 2*x
|
||
|
height: parent.height
|
||
|
|
||
|
Label {
|
||
|
width: parent.width
|
||
|
height: parent.height
|
||
|
verticalAlignment: Text.AlignVCenter
|
||
|
horizontalAlignment: Text.AlignHCenter
|
||
|
wrapMode: Text.WordWrap
|
||
|
font.pixelSize: Theme.fontSizeSmall
|
||
|
color: Theme.highlightColor
|
||
|
text: member_name
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Row {
|
||
|
width: parent.width
|
||
|
visible: showTextfieldMemberName
|
||
|
topPadding: Theme.paddingMedium
|
||
|
|
||
|
TextField {
|
||
|
id: idTextfieldAddMember
|
||
|
width: parent.width // 3*2 - Theme.paddingLarge
|
||
|
acceptableInput: text.length < 255
|
||
|
font.pixelSize: Theme.fontSizeSmall
|
||
|
onActiveFocusChanged: {
|
||
|
if (!focus) {
|
||
|
showTextfieldMemberName = false
|
||
|
idTextfieldAddMember.text = ""
|
||
|
}
|
||
|
}
|
||
|
EnterKey.onClicked: {
|
||
|
if (text.length > 0) {
|
||
|
if (editItemIndex === -1) { // -1=add new member
|
||
|
listModel_activeProjectMembersTEMP.append({ member_name : idTextfieldAddMember.text,
|
||
|
member_isBeneficiary : true,
|
||
|
member_isPayer : false,
|
||
|
})
|
||
|
} else { // "edit" existing member name by index in listmodel
|
||
|
listModel_activeProjectMembersTEMP.setProperty(editItemIndex, "member_name", idTextfieldAddMember.text)
|
||
|
}
|
||
|
}
|
||
|
focus = false
|
||
|
showTextfieldMemberName = false
|
||
|
}
|
||
|
Label {
|
||
|
anchors.top: parent.bottom
|
||
|
anchors.topMargin: Theme.paddingSmall
|
||
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||
|
text: qsTr("name")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Item {
|
||
|
width: parent.width
|
||
|
height: Theme.itemSizeSmall
|
||
|
}
|
||
|
Row {
|
||
|
width: parent.width
|
||
|
visible: (modeEdit === "edit") && (listModel_allProjects.count > 0) // make sure there is always one project left once created
|
||
|
spacing: Theme.paddingLarge
|
||
|
leftPadding: Theme.paddingLarge
|
||
|
|
||
|
Button {
|
||
|
id: idLabelDeleteProject
|
||
|
width: parent.width /3 - parent.spacing * 1.5
|
||
|
height: idColumnAddProject.height
|
||
|
color: Theme.errorColor
|
||
|
text: (Number(activeProjectID_unixtime) != Number(timeStamp)) ? qsTr("Delete") : qsTr("Reset")
|
||
|
onClicked: {
|
||
|
if (Number(activeProjectID_unixtime) != Number(timeStamp)) { // if it is not the active project, delete it
|
||
|
remorse_deleteProject.execute(qsTr("Delete this project?"), function() {
|
||
|
deleteProject()
|
||
|
})
|
||
|
} else { // if active project
|
||
|
remorse_deleteProject.execute(qsTr("Clear all transactions?"), function() {
|
||
|
clearProject()
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Button {
|
||
|
id: idLabelBackupProject
|
||
|
width: parent.width /3 - parent.spacing * 1.5
|
||
|
height: idColumnAddProject.height
|
||
|
text: qsTr("Backup")
|
||
|
onClicked: {
|
||
|
// hide() // ToDo: maybe close this popup?
|
||
|
pageStack.push(idFolderPickerPage)
|
||
|
}
|
||
|
}
|
||
|
Button {
|
||
|
id: idLabelRestoreProject
|
||
|
width: parent.width /3 - parent.spacing
|
||
|
height: idColumnAddProject.height
|
||
|
text: qsTr("Restore")
|
||
|
onClicked: {
|
||
|
// hide() // ToDo: maybe close this popup?
|
||
|
pageStack.push(idFilePickerPage)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Item {
|
||
|
width: parent.width
|
||
|
height: Theme.itemSizeSmall / 2
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Icon {
|
||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||
|
anchors.top: parent.top
|
||
|
anchors.topMargin: idBackgroundRectProject.anchors.topMargin / 2 - height/2
|
||
|
source: "image://theme/icon-splus-cancel?"
|
||
|
opacity: 1
|
||
|
}
|
||
|
|
||
|
|
||
|
function notify( color, upperMargin, modeEditNew, indexCurrentProject ) {
|
||
|
// color settings
|
||
|
if (color && (typeof(color) != "undefined")) {
|
||
|
idBackgroundRectProject.color = color
|
||
|
}
|
||
|
else {
|
||
|
idBackgroundRectProject.color = Theme.rgba(Theme.highlightBackgroundColor, 0.9)
|
||
|
}
|
||
|
|
||
|
// position settings
|
||
|
if (upperMargin && (typeof(upperMargin) != "undefined")) {
|
||
|
idBackgroundRectProject.anchors.topMargin = upperMargin
|
||
|
}
|
||
|
else {
|
||
|
idBackgroundRectProject.anchors.topMargin = 0
|
||
|
}
|
||
|
|
||
|
// adjust input fields
|
||
|
tempProjectListIndex = indexCurrentProject
|
||
|
listModel_activeProjectMembersTEMP.clear()
|
||
|
if (modeEditNew === "new") {
|
||
|
modeEdit = "new"
|
||
|
timeStamp = ((new Date).getTime()).toString()
|
||
|
idTextfieldCurrencyProject.text = recentlyUsedCurrency
|
||
|
idTextfieldProjectname.text = ""
|
||
|
idTextfieldProjectname.forceActiveFocus()
|
||
|
} else { // edit project mode
|
||
|
modeEdit = "edit"
|
||
|
var tempProjectMembersArray = []
|
||
|
tempProjectMembersArray = (listModel_allProjects.get(idComboboxProject.currentIndex).project_members).split(" ||| ")
|
||
|
for (var i = 0; i < tempProjectMembersArray.length ; i++) {
|
||
|
listModel_activeProjectMembersTEMP.append({ member_name : tempProjectMembersArray[i],
|
||
|
})
|
||
|
}
|
||
|
timeStamp = (listModel_allProjects.get(idComboboxProject.currentIndex).project_id_timestamp).toString()
|
||
|
idTextfieldProjectname.text = listModel_allProjects.get(idComboboxProject.currentIndex).project_name
|
||
|
idTextfieldCurrencyProject.text = listModel_allProjects.get(idComboboxProject.currentIndex).project_base_currency
|
||
|
}
|
||
|
|
||
|
// all members are beneficiaries
|
||
|
|
||
|
|
||
|
// show banner overlay
|
||
|
popup.opacity = 1.0
|
||
|
}
|
||
|
|
||
|
function hide() {
|
||
|
idTextfieldProjectname.focus = false
|
||
|
idTextfieldCurrencyProject.focus = false
|
||
|
|
||
|
// clear all fields
|
||
|
idTextfieldProjectname.text = ""
|
||
|
idTextfieldCurrencyProject.text = recentlyUsedCurrency
|
||
|
|
||
|
// make invisible
|
||
|
popup.opacity = 0.0
|
||
|
}
|
||
|
|
||
|
function addProjectDB () {
|
||
|
var project_id_timestamp = timeStamp
|
||
|
var project_name = idTextfieldProjectname.text
|
||
|
var project_members = ""
|
||
|
var project_recent_payer_boolarray = ""
|
||
|
var project_recent_beneficiaries_boolarray = ""
|
||
|
var project_base_currency = idTextfieldCurrencyProject.text
|
||
|
|
||
|
for (var i = 0; i < listModel_activeProjectMembersTEMP.count ; i++) {
|
||
|
project_members += " ||| " + listModel_activeProjectMembersTEMP.get(i).member_name
|
||
|
project_recent_beneficiaries_boolarray += " ||| " + "true"
|
||
|
// recent_payer can only be one person, initially this will be the first entry of the list
|
||
|
if (i===0) {
|
||
|
project_recent_payer_boolarray += " ||| " + "true"
|
||
|
} else {
|
||
|
project_recent_payer_boolarray += " ||| " + "false"
|
||
|
}
|
||
|
}
|
||
|
// remove first occurance of " ||| " to later be able to split that string
|
||
|
project_members = project_members.replace(" ||| ", "")
|
||
|
project_recent_payer_boolarray = project_recent_payer_boolarray.replace(" ||| ", "")
|
||
|
project_recent_beneficiaries_boolarray = project_recent_beneficiaries_boolarray.replace(" ||| ", "")
|
||
|
|
||
|
if (modeEdit === "new") {
|
||
|
// store in DB and list for new project
|
||
|
storageItem.setProject( project_id_timestamp, project_name, project_members, project_recent_payer_boolarray, project_recent_beneficiaries_boolarray, project_base_currency )
|
||
|
listModel_allProjects.append({ project_id_timestamp : Number(project_id_timestamp),
|
||
|
project_name : project_name,
|
||
|
project_members : project_members,
|
||
|
project_recent_payer_boolarray : project_recent_payer_boolarray,
|
||
|
project_recent_beneficiaries_boolarray : project_recent_beneficiaries_boolarray,
|
||
|
project_base_currency : project_base_currency,
|
||
|
})
|
||
|
|
||
|
// if this is the first project, auto set it as active project
|
||
|
if (listModel_allProjects.count === 1) { // auto-sets as currently active project, if this project is very first one
|
||
|
storageItem.setSettings("activeProjectID_unixtime", Number(project_id_timestamp) )
|
||
|
activeProjectID_unixtime = Number(project_id_timestamp)
|
||
|
loadActiveProjectInfos_FromDB( Number(project_id_timestamp) )
|
||
|
//console.log("auto set as active project ID = " + activeProjectID_unixtime)
|
||
|
}
|
||
|
|
||
|
} else { // modeEdit === "edit
|
||
|
// update DB and list for existing project
|
||
|
storageItem.updateProject( project_id_timestamp, project_name, project_members, project_recent_payer_boolarray, project_recent_beneficiaries_boolarray, project_base_currency )
|
||
|
for (var j = 0; j < listModel_allProjects.count ; j++) {
|
||
|
if (listModel_allProjects.get(j).project_id_timestamp === Number(project_id_timestamp)) {
|
||
|
//console.log("updated entry at: id_" + project_id_timestamp)
|
||
|
listModel_allProjects.set(j, { "project_name" : project_name,
|
||
|
"project_members" : project_members,
|
||
|
"project_recent_payer_boolarray" : project_recent_payer_boolarray,
|
||
|
"project_recent_beneficiaries_boolarray" : project_recent_beneficiaries_boolarray,
|
||
|
"project_base_currency" : project_base_currency
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
updateEvenWhenCanceled = true
|
||
|
hide()
|
||
|
}
|
||
|
|
||
|
function deleteProject() {
|
||
|
updateEvenWhenCanceled = true
|
||
|
storageItem.deleteProject(timeStamp)
|
||
|
listModel_allProjects.remove(tempProjectListIndex)
|
||
|
// set active project to reasonable one
|
||
|
if (idComboboxProject.currentIndex != 0) {
|
||
|
idComboboxProject.currentIndex = idComboboxProject.currentIndex -1
|
||
|
}
|
||
|
//console.log("auto set after deleting ID = " + Number(listModel_allProjects.get(idComboboxProject.currentIndex).project_id_timestamp))
|
||
|
loadActiveProjectInfos_FromDB(Number(listModel_allProjects.get(idComboboxProject.currentIndex).project_id_timestamp)) // needed to make sure there is no expense or member list still active
|
||
|
hide()
|
||
|
}
|
||
|
|
||
|
function clearProject() {
|
||
|
updateEvenWhenCanceled = true
|
||
|
listModel_activeProjectExpenses.clear()
|
||
|
storageItem.removeFullTable( "table_" + activeProjectID_unixtime.toString() )
|
||
|
loadActiveProjectInfos_FromDB(Number(listModel_allProjects.get(idComboboxProject.currentIndex).project_id_timestamp)) // needed to make sure there is no expense or member list still active
|
||
|
hide()
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|