mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-09-08 19:13:28 +02:00
settingssidepanel: use ListView
Change-Id: I034edd72522badee2adb1ca558518854938b6deb
This commit is contained in:
parent
58a96d14b7
commit
4d8b006c34
3 changed files with 218 additions and 226 deletions
|
@ -26,13 +26,13 @@ QtObject {
|
||||||
|
|
||||||
// The number of views loaded (`views` is only resized).
|
// The number of views loaded (`views` is only resized).
|
||||||
function viewCount() {
|
function viewCount() {
|
||||||
return Object.keys(views).length;
|
return Object.keys(views).length
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy all views.
|
// Destroy all views.
|
||||||
function destroyAllViews() {
|
function destroyAllViews() {
|
||||||
for (var path in views) {
|
for (var path in views) {
|
||||||
destroyView(path);
|
destroyView(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,50 +40,50 @@ QtObject {
|
||||||
if (views.hasOwnProperty(path)) {
|
if (views.hasOwnProperty(path)) {
|
||||||
// an instance of <path> already exists
|
// an instance of <path> already exists
|
||||||
if (cb !== null) {
|
if (cb !== null) {
|
||||||
cb(views[path]);
|
cb(views[path])
|
||||||
}
|
}
|
||||||
return views[path];
|
return views[path]
|
||||||
}
|
}
|
||||||
const component = Qt.createComponent(Qt.resolvedUrl(path));
|
const component = Qt.createComponent(Qt.resolvedUrl(path))
|
||||||
if (component.status === Component.Ready) {
|
if (component.status === Component.Ready) {
|
||||||
const obj = component.createObject(parent, props);
|
const obj = component.createObject(parent, props)
|
||||||
if (obj === null) {
|
if (obj === null) {
|
||||||
print("error creating object");
|
print("error creating object")
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
views[path] = obj;
|
views[path] = obj
|
||||||
// Set the view name to the object name if it has one.
|
// Set the view name to the object name if it has one.
|
||||||
const viewName = obj.objectName.toString() !== '' ? obj.objectName : path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "");
|
const viewName = obj.objectName.toString() !== '' ? obj.objectName : path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
|
||||||
viewPaths[viewName] = path;
|
viewPaths[viewName] = path
|
||||||
if (cb !== null) {
|
if (cb !== null) {
|
||||||
cb(obj);
|
cb(obj)
|
||||||
}
|
}
|
||||||
return views[path];
|
return views[path]
|
||||||
}
|
}
|
||||||
print("error creating component", path);
|
print("error creating component", path)
|
||||||
console.error(component.errorString());
|
console.error(component.errorString())
|
||||||
Qt.exit(1);
|
Qt.exit(1)
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function destroyView(path) {
|
function destroyView(path) {
|
||||||
// The view may already have been destroyed.
|
// The view may already have been destroyed.
|
||||||
if (!views.hasOwnProperty(path)) {
|
if (!views.hasOwnProperty(path)) {
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
views[path].destroy();
|
views[path].destroy()
|
||||||
delete views[path];
|
delete views[path]
|
||||||
// Remove the view name from the viewPaths map.
|
// Remove the view name from the viewPaths map.
|
||||||
for (var viewName in viewPaths) {
|
for (var viewName in viewPaths) {
|
||||||
if (viewPaths[viewName] === path) {
|
if (viewPaths[viewName] === path) {
|
||||||
delete viewPaths[viewName];
|
delete viewPaths[viewName]
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function getView(viewName) {
|
function getView(viewName) {
|
||||||
return views[viewPaths[viewName]] || null;
|
return views[viewPaths[viewName]] || null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,47 +32,14 @@ SidePanelBase {
|
||||||
|
|
||||||
color: JamiTheme.backgroundColor
|
color: JamiTheme.backgroundColor
|
||||||
property int currentIndex
|
property int currentIndex
|
||||||
|
property bool isSinglePane
|
||||||
function createChild() {
|
|
||||||
if (page.menu === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
page.menu.createChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
Page {
|
|
||||||
id: page
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
background: null
|
|
||||||
|
|
||||||
header: AccountComboBox {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind to requests for a settings page to be selected via shorcut.
|
|
||||||
Connections {
|
|
||||||
target: JamiQmlUtils
|
|
||||||
function onSettingsPageRequested(index) {
|
|
||||||
viewCoordinator.present("SettingsView");
|
|
||||||
root.indexSelected(index);
|
|
||||||
root.currentIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property var menu: undefined
|
|
||||||
|
|
||||||
Flickable {
|
|
||||||
id: flick
|
|
||||||
width: root.width
|
|
||||||
height: childrenRect.height
|
|
||||||
clip: true
|
|
||||||
contentHeight: col.implicitHeight
|
|
||||||
|
|
||||||
function getHeaders() {
|
function getHeaders() {
|
||||||
return [{
|
return [{
|
||||||
"title": JamiStrings.accountSettingsMenuTitle,
|
"title": JamiStrings.accountSettingsMenuTitle,
|
||||||
"icon": JamiResources.account_24dp_svg,
|
"icon": JamiResources.account_24dp_svg,
|
||||||
|
"first": 0,
|
||||||
|
"last": 4,
|
||||||
"children": [{
|
"children": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"title": JamiStrings.manageAccountSettingsTitle
|
"title": JamiStrings.manageAccountSettingsTitle
|
||||||
|
@ -82,7 +49,7 @@ SidePanelBase {
|
||||||
}, {
|
}, {
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"title": JamiStrings.linkedDevicesSettingsTitle,
|
"title": JamiStrings.linkedDevicesSettingsTitle,
|
||||||
"visible": "isJamiAccount"
|
"visible": CurrentAccount.type !== Profile.Type.SIP
|
||||||
}, {
|
}, {
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"title": JamiStrings.callSettingsTitle
|
"title": JamiStrings.callSettingsTitle
|
||||||
|
@ -93,6 +60,8 @@ SidePanelBase {
|
||||||
}, {
|
}, {
|
||||||
"title": JamiStrings.generalSettingsTitle,
|
"title": JamiStrings.generalSettingsTitle,
|
||||||
"icon": JamiResources.gear_black_24dp_svg,
|
"icon": JamiResources.gear_black_24dp_svg,
|
||||||
|
"first": 5,
|
||||||
|
"last": 11,
|
||||||
"children": [{
|
"children": [{
|
||||||
"id": 5,
|
"id": 5,
|
||||||
"title": JamiStrings.system
|
"title": JamiStrings.system
|
||||||
|
@ -114,11 +83,13 @@ SidePanelBase {
|
||||||
}, {
|
}, {
|
||||||
"id": 11,
|
"id": 11,
|
||||||
"title": JamiStrings.updatesTitle,
|
"title": JamiStrings.updatesTitle,
|
||||||
"visible": "isUpdatable"
|
"visible": UpdateManager.isUpdaterEnabled()
|
||||||
}]
|
}]
|
||||||
}, {
|
}, {
|
||||||
"title": JamiStrings.audioVideoSettingsTitle,
|
"title": JamiStrings.audioVideoSettingsTitle,
|
||||||
"icon": JamiResources.media_black_24dp_svg,
|
"icon": JamiResources.media_black_24dp_svg,
|
||||||
|
"first": 12,
|
||||||
|
"last": 14,
|
||||||
"children": [{
|
"children": [{
|
||||||
"id": 12,
|
"id": 12,
|
||||||
"title": JamiStrings.audio
|
"title": JamiStrings.audio
|
||||||
|
@ -132,6 +103,8 @@ SidePanelBase {
|
||||||
}, {
|
}, {
|
||||||
"title": JamiStrings.pluginSettingsTitle,
|
"title": JamiStrings.pluginSettingsTitle,
|
||||||
"icon": JamiResources.plugins_24dp_svg,
|
"icon": JamiResources.plugins_24dp_svg,
|
||||||
|
"first": 15,
|
||||||
|
"last": 15,
|
||||||
"children": [{
|
"children": [{
|
||||||
"id": 15,
|
"id": 15,
|
||||||
"title": JamiStrings.pluginSettingsTitle
|
"title": JamiStrings.pluginSettingsTitle
|
||||||
|
@ -139,127 +112,138 @@ SidePanelBase {
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
function updateModel() {
|
||||||
|
if (visible) {
|
||||||
|
listView.model = {}
|
||||||
|
listView.model = getHeaders()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: UtilsAdapter
|
||||||
|
|
||||||
|
function onChangeLanguage() {
|
||||||
|
updateModel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to requests for a settings page to be selected via shorcut.
|
||||||
|
Connections {
|
||||||
|
target: JamiQmlUtils
|
||||||
|
function onSettingsPageRequested(index) {
|
||||||
|
viewCoordinator.present("SettingsView")
|
||||||
|
root.indexSelected(index)
|
||||||
|
root.currentIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onIsSinglePaneChanged: {
|
||||||
|
if (visible && !isSinglePane)
|
||||||
|
select(root.currentIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
function open(index) {
|
||||||
|
indexSelected(index)
|
||||||
|
root.currentIndex = index
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(index) {
|
||||||
|
if (!root.isSinglePane)
|
||||||
|
indexSelected(index)
|
||||||
|
root.currentIndex = index
|
||||||
|
}
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: page
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
background: null
|
||||||
|
|
||||||
|
header: AccountComboBox {
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: listView
|
||||||
|
width: page.width
|
||||||
|
height: page.height
|
||||||
|
clip: true
|
||||||
|
contentHeight: contentItem.childrenRect.height
|
||||||
|
|
||||||
|
model: getHeaders()
|
||||||
|
delegate: ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
anchors.left: parent.left
|
width: page.width
|
||||||
Component.onCompleted: {
|
property bool isChildSelected: root.currentIndex >= modelData.first && root.currentIndex <= modelData.last
|
||||||
page.menu = clv.createObject(this, {
|
|
||||||
"base": flick.getHeaders()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Component {
|
|
||||||
id: clv
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
id: repeater
|
|
||||||
|
|
||||||
property var base: ({})
|
|
||||||
property var selected: null
|
|
||||||
model: Object.keys(base)
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
function createChild() {
|
|
||||||
itemAt(0).children[0].createChild();
|
|
||||||
root.currentIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: clvButtons
|
|
||||||
spacing: 0
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
PushButton {
|
PushButton {
|
||||||
id: btn
|
buttonText: modelData.title
|
||||||
property var sprite: null
|
|
||||||
property bool showFocusMargin: true
|
|
||||||
|
|
||||||
property var isChildren: {
|
|
||||||
var ob = base[modelData];
|
|
||||||
var c = ob["children"];
|
|
||||||
return c === undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateVisibility() {
|
|
||||||
var currentVisibility = visible;
|
|
||||||
var ob = base[modelData];
|
|
||||||
var c = ob["visible"];
|
|
||||||
if (c === undefined)
|
|
||||||
return true;
|
|
||||||
var res = false;
|
|
||||||
if (c === "isUpdatable") {
|
|
||||||
res = UpdateManager.isUpdaterEnabled();
|
|
||||||
} else if (c === "isJamiAccount") {
|
|
||||||
res = CurrentAccount.type !== Profile.Type.SIP;
|
|
||||||
} else {
|
|
||||||
console.warn("Visibility condition not managed");
|
|
||||||
}
|
|
||||||
if (currentVisibility !== res && root.currentIndex === ob["id"]) {
|
|
||||||
// If a menu disappears, go to the first index
|
|
||||||
root.currentIndex = 0;
|
|
||||||
root.indexSelected(0);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createChild() {
|
|
||||||
var ob = base[modelData];
|
|
||||||
if (sprite === null) {
|
|
||||||
//deselect the current selection and collapse menu
|
|
||||||
if (repeater.selected)
|
|
||||||
repeater.selected.destroy();
|
|
||||||
var c = ob["children"];
|
|
||||||
if (c !== undefined) {
|
|
||||||
sprite = clv.createObject(parent, {
|
|
||||||
"base": c
|
|
||||||
});
|
|
||||||
repeater.selected = sprite;
|
|
||||||
indexSelected(c[0]["id"]);
|
|
||||||
root.currentIndex = c[0]["id"];
|
|
||||||
} else {
|
|
||||||
indexSelected(ob["id"]);
|
|
||||||
root.currentIndex = ob["id"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
visible: updateVisibility()
|
|
||||||
|
|
||||||
property bool isOpen: !isChildren && sprite != null
|
|
||||||
property bool isChildOpen: isChildren && (base[modelData]["id"] === root.currentIndex)
|
|
||||||
|
|
||||||
alignement: Text.AlignLeft
|
|
||||||
Layout.preferredWidth: root.width - (isChildren ? 28 : 0)
|
|
||||||
Layout.leftMargin: isChildren ? 28 : 0
|
|
||||||
preferredLeftMargin: isChildren ? 47 : 25
|
|
||||||
|
|
||||||
imageContainerWidth: !isChildren ? 30 : 0
|
|
||||||
height: isChildren ? JamiTheme.settingsMenuChildrenButtonHeight : JamiTheme.settingsMenuHeaderButtonHeight
|
|
||||||
|
|
||||||
circled: false
|
circled: false
|
||||||
radius: 0
|
radius: 0
|
||||||
|
|
||||||
buttonText: {
|
alignement: Text.AlignLeft
|
||||||
return base[modelData]["title"];
|
Layout.preferredWidth: parent.width
|
||||||
}
|
Layout.leftMargin: 0
|
||||||
|
preferredLeftMargin: 25
|
||||||
|
|
||||||
buttonTextFont.pixelSize: !isChildren ? JamiTheme.settingsDescriptionPixelSize : JamiTheme.settingMenuPixelSize
|
imageContainerWidth: 30
|
||||||
buttonTextColor: isOpen || isChildOpen ? JamiTheme.tintedBlue : JamiTheme.primaryForegroundColor
|
height: JamiTheme.settingsMenuHeaderButtonHeight
|
||||||
buttonTextFont.weight: isOpen || isChildOpen ? Font.Medium : Font.Normal
|
|
||||||
|
buttonTextFont.pixelSize: JamiTheme.settingsDescriptionPixelSize
|
||||||
|
buttonTextColor: isChildSelected ? JamiTheme.tintedBlue : JamiTheme.primaryForegroundColor
|
||||||
|
buttonTextFont.weight: isChildSelected ? Font.Medium : Font.Normal
|
||||||
buttonTextEnableElide: true
|
buttonTextEnableElide: true
|
||||||
|
|
||||||
normalColor: isOpen ? JamiTheme.smartListSelectedColor : "transparent"
|
normalColor: isChildSelected ? JamiTheme.smartListSelectedColor : "transparent"
|
||||||
hoveredColor: JamiTheme.smartListHoveredColor
|
hoveredColor: JamiTheme.smartListHoveredColor
|
||||||
imageColor: !isChildren ? JamiTheme.tintedBlue : null
|
imageColor: JamiTheme.tintedBlue
|
||||||
|
|
||||||
source: {
|
source: modelData.icon
|
||||||
if (!isChildren)
|
|
||||||
return base[modelData]["icon"];
|
onClicked: select(modelData.first)
|
||||||
else
|
Keys.onPressed: function (keyEvent) {
|
||||||
return "";
|
if (keyEvent.key === Qt.Key_Enter || keyEvent.key === Qt.Key_Return) {
|
||||||
|
clicked();
|
||||||
|
keyEvent.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: createChild()
|
ListView {
|
||||||
|
id: childListView
|
||||||
|
width: parent.width
|
||||||
|
height: childrenRect.height
|
||||||
|
clip: true
|
||||||
|
visible: isChildSelected
|
||||||
|
|
||||||
|
model: modelData.children
|
||||||
|
delegate: ColumnLayout {
|
||||||
|
id: childCol
|
||||||
|
width: childListView.width
|
||||||
|
property bool isSelected: root.currentIndex == modelData.id
|
||||||
|
PushButton {
|
||||||
|
buttonText: modelData.title
|
||||||
|
circled: false
|
||||||
|
radius: 0
|
||||||
|
visible: modelData.visible ? modelData.visible : true
|
||||||
|
|
||||||
|
alignement: Text.AlignLeft
|
||||||
|
Layout.preferredWidth: parent.width - 28
|
||||||
|
Layout.leftMargin: 28
|
||||||
|
preferredLeftMargin: 47
|
||||||
|
|
||||||
|
imageContainerWidth: 0
|
||||||
|
height: JamiTheme.settingsMenuChildrenButtonHeight
|
||||||
|
|
||||||
|
buttonTextFont.pixelSize: JamiTheme.settingMenuPixelSize
|
||||||
|
buttonTextColor: isSelected ? JamiTheme.tintedBlue : JamiTheme.primaryForegroundColor
|
||||||
|
buttonTextFont.weight: isSelected ? Font.Medium : Font.Normal
|
||||||
|
buttonTextEnableElide: true
|
||||||
|
|
||||||
|
normalColor: "transparent"
|
||||||
|
hoveredColor: JamiTheme.smartListHoveredColor
|
||||||
|
|
||||||
|
onClicked: open(modelData.id)
|
||||||
|
|
||||||
Keys.onPressed: function (keyEvent) {
|
Keys.onPressed: function (keyEvent) {
|
||||||
if (keyEvent.key === Qt.Key_Enter || keyEvent.key === Qt.Key_Return) {
|
if (keyEvent.key === Qt.Key_Enter || keyEvent.key === Qt.Key_Return) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import "../mainview/js/contactpickercreation.js" as ContactPickerCreation
|
||||||
ListSelectionView {
|
ListSelectionView {
|
||||||
id: viewNode
|
id: viewNode
|
||||||
objectName: "SettingsView"
|
objectName: "SettingsView"
|
||||||
|
selectionFallback: true
|
||||||
|
|
||||||
// A map of view names to file paths for QML files that define each view.
|
// A map of view names to file paths for QML files that define each view.
|
||||||
property variant resources: {
|
property variant resources: {
|
||||||
|
@ -57,6 +58,18 @@ ListSelectionView {
|
||||||
|
|
||||||
leftPaneItem: viewCoordinator.getView("SettingsSidePanel")
|
leftPaneItem: viewCoordinator.getView("SettingsSidePanel")
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
leftPaneItem.updateModel()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: viewNode
|
||||||
|
|
||||||
|
function onIsSinglePaneChanged() {
|
||||||
|
leftPaneItem.isSinglePane = viewNode.isSinglePane
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onDismissed: {
|
onDismissed: {
|
||||||
// Trigger an update to messages if needed.
|
// Trigger an update to messages if needed.
|
||||||
// Currently needed when changing the show link preview setting.
|
// Currently needed when changing the show link preview setting.
|
||||||
|
@ -68,10 +81,6 @@ ListSelectionView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
leftPaneItem.createChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
property int selectedMenu: index
|
property int selectedMenu: index
|
||||||
|
|
||||||
rightPaneItem: StackView {
|
rightPaneItem: StackView {
|
||||||
|
@ -83,8 +92,7 @@ ListSelectionView {
|
||||||
|
|
||||||
signal stopBooth
|
signal stopBooth
|
||||||
|
|
||||||
initialItem: ManageAccountPage {
|
initialItem: ManageAccountPage {}
|
||||||
}
|
|
||||||
|
|
||||||
onCurrentIndexChanged: {
|
onCurrentIndexChanged: {
|
||||||
switch (currentIndex) {
|
switch (currentIndex) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue