From ba2b553d7c8a01a2e11b3892e7710dc697747f61 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Tue, 22 Jun 2021 11:38:45 -0400 Subject: [PATCH] refactor: Profile --- src/app/profile/core.nim | 16 +- src/app/profile/view.nim | 149 ++++-------------- src/app/profile/views/muted_chats.nim | 86 ++++++++++ src/app/profile/views/profile_picture.nim | 48 ++++++ src/app/profile/views/profile_settings.nim | 63 ++++++++ src/app/provider/view.nim | 6 +- .../Sections/ChangeProfilePicModal.qml | 4 +- .../Profile/Sections/MutedChatsModal.qml | 4 +- .../Sections/NotificationsContainer.qml | 4 +- ui/app/AppMain.qml | 6 +- ui/main.qml | 2 +- 11 files changed, 251 insertions(+), 137 deletions(-) create mode 100644 src/app/profile/views/muted_chats.nim create mode 100644 src/app/profile/views/profile_picture.nim create mode 100644 src/app/profile/views/profile_settings.nim diff --git a/src/app/profile/core.nim b/src/app/profile/core.nim index c0da39bdfc..c1a88534f4 100644 --- a/src/app/profile/core.nim +++ b/src/app/profile/core.nim @@ -11,7 +11,7 @@ import ../../status/chat/chat import ../../status/wallet import ../../eventemitter import view -import views/[ens_manager, devices, network, mailservers, contacts] +import views/[ens_manager, devices, network, mailservers, contacts, muted_chats] import ../chat/views/channels_list import chronicles import ../../status/tasks/marathon/mailserver/events @@ -73,25 +73,25 @@ proc init*(self: ProfileController, account: Account) = var channel = ChannelArgs(e) if channel.chat.muted: if channel.chat.chatType.isOneToOne: - discard self.view.mutedContacts.addChatItemToList(channel.chat) + discard self.view.mutedChats.mutedContacts.addChatItemToList(channel.chat) return - discard self.view.mutedChats.addChatItemToList(channel.chat) + discard self.view.mutedChats.mutedChats.addChatItemToList(channel.chat) self.status.events.on("channelJoined") do(e: Args): var channel = ChannelArgs(e) if channel.chat.muted: if channel.chat.chatType.isOneToOne: - discard self.view.mutedContacts.addChatItemToList(channel.chat) + discard self.view.mutedChats.mutedContacts.addChatItemToList(channel.chat) return - discard self.view.mutedChats.addChatItemToList(channel.chat) + discard self.view.mutedChats.mutedChats.addChatItemToList(channel.chat) self.status.events.on("chatsLoaded") do(e:Args): - self.view.mutedChatsListChanged() - self.view.mutedContactsListChanged() + self.view.mutedChats.mutedChatsListChanged() + self.view.mutedChats.mutedContactsListChanged() self.status.events.on("chatUpdate") do(e: Args): var evArgs = ChatUpdateArgs(e) - self.view.updateChats(evArgs.chats) + self.view.mutedChats.updateChats(evArgs.chats) self.status.events.on("contactAdded") do(e: Args): let contacts = self.status.contacts.getContacts() diff --git a/src/app/profile/view.nim b/src/app/profile/view.nim index 474ca59a3b..1c19a781f1 100644 --- a/src/app/profile/view.nim +++ b/src/app/profile/view.nim @@ -1,5 +1,5 @@ import NimQml, sequtils, strutils, sugar, os, json, chronicles -import views/[mailservers_list, ens_manager, contacts, devices, mailservers, mnemonic, network, fleets, profile_info, device_list, dapp_list] +import views/[mailservers_list, ens_manager, contacts, devices, mailservers, mnemonic, network, fleets, profile_info, device_list, dapp_list, profile_picture, profile_settings, muted_chats] import chronicles import ../chat/views/channels_list import ../../status/profile/profile @@ -16,17 +16,16 @@ import ../utils/image_utils logScope: topics = "profile-view" -const UNKNOWN_ACCOUNT = "unknownAccount" - QtObject: type ProfileView* = ref object of QObject profile*: ProfileInfoView + profilePicture*: ProfilePictureView + profileSettings*: ProfileSettingsView + mutedChats*: MutedChatsView contacts*: ContactsView devices*: DevicesView mailservers*: MailserversView mnemonic*: MnemonicView - mutedChats*: ChannelsList - mutedContacts*: ChannelsList dappList*: DappList fleets*: Fleets network*: NetworkView @@ -40,9 +39,10 @@ QtObject: proc delete*(self: ProfileView) = if not self.contacts.isNil: self.contacts.delete if not self.devices.isNil: self.devices.delete - if not self.mutedChats.isNil: self.mutedChats.delete - if not self.mutedContacts.isNil: self.mutedContacts.delete if not self.ens.isNil: self.ens.delete + if not self.profilePicture.isNil: self.profilePicture.delete + if not self.profileSettings.isNil: self.profileSettings.delete + if not self.mutedChats.isNil: self.mutedChats.delete if not self.profile.isNil: self.profile.delete if not self.dappList.isNil: self.dappList.delete if not self.fleets.isNil: self.fleets.delete @@ -55,13 +55,14 @@ QtObject: new(result, delete) result = ProfileView() result.profile = newProfileInfoView() + result.profilePicture = newProfilePictureView(status, result.profile) + result.profileSettings = newProfileSettingsView(status, result.profile) + result.mutedChats = newMutedChatsView(status) result.contacts = newContactsView(status) result.devices = newDevicesView(status) result.network = newNetworkView(status) result.mnemonic = newMnemonicView(status) result.mailservers = newMailserversView(status) - result.mutedChats = newChannelsList(status) - result.mutedContacts = newChannelsList(status) result.dappList = newDappList(status) result.ens = newEnsManager(status) result.fleets = newFleets(status) @@ -69,31 +70,6 @@ QtObject: result.status = status result.setup - proc profileSettingsFileChanged*(self: ProfileView) {.signal.} - - proc getProfileSettingsFile(self: ProfileView): string {.slot.} = - let pubkey = - if (self.profile.pubKey == ""): - UNKNOWN_ACCOUNT - else: - self.profile.pubKey - - return os.joinPath(accountConstants.DATADIR, "qt", pubkey) - - QtProperty[string] profileSettingsFile: - read = getProfileSettingsFile - notify = profileSettingsFileChanged - - proc getGlobalSettingsFile(self: ProfileView): string {.slot.} = - return os.joinPath(accountConstants.DATADIR, "qt", "global") - - proc globalSettingsFileChanged*(self: ProfileView) {.signal.} - - QtProperty[string] globalSettingsFile: - read = getGlobalSettingsFile - notify = globalSettingsFileChanged - - proc initialized*(self: ProfileView) {.signal.} proc getProfile(self: ProfileView): QVariant {.slot.} = @@ -103,14 +79,7 @@ QtObject: proc setNewProfile*(self: ProfileView, profile: Profile) = self.profile.setProfile(profile) - self.profileChanged() - self.profileSettingsFileChanged() - # Remove old 'unknownAccount' settings file if it was created - let unknownSettingsPath = os.joinPath(accountConstants.DATADIR, "qt", UNKNOWN_ACCOUNT) - if (not unknownSettingsPath.tryRemoveFile): - # Only fails if the file exists and an there was an error removing it - # More info: https://nim-lang.org/docs/os.html#tryRemoveFile%2Cstring - warn "Failed to remove unused settings file", file=unknownSettingsPath + self.profileSettings.removeUnknownAccountSettings() QtProperty[QVariant] profile: read = getProfile @@ -132,13 +101,6 @@ QtObject: self.profile.setAppearance(theme) self.status.saveSetting(Setting.Appearance, $theme) - proc setMessagesFromContactsOnly*(self: ProfileView, messagesFromContactsOnly: bool) {.slot.} = - if (messagesFromContactsOnly == self.profile.messagesFromContactsOnly): - return - self.profile.setMessagesFromContactsOnly(messagesFromContactsOnly) - self.status.saveSetting(Setting.MessagesFromContactsOnly, messagesFromContactsOnly) - # TODO cleanup chats after activating this - proc getDappList(self: ProfileView): QVariant {.slot.} = return newQVariant(self.dappList) @@ -160,54 +122,12 @@ QtObject: proc getLinkPreviewWhitelist*(self: ProfileView): string {.slot.} = result = $(self.status.profile.getLinkPreviewWhitelist()) - proc getMutedChatsList(self: ProfileView): QVariant {.slot.} = - newQVariant(self.mutedChats) - - proc getMutedContactsList(self: ProfileView): QVariant {.slot.} = - newQVariant(self.mutedContacts) - - proc mutedChatsListChanged*(self: ProfileView) {.signal.} - - proc mutedContactsListChanged*(self: ProfileView) {.signal.} - - QtProperty[QVariant] mutedChats: - read = getMutedChatsList - notify = mutedChatsListChanged - - QtProperty[QVariant] mutedContacts: - read = getMutedContactsList - notify = mutedContactsListChanged - - proc unmuteChannel*(self: ProfileView, chatId: string) {.slot.} = - if (self.mutedChats.chats.len == 0 and self.mutedContacts.chats.len == 0): return - - var selectedChannel = self.mutedChats.getChannelById(chatId) - if (selectedChannel != nil): - discard self.mutedChats.removeChatItemFromList(chatId) - else: - selectedChannel = self.mutedContacts.getChannelById(chatId) - if (selectedChannel == nil): return - discard self.mutedContacts.removeChatItemFromList(chatId) - - selectedChannel.muted = false - self.status.chat.unmuteChat(selectedChannel) - self.mutedChatsListChanged() - self.mutedContactsListChanged() - - proc updateChats*(self: ProfileView, chats: seq[Chat]) = - for chat in chats: - if not chat.muted: - if chat.chatType.isOneToOne: - discard self.mutedContacts.removeChatItemFromList(chat.id) - else: - discard self.mutedChats.removeChatItemFromList(chat.id) - else: - if chat.chatType.isOneToOne: - discard self.mutedContacts.addChatItemToList(chat) - else: - discard self.mutedChats.addChatItemToList(chat) - self.mutedChatsListChanged() - self.mutedContactsListChanged() + proc setMessagesFromContactsOnly*(self: ProfileView, messagesFromContactsOnly: bool) {.slot.} = + if (messagesFromContactsOnly == self.profile.messagesFromContactsOnly): + return + self.profile.setMessagesFromContactsOnly(messagesFromContactsOnly) + self.status.saveSetting(Setting.MessagesFromContactsOnly, messagesFromContactsOnly) + # TODO cleanup chats after activating this proc contactsChanged*(self: ProfileView) {.signal.} @@ -236,29 +156,26 @@ QtObject: QtProperty[QVariant] mnemonic: read = getMnemonic - proc getNetwork*(self: ProfileView): QVariant {.slot.} = + proc getNetwork*(self: ProfileView): QVariant {.slot.} = newQVariant(self.network) QtProperty[QVariant] network: read = getNetwork - proc uploadNewProfilePic*(self: ProfileView, imageUrl: string, aX: int, aY: int, bX: int, bY: int): string {.slot.} = - var image = image_utils.formatImagePath(imageUrl) - # FIXME the function to get the file size is messed up - # var size = image_getFileSize(image) - # TODO find a way to i18n this (maybe send just a code and then QML sets the right string) - # return "Max file size is 20MB" + proc getProfilePicture*(self: ProfileView): QVariant {.slot.} = + newQVariant(self.profilePicture) - try: - # TODO add crop tool for the image - let identityImage = self.status.profile.storeIdentityImage(self.profile.address, image, aX, aY, bX, bY) - self.profile.setIdentityImage(identityImage) - result = "" - except Exception as e: - error "Error storing identity image", msg=e.msg - result = "Error storing identity image: " & e.msg + QtProperty[QVariant] picture: + read = getProfilePicture - proc deleteProfilePic*(self: ProfileView): string {.slot.} = - result = self.status.profile.deleteIdentityImage(self.profile.address) - if (result == ""): - self.profile.removeIdentityImage() + proc getProfileSettings*(self: ProfileView): QVariant {.slot.} = + newQVariant(self.profileSettings) + + QtProperty[QVariant] settings: + read = getProfileSettings + + proc getMutedChats*(self: ProfileView): QVariant {.slot.} = + newQVariant(self.mutedChats) + + QtProperty[QVariant] mutedChats: + read = getMutedChats diff --git a/src/app/profile/views/muted_chats.nim b/src/app/profile/views/muted_chats.nim new file mode 100644 index 0000000000..a430f9faad --- /dev/null +++ b/src/app/profile/views/muted_chats.nim @@ -0,0 +1,86 @@ +import NimQml, sequtils, strutils, sugar, os, json, chronicles +import chronicles +import ../../chat/views/channels_list +import ../../../status/profile/profile +import ../../../status/profile as status_profile +import ../../../status/contacts as status_contacts +import ../../../status/status +import ../../../status/ens as status_ens +import ../../../status/chat/chat +import ../../../status/types +import ../../../status/constants as accountConstants +import ../../utils/image_utils + +logScope: + topics = "muted-chats-view" + +QtObject: + type MutedChatsView* = ref object of QObject + status*: Status + mutedChats*: ChannelsList + mutedContacts*: ChannelsList + + proc setup(self: MutedChatsView) = + self.QObject.setup + + proc delete*(self: MutedChatsView) = + if not self.mutedChats.isNil: self.mutedChats.delete + if not self.mutedContacts.isNil: self.mutedContacts.delete + self.QObject.delete + + proc newMutedChatsView*(status: Status): MutedChatsView = + new(result, delete) + result.status = status + result.mutedChats = newChannelsList(status) + result.mutedContacts = newChannelsList(status) + result.setup + + proc getMutedChatsList(self: MutedChatsView): QVariant {.slot.} = + newQVariant(self.mutedChats) + + proc getMutedContactsList(self: MutedChatsView): QVariant {.slot.} = + newQVariant(self.mutedContacts) + + proc mutedChatsListChanged*(self: MutedChatsView) {.signal.} + + proc mutedContactsListChanged*(self: MutedChatsView) {.signal.} + + QtProperty[QVariant] chats: + read = getMutedChatsList + notify = mutedChatsListChanged + + QtProperty[QVariant] contacts: + read = getMutedContactsList + notify = mutedContactsListChanged + + proc unmuteChannel*(self: MutedChatsView, chatId: string) {.slot.} = + echo "A" + if (self.mutedChats.chats.len == 0 and self.mutedContacts.chats.len == 0): return + echo "B" + var selectedChannel = self.mutedChats.getChannelById(chatId) + if (selectedChannel != nil): + discard self.mutedChats.removeChatItemFromList(chatId) + else: + selectedChannel = self.mutedContacts.getChannelById(chatId) + if (selectedChannel == nil): return + discard self.mutedContacts.removeChatItemFromList(chatId) + echo "C" + selectedChannel.muted = false + self.status.chat.unmuteChat(selectedChannel) + self.mutedChatsListChanged() + self.mutedContactsListChanged() + + proc updateChats*(self: MutedChatsView, chats: seq[Chat]) = + for chat in chats: + if not chat.muted: + if chat.chatType.isOneToOne: + discard self.mutedContacts.removeChatItemFromList(chat.id) + else: + discard self.mutedChats.removeChatItemFromList(chat.id) + else: + if chat.chatType.isOneToOne: + discard self.mutedContacts.addChatItemToList(chat) + else: + discard self.mutedChats.addChatItemToList(chat) + self.mutedChatsListChanged() + self.mutedContactsListChanged() diff --git a/src/app/profile/views/profile_picture.nim b/src/app/profile/views/profile_picture.nim new file mode 100644 index 0000000000..8a3927ee76 --- /dev/null +++ b/src/app/profile/views/profile_picture.nim @@ -0,0 +1,48 @@ +import NimQml +import chronicles +import profile_info +import ../../utils/image_utils +import ../../../status/profile as status_profile +import ../../../status/status + + +logScope: + topics = "profile-picture-view" + +QtObject: + type ProfilePictureView* = ref object of QObject + status*: Status + profile*: ProfileInfoView + + proc setup(self: ProfilePictureView) = + self.QObject.setup + + proc delete*(self: ProfilePictureView) = + self.QObject.delete + + proc newProfilePictureView*(status: Status, profile: ProfileInfoView): ProfilePictureView = + new(result, delete) + result.status = status + result.profile = profile + result.setup + + proc upload*(self: ProfilePictureView, imageUrl: string, aX: int, aY: int, bX: int, bY: int): string {.slot.} = + var image = image_utils.formatImagePath(imageUrl) + # FIXME the function to get the file size is messed up + # var size = image_getFileSize(image) + # TODO find a way to i18n this (maybe send just a code and then QML sets the right string) + # return "Max file size is 20MB" + + try: + # TODO add crop tool for the image + let identityImage = self.status.profile.storeIdentityImage(self.profile.address, image, aX, aY, bX, bY) + self.profile.setIdentityImage(identityImage) + result = "" + except Exception as e: + error "Error storing identity image", msg=e.msg + result = "Error storing identity image: " & e.msg + + proc remove*(self: ProfilePictureView): string {.slot.} = + result = self.status.profile.deleteIdentityImage(self.profile.address) + if (result == ""): + self.profile.removeIdentityImage() diff --git a/src/app/profile/views/profile_settings.nim b/src/app/profile/views/profile_settings.nim new file mode 100644 index 0000000000..bc5e5d2def --- /dev/null +++ b/src/app/profile/views/profile_settings.nim @@ -0,0 +1,63 @@ +import NimQml, os +import chronicles +import profile_info +import ../../../status/profile/profile +import ../../../status/status +import ../../../status/types +import ../../../status/constants as accountConstants + +logScope: + topics = "profile-settings-view" + +const UNKNOWN_ACCOUNT = "unknownAccount" + +QtObject: + type ProfileSettingsView* = ref object of QObject + status*: Status + profile*: ProfileInfoView + + proc setup(self: ProfileSettingsView) = + self.QObject.setup + + proc delete*(self: ProfileSettingsView) = + self.QObject.delete + + proc newProfileSettingsView*(status: Status, profile: ProfileInfoView): ProfileSettingsView = + new(result, delete) + result.status = status + result.profile = profile + result.setup + + proc settingsFileChanged*(self: ProfileSettingsView) {.signal.} + + proc getSettingsFile(self: ProfileSettingsView): string {.slot.} = + let pubkey = + if (self.profile.pubKey == ""): + UNKNOWN_ACCOUNT + else: + self.profile.pubKey + + return os.joinPath(accountConstants.DATADIR, "qt", pubkey) + + QtProperty[string] settingsFile: + read = getSettingsFile + notify = settingsFileChanged + + proc getGlobalSettingsFile(self: ProfileSettingsView): string {.slot.} = + return os.joinPath(accountConstants.DATADIR, "qt", "global") + + proc globalSettingsFileChanged*(self: ProfileSettingsView) {.signal.} + + QtProperty[string] globalSettingsFile: + read = getGlobalSettingsFile + notify = globalSettingsFileChanged + + proc removeUnknownAccountSettings*(self: ProfileSettingsView) = + # Remove old 'unknownAccount' settings file if it was created + self.settingsFileChanged() + let unknownSettingsPath = os.joinPath(accountConstants.DATADIR, "qt", UNKNOWN_ACCOUNT) + if (not unknownSettingsPath.tryRemoveFile): + # Only fails if the file exists and an there was an error removing it + # More info: https://nim-lang.org/docs/os.html#tryRemoveFile%2Cstring + warn "Failed to remove unused settings file", file=unknownSettingsPath + \ No newline at end of file diff --git a/src/app/provider/view.nim b/src/app/provider/view.nim index 4a74f82bfa..1368eb96ed 100644 --- a/src/app/provider/view.nim +++ b/src/app/provider/view.nim @@ -28,9 +28,6 @@ QtObject: result.dappsAddress = "" result.setup - proc hasPermission*(self: Web3ProviderView, hostname: string, permission: string): bool {.slot.} = - result = self.status.permissions.hasPermission(hostname, permission.toPermission()) - proc disconnect*(self: Web3ProviderView) {.slot.} = self.status.permissions.revoke("web3".toPermission()) @@ -58,6 +55,9 @@ QtObject: notify = dappsAddressChanged write = setDappsAddress + proc hasPermission*(self: Web3ProviderView, hostname: string, permission: string): bool {.slot.} = + result = self.status.permissions.hasPermission(hostname, permission.toPermission()) + proc clearPermissions*(self: Web3ProviderView): string {.slot.} = self.status.permissions.clearPermissions() diff --git a/ui/app/AppLayouts/Profile/Sections/ChangeProfilePicModal.qml b/ui/app/AppLayouts/Profile/Sections/ChangeProfilePicModal.qml index b9972301b0..5de164710e 100644 --- a/ui/app/AppLayouts/Profile/Sections/ChangeProfilePicModal.qml +++ b/ui/app/AppLayouts/Profile/Sections/ChangeProfilePicModal.qml @@ -60,7 +60,7 @@ ModalPopup { selectedImage: popup.selectedImage ratio: "1:1" onCropFinished: { - uploadError = profileModel.uploadNewProfilePic(selectedImage, aX, aY, bX, bY) + uploadError = profileModel.picture.upload(selectedImage, aX, aY, bX, bY) } } } @@ -80,7 +80,7 @@ ModalPopup { anchors.rightMargin: Style.current.padding anchors.bottom: parent.bottom onClicked: { - uploadError = profileModel.deleteProfilePic() + uploadError = profileModel.picture.remove() } } diff --git a/ui/app/AppLayouts/Profile/Sections/MutedChatsModal.qml b/ui/app/AppLayouts/Profile/Sections/MutedChatsModal.qml index 66687835b0..f33ee8fad4 100644 --- a/ui/app/AppLayouts/Profile/Sections/MutedChatsModal.qml +++ b/ui/app/AppLayouts/Profile/Sections/MutedChatsModal.qml @@ -22,7 +22,7 @@ ModalPopup { visible: true anchors.left: parent.left anchors.right: parent.right - model: root.showMutedContacts ? profileModel.mutedContacts : profileModel.mutedChats + model: root.showMutedContacts ? profileModel.mutedChats.contacts : profileModel.mutedChats.chats delegate: Rectangle { id: channelItem property bool isHovered: false @@ -74,7 +74,7 @@ ModalPopup { //% "Unmute" text: qsTrId("unmute") onClicked: { - profileModel.unmuteChannel(model.id) + profileModel.mutedChats.unmuteChannel(model.id) } MouseArea { anchors.fill: parent diff --git a/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml b/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml index 7fbecf8dcc..8ee6ce5c89 100644 --- a/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml +++ b/ui/app/AppLayouts/Profile/Sections/NotificationsContainer.qml @@ -265,7 +265,7 @@ ScrollView { //% "Muted users" text: qsTrId("muted-users") //% "None" - currentValue: profileModel.mutedContacts.rowCount() > 0 ? profileModel.mutedContacts.rowCount() : qsTrId("none") + currentValue: profileModel.mutedChats.contacts.rowCount() > 0 ? profileModel.mutedChats.contacts.rowCount() : qsTrId("none") isSwitch: false onClicked: { const mutedChatsModal = notificationsContainer.mutedChatsModalComponent.createObject(notificationsContainer, { @@ -281,7 +281,7 @@ ScrollView { //% "Muted chats" text: qsTrId("muted-chats") //% "None" - currentValue: profileModel.mutedChats.rowCount() > 0 ? profileModel.mutedChats.rowCount() : qsTrId("none") + currentValue: profileModel.mutedChats.chats.rowCount() > 0 ? profileModel.mutedChats.chats.rowCount() : qsTrId("none") isSwitch: false onClicked: { const mutedChatsModal = notificationsContainer.mutedChatsModalComponent.createObject(notificationsContainer, { diff --git a/ui/app/AppMain.qml b/ui/app/AppMain.qml index 7872942f76..45c2671be4 100644 --- a/ui/app/AppMain.qml +++ b/ui/app/AppMain.qml @@ -317,7 +317,7 @@ StatusAppLayout { Settings { id: appSettings - fileName: profileModel.profileSettingsFile + fileName: profileModel.settings.settingsFile property var chatSplitView property var walletSplitView property var profileSplitView @@ -386,8 +386,8 @@ StatusAppLayout { } Connections { - target: profileModel - onProfileSettingsFileChanged: { + target: profileModel.settings + onSettingsFileChanged: { profileModel.changeLocale(globalSettings.locale) // Since https://github.com/status-im/status-desktop/commit/93668ff75 diff --git a/ui/main.qml b/ui/main.qml index b090424f63..b7865aad0e 100644 --- a/ui/main.qml +++ b/ui/main.qml @@ -28,7 +28,7 @@ StatusWindow { Settings { id: globalSettings category: "global" - fileName: profileModel.globalSettingsFile + fileName: profileModel.settings.globalSettingsFile property string locale: "en" property int theme: 2 }