diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml
index ca7226a6ab..579b4e7fd6 100644
--- a/interface/resources/qml/desktop/Desktop.qml
+++ b/interface/resources/qml/desktop/Desktop.qml
@@ -50,7 +50,22 @@ FocusScope {
property bool desktopRoot: true
// The VR version of the primary menu
- property var rootMenu: Menu { objectName: "rootMenu" }
+ property var rootMenu: Menu {
+ objectName: "rootMenu"
+
+ // for some reasons it is not possible to use just '({})' here as it gets empty when passed to TableRoot/DesktopRoot
+ property var exclusionGroupsByMenuItem : ListModel {}
+
+ function addExclusionGroup(menuItem, exclusionGroup)
+ {
+ exclusionGroupsByMenuItem.append(
+ {
+ 'menuItem' : menuItem.toString(),
+ 'exclusionGroup' : exclusionGroup.toString()
+ }
+ );
+ }
+ }
// FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX/AMD
// because shaders are 4.2, and do not include #version declarations.
diff --git a/interface/resources/qml/hifi/tablet/TabletMenuItem.qml b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml
index 25f672e7a9..71e59e0d01 100644
--- a/interface/resources/qml/hifi/tablet/TabletMenuItem.qml
+++ b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml
@@ -26,24 +26,48 @@ Item {
visible: source.visible
width: parent.width
- CheckBox {
+ Item {
id: check
- // FIXME: Should use radio buttons if source.exclusiveGroup.
+
anchors {
left: parent.left
leftMargin: hifi.dimensions.menuPadding.x + 15
verticalCenter: label.verticalCenter
}
- width: 20
- visible: source.visible && source.type === 1 && source.checkable
- checked: setChecked()
- function setChecked() {
- if (!source || source.type !== 1 || !source.checkable) {
- return false;
+
+ width: checkbox.visible ? checkbox.width : radiobutton.width
+ height: checkbox.visible ? checkbox.height : radiobutton.height
+
+ CheckBox {
+ id: checkbox
+ // FIXME: Should use radio buttons if source.exclusiveGroup.
+ width: 20
+ visible: source.visible && source.type === 1 && source.checkable && !source.exclusiveGroup
+ checked: setChecked()
+ function setChecked() {
+ if (!source || source.type !== 1 || !source.checkable) {
+ return false;
+ }
+ // FIXME this works for native QML menus but I don't think it will
+ // for proxied QML menus
+ return source.checked;
+ }
+ }
+
+ RadioButton {
+ id: radiobutton
+ // FIXME: Should use radio buttons if source.exclusiveGroup.
+ width: 20
+ visible: source.visible && source.type === 1 && source.checkable && source.exclusiveGroup
+ checked: setChecked()
+ function setChecked() {
+ if (!source || source.type !== 1 || !source.checkable) {
+ return false;
+ }
+ // FIXME this works for native QML menus but I don't think it will
+ // for proxied QML menus
+ return source.checked;
}
- // FIXME this works for native QML menus but I don't think it will
- // for proxied QML menus
- return source.checked;
}
}
diff --git a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml
index 9076cd6c48..e7eefbc5e7 100644
--- a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml
+++ b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml
@@ -64,8 +64,10 @@ Item {
d.pop();
}
- function toModel(items) {
+ function toModel(items, newMenu) {
var result = modelMaker.createObject(tabletMenu);
+ var exclusionGroups = {};
+
for (var i = 0; i < items.length; ++i) {
var item = items[i];
if (!item.visible) continue;
@@ -77,6 +79,28 @@ Item {
if (item.text !== "Users Online") {
result.append({"name": item.text, "item": item})
}
+
+ for(var j = 0; j < tabletMenu.rootMenu.exclusionGroupsByMenuItem.count; ++j)
+ {
+ var entry = tabletMenu.rootMenu.exclusionGroupsByMenuItem.get(j);
+ if(entry.menuItem == item.toString())
+ {
+ var exclusionGroupId = entry.exclusionGroup;
+ console.debug('item exclusionGroupId: ', exclusionGroupId)
+
+ if(!exclusionGroups[exclusionGroupId])
+ {
+ exclusionGroups[exclusionGroupId] = exclusiveGroupMaker.createObject(newMenu);
+ console.debug('new exclusion group created: ', exclusionGroups[exclusionGroupId])
+ }
+
+ var exclusionGroup = exclusionGroups[exclusionGroupId];
+
+ item.exclusiveGroup = exclusionGroup
+ console.debug('item.exclusiveGroup: ', item.exclusiveGroup)
+ }
+ }
+
break;
case MenuItemType.Separator:
result.append({"name": "", "item": item})
@@ -133,10 +157,21 @@ Item {
}
}
+ property Component exclusiveGroupMaker: Component {
+ ExclusiveGroup {
+ }
+ }
+
function buildMenu(items) {
- var model = toModel(items);
// Menus must be childed to desktop for Z-ordering
- var newMenu = menuViewMaker.createObject(tabletMenu, { model: model, isSubMenu: topMenu !== null });
+ var newMenu = menuViewMaker.createObject(tabletMenu);
+ console.debug('newMenu created: ', newMenu)
+
+ var model = toModel(items, newMenu);
+
+ newMenu.model = model;
+ newMenu.isSubMenu = topMenu !== null;
+
pushMenu(newMenu);
return newMenu;
}
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 2c4a515736..17cf782b70 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -56,6 +56,8 @@ Menu* Menu::getInstance() {
return dynamic_cast