Commit 0d6d94d1 authored by Andreas Traczyk's avatar Andreas Traczyk

accountcombobox: cleanup and simplify qml layer

- remove some faulty hover state management, excessive text metrics
  objects. Split the code up too and increase declarativeness.
- fix the rendering of account avatars in the dropdown list
- make the 'add account' item always visible
- make the popup modal with transparent overlay

Gitlab: #388
Change-Id: If0e5f95d1250ee77902c518469878bdb678c8b9d
parent 9aa98230
......@@ -137,5 +137,6 @@
<file>src/mainview/js/contactpickercreation.js</file>
<file>src/mainview/js/pluginhandlerpickercreation.js</file>
<file>src/mainview/components/FilterTabButton.qml</file>
<file>src/mainview/components/AccountItemDelegate.qml</file>
</qresource>
</RCC>
......@@ -63,12 +63,12 @@ AccountAdapter::getDeviceModel()
}
void
AccountAdapter::accountChanged(int index)
AccountAdapter::changeAccount(int row)
{
deselectConversation(); // Hack UI
auto accountList = lrcInstance_->accountModel().getAccountList();
if (accountList.size() > index) {
lrcInstance_->setSelectedAccountId(accountList.at(index));
if (accountList.size() > row) {
lrcInstance_->setSelectedAccountId(accountList.at(row));
}
}
......
......@@ -62,7 +62,7 @@ protected:
public:
// Change to account corresponding to combox box index.
Q_INVOKABLE void accountChanged(int index);
Q_INVOKABLE void changeAccount(int row);
// Create normal Jami account, SIP account and JAMS accounts.
Q_INVOKABLE void createJamiAccount(QString registeredName,
......
......@@ -114,7 +114,7 @@ Item {
anchors.fill: root
smooth: false
smooth: true
antialiasing: true
asynchronous: true
......@@ -146,7 +146,7 @@ Item {
anchors.fill: rootImage
smooth: false
smooth: true
antialiasing: true
asynchronous: true
......
......@@ -176,6 +176,8 @@ Item {
property real smartlistItemFontSize: 10.5
property real filterItemFontSize: smartlistItemFontSize
property real filterBadgeFontSize: 8.25
property real accountListItemHeight: 64
property real accountListAvatarSize: 40
property real maximumWidthSettingsView: 600
property real settingsHeaderpreferredHeight: 64
......
......@@ -278,18 +278,16 @@ Rectangle {
SplitView.fillHeight: true
color: JamiTheme.backgroundColor
// AccountComboBox is always visible
// AccountComboBox is not a ComboBox
AccountComboBox {
id: accountComboBox
anchors.top: mainViewSidePanelRect.top
width: mainViewSidePanelRect.width
height: 64
height: JamiTheme.accountListItemHeight
visible: (mainViewSidePanel.visible || settingsMenu.visible)
currentIndex: 0
Connections {
target: AccountAdapter
......@@ -416,7 +414,7 @@ Rectangle {
visible: false
onSettingsViewNeedToShowMainView: {
AccountAdapter.accountChanged(0)
AccountAdapter.changeAccount(0)
toggleSettingsView()
}
......
......@@ -28,10 +28,11 @@ import net.jami.Constants 1.0
import "../../commoncomponents"
ComboBox {
Label {
id: root
signal settingBtnClicked
property alias popup: comboBoxPopup
// Reset accountListModel.
function resetAccountListModel(accountId) {
......@@ -39,80 +40,140 @@ ComboBox {
accountListModel.reset()
}
Connections {
target: accountListModel
function togglePopup() {
if (root.popup.opened) {
root.popup.close()
} else {
root.popup.open()
}
}
function onModelReset() {
userImageRoot.updateImage(
AccountAdapter.currentAccountId,
accountListModel.data(
accountListModel.index(0, 0), AccountListModel.PictureUid))
userImageRoot.presenceStatus =
accountListModel.data(accountListModel.index(0, 0), AccountListModel.Status)
textMetricsUserAliasRoot.text = accountListModel.data(accountListModel.index(0,0),
AccountListModel.Alias)
textMetricsUsernameRoot.text = accountListModel.data(accountListModel.index(0,0),
AccountListModel.Username)
background: Rectangle {
id: background
implicitWidth: root.width
implicitHeight: root.height
color: root.popup.opened ?
Qt.lighter(JamiTheme.hoverColor, 1.0) :
mouseArea.containsMouse ?
Qt.lighter(JamiTheme.hoverColor, 1.05) :
JamiTheme.backgroundColor
Behavior on color {
ColorAnimation { duration: JamiTheme.fadeDuration }
}
// TODO: this can be removed when frameless window is implemented
Rectangle {
height: 1
anchors {
top: parent.top
left: parent.left
right: parent.right
}
color: JamiTheme.tabbarBorderColor
}
}
AvatarImage {
id: userImageRoot
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: togglePopup()
}
anchors.left: root.left
anchors.leftMargin: 16
anchors.verticalCenter: root.verticalCenter
AccountComboBoxPopup {
id: comboBoxPopup
width: 40
height: 40
Shortcut {
sequence: "Ctrl+J"
context: Qt.ApplicationShortcut
onActivated: togglePopup()
}
}
imageId: AccountAdapter.currentAccountId
Connections {
target: accountListModel
presenceStatus: accountListModel.data(accountListModel.index(0, 0),
AccountListModel.Status)
function onModelReset() {
avatar.updateImage(AccountAdapter.currentAccountId,
accountListModel.data(accountListModel.index(0, 0),
AccountListModel.PictureUid))
avatar.presenceStatus = accountListModel.data(accountListModel.index(0, 0),
AccountListModel.Status)
userAliasText.text = accountListModel.data(accountListModel.index(0,0),
AccountListModel.Alias)
usernameText.text = accountListModel.data(accountListModel.index(0,0),
AccountListModel.Username)
}
}
ColumnLayout {
anchors.left: userImageRoot.right
anchors.leftMargin: 16
anchors.top: background.top
RowLayout {
anchors.fill: parent
anchors.leftMargin: 15
anchors.rightMargin: 15
spacing: 10
AvatarImage {
id: avatar
height: root.height
Layout.preferredWidth: JamiTheme.accountListAvatarSize
Layout.preferredHeight: JamiTheme.accountListAvatarSize
Layout.alignment: Qt.AlignVCenter
spacing: 0
imageId: AccountAdapter.currentAccountId
presenceStatus: accountListModel.data(accountListModel.index(0, 0),
AccountListModel.Status)
}
RowLayout {
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.topMargin: textUsernameRoot.visible ? root.height / 2 - implicitHeight : 0
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 2
Text {
id: textUserAliasRoot
id: userAliasText
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
text: textMetricsUserAliasRoot.elidedText
text: accountListModel.data(accountListModel.index(0,0),
AccountListModel.Alias)
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.textColor
elide: Text.ElideRight
}
TextMetrics {
id: textMetricsUserAliasRoot
Text {
id: usernameText
font: textUserAliasRoot.font
elide: Text.ElideRight
elideWidth: root.width - userImageRoot.width - settingsButton.width
- arrowDropDown.width - qrCodeGenerateButton.width - 55
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
text: accountListModel.data(accountListModel.index(0,0), AccountListModel.Alias)
}
visible: text.length
text: accountListModel.data(accountListModel.index(0,0),
AccountListModel.Username)
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.faddedLastInteractionFontColor
elide: Text.ElideRight
}
}
Row {
id: controlRow
spacing: 10
Layout.preferredWidth: childrenRect.width
Layout.preferredHeight: parent.height
ResponsiveImage {
id: arrowDropDown
Layout.alignment: Qt.AlignRight
width: 24
height: 24
anchors.verticalCenter: parent.verticalCenter
layer {
enabled: true
......@@ -121,168 +182,55 @@ ComboBox {
}
}
source: "qrc:/images/icons/round-arrow_drop_down-24px.svg"
source: !root.popup.opened ?
"qrc:/images/icons/expand_more-24px.svg" :
"qrc:/images/icons/expand_less-24px.svg"
}
}
Text {
id: textUsernameRoot
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.bottomMargin: root.height / 2 - implicitHeight
PushButton {
id: shareButton
visible: textMetricsUsernameRoot.text.length
width: visible ? preferredSize : 0
height: visible ? preferredSize : 0
anchors.verticalCenter: parent.verticalCenter
text: textMetricsUsernameRoot.elidedText
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.faddedLastInteractionFontColor
visible: AccountAdapter.currentAccountType === Profile.Type.RING
toolTipText: JamiStrings.displayQRCode
TextMetrics {
id: textMetricsUsernameRoot
source: "qrc:/images/icons/share-24px.svg"
font: textUsernameRoot.font
elide: Text.ElideRight
elideWidth: root.width - userImageRoot.width - settingsButton.width
- qrCodeGenerateButton.width - 55
normalColor: JamiTheme.backgroundColor
imageColor: JamiTheme.textColor
text: accountListModel.data(accountListModel.index(0,0),
AccountListModel.Username)
}
}
}
background: Rectangle {
id: background
implicitWidth: root.width
implicitHeight: root.height
color: JamiTheme.backgroundColor
// TODO: this can be removed when frameless window is implemented
Rectangle {
height: 1
anchors {
top: parent.top
left: parent.left
right: parent.right
}
color: JamiTheme.tabbarBorderColor
}
states: [
State {
name: "open"; when: comboBoxPopup.opened
PropertyChanges {
target: background
color: Qt.lighter(JamiTheme.hoverColor, 1.0)
}
},
State {
name: "hovered"
PropertyChanges {
target: background
color: Qt.lighter(JamiTheme.hoverColor, 1.05)
onClicked: {
if (visible)
qrDialog.open()
}
},
State {
name: "normal"
PropertyChanges {
target: background
color: JamiTheme.backgroundColor
}
}
]
transitions: [
Transition {
to: "hovered"; reversible: true
ColorAnimation { duration: JamiTheme.fadeDuration }
}
]
}
MouseArea {
id: comboBoxRootMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: {
if (comboBoxPopup.opened) {
root.popup.close()
} else {
root.popup.open()
}
}
onEntered: background.state = "hovered"
onExited: {
if (!comboBoxPopup.opened)
background.state = "normal"
}
}
Row {
spacing: 10
anchors.right: root.right
anchors.rightMargin: 10
anchors.verticalCenter: root.verticalCenter
PushButton {
id: qrCodeGenerateButton
width: visible ? preferredSize : 0
height: visible ? preferredSize : 0
visible: AccountAdapter.currentAccountType === Profile.Type.RING
toolTipText: JamiStrings.displayQRCode
source: "qrc:/images/icons/share-24px.svg"
normalColor: JamiTheme.backgroundColor
imageColor: JamiTheme.textColor
onClicked: {
if (visible)
qrDialog.open()
}
}
PushButton {
id: settingsButton
PushButton {
id: settingsButton
source: !mainView.inSettingsView ?
"qrc:/images/icons/settings-24px.svg" :
"qrc:/images/icons/round-close-24px.svg"
anchors.verticalCenter: parent.verticalCenter
source: !mainView.inSettingsView ?
"qrc:/images/icons/settings-24px.svg" :
"qrc:/images/icons/round-close-24px.svg"
normalColor: JamiTheme.backgroundColor
imageColor: JamiTheme.textColor
toolTipText: !mainView.inSettingsView ?
JamiStrings.openSettings :
JamiStrings.closeSettings
normalColor: JamiTheme.backgroundColor
imageColor: JamiTheme.textColor
toolTipText: !mainView.inSettingsView ?
JamiStrings.openSettings :
JamiStrings.closeSettings
onClicked: {
settingBtnClicked()
background.state = "normal"
onClicked: {
settingBtnClicked()
background.state = "normal"
}
}
}
}
indicator: null
// Overwrite the combo box pop up to add footer (for add accounts).
popup: AccountComboBoxPopup {
id: comboBoxPopup
Shortcut {
sequence: "Ctrl+J"
context: Qt.ApplicationShortcut
onActivated: comboBoxPopup.visible ?
comboBoxPopup.close() :
comboBoxPopup.open()
}
}
Shortcut {
sequence: "Ctrl+,"
context: Qt.ApplicationShortcut
......
......@@ -30,167 +30,82 @@ import "../../commoncomponents"
Popup {
id: root
property bool toggleUpdatePopupHeight: false
y: accountComboBox.height - 1
implicitWidth: accountComboBox.width - 1
// Hack - limite the accounts that can be shown.
y: parent.height
implicitWidth: parent.width
// limit the number of accounts shown at once
implicitHeight: {
root.visible
return Math.min(accountComboBox.height *
return Math.min(JamiTheme.accountListItemHeight *
Math.min(5, accountListModel.rowCount() + 1),
mainViewSidePanelRect.height)
}
padding: 0
modal: true
Overlay.modal: Rectangle {
color: "transparent"
}
contentItem: ListView {
id: comboBoxPopupListView
// In list view, index is an interger.
clip: true
model: accountListModel
implicitHeight: contentHeight
delegate: Rectangle {
id: delegate
width: root.width
height: accountComboBox.height
color: JamiTheme.backgroundColor
AvatarImage {
id: userImage
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
contentItem: ColumnLayout {
spacing: 0
ListView {
id: listView
width: 40
height: 40
Layout.fillHeight: true
Layout.preferredWidth: parent.width
presenceStatus: Status
clip: true
Component.onCompleted: {
return updateImage(
accountListModel.data(
accountListModel.index(index, 0), AccountListModel.ID),
accountListModel.data(
accountListModel.index(index, 0), AccountListModel.PictureUid))
// TODO: this should use proxy model or custom filter out the
// current account
model: accountListModel
delegate: AccountItemDelegate {
height: JamiTheme.accountListItemHeight
width: root.width
onClicked: {
root.close()
AccountAdapter.changeAccount(index)
}
}
ColumnLayout {
anchors.left: userImage.right
anchors.leftMargin: 16
anchors.top: delegate.top
height: delegate.height
spacing: 0
Text {
id: textUserAliasPopup
ScrollIndicator.vertical: ScrollIndicator {}
}
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.topMargin: textUsernamePopup.visible ?
delegate.height / 2 - implicitHeight : 0
// fake footer item as workaround for Qt 5.15 bug
// https://bugreports.qt.io/browse/QTBUG-85302
// don't use the clip trick and footer item overlay
// explained here https://stackoverflow.com/a/64625149
// as it causes other complexities in handling the drop shadow
ItemDelegate {
id: footerItem
text: textMetricsUserAliasPopup.elidedText
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.textColor
Layout.preferredHeight: JamiTheme.accountListItemHeight
Layout.preferredWidth: parent.width
TextMetrics {
id: textMetricsUserAliasPopup
elide: Text.ElideRight
elideWidth: delegate.width - userImage.width - 80