Skip to content

Commit f9020b2

Browse files
committed
Add components for menu bar
1 parent 2e77042 commit f9020b2

File tree

5 files changed

+218
-0
lines changed

5 files changed

+218
-0
lines changed

src/uicomponents/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ set(MODULE_QML_FILES
44
CustomButton.qml
55
CustomToolButton.qml
66
HoverToolTip.qml
7+
CustomMenuBar.qml
8+
CustomMenu.qml
9+
CustomMenuItem.qml
10+
CustomMenuSeparator.qml
711
)
812
set(MODULE_SRC
913
menubarmodel.cpp

src/uicomponents/CustomMenu.qml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
import QtQuick
4+
import QtQuick.Controls
5+
6+
Menu {
7+
property bool isSubMenu: false
8+
9+
function updateWidth() {
10+
let maxWidth = 0;
11+
12+
for (let i = 0; i < count; i++)
13+
maxWidth = Math.max(maxWidth, itemAt(i).implicitWidth);
14+
15+
background.implicitWidth = maxWidth;
16+
}
17+
18+
function toggle() {
19+
if (visible)
20+
close();
21+
else
22+
open();
23+
}
24+
25+
x: isSubMenu ? parent.width : 0
26+
y: isSubMenu ? 0 : parent.height
27+
font.pointSize: 10
28+
background: Rectangle {
29+
// Load colors from theme
30+
color: /*ThemeEngine.bgColor*/ Material.background
31+
border.color: /*ThemeEngine.borderColor*/ Qt.rgba(1, 1, 1, 0.25)
32+
radius: 10
33+
implicitHeight: 40
34+
}
35+
delegate: CustomMenuItem {}
36+
onAboutToShow: updateWidth()
37+
}

src/uicomponents/CustomMenuBar.qml

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
import QtQuick
4+
import QtQuick.Controls
5+
import ScratchCPP.UiComponents
6+
7+
MenuBar {
8+
id: root
9+
property MenuBarModel model: MenuBarModel {}
10+
11+
QtObject {
12+
id: priv
13+
readonly property alias menus: root.model.menus
14+
readonly property var menuObjects: []
15+
}
16+
17+
Connections {
18+
target: root.model
19+
20+
function onMenusChanged() { reload() }
21+
}
22+
23+
function getComponentString(typeName) {
24+
var imports = "import QtQuick; import QtQuick.Controls; import Qt.labs.platform as Platform;"
25+
return imports + " " + typeName + " {}";
26+
}
27+
28+
function createMenuBar(parentItem, menuType, menuItemType, menuSeparatorType) {
29+
for(var i = 0; i < priv.menus.length; i++) {
30+
var menuParent = parentItem;
31+
var menu = Qt.createQmlObject(getComponentString(menuType), menuParent);
32+
menu.title = priv.menus[i].title;
33+
priv.menuObjects[priv.menuObjects.length] = menu;
34+
parentItem.addMenu(menu);
35+
createMenu(menu, priv.menus[i].items, menuType, menuItemType, menuSeparatorType);
36+
}
37+
}
38+
39+
function createMenu(parentItem, itemList, menuType, menuItemType, menuSeparatorType) {
40+
for (let i = 0; i < itemList.length; i++) {
41+
let itemData = itemList[i];
42+
let itemComponent;
43+
let item;
44+
let overrideAddItem = false;
45+
46+
if (itemData.isSeparator) {
47+
item = Qt.createQmlObject(getComponentString(menuSeparatorType), parentItem);
48+
} else if (itemData.submenu === null) {
49+
item = Qt.createQmlObject(getComponentString(menuItemType), parentItem);
50+
item.text = itemData.text;
51+
item.checkable = itemData.checkable;
52+
item.checked = itemData.checked;
53+
item.enabled = itemData.enabled;
54+
item.onCheckedChanged.connect(function() { itemData.checked = item.checked; });
55+
itemData.onCheckedChanged.connect(function() { item.checked = itemData.checked; });
56+
itemData.onEnabledChanged.connect(function() { item.enabled = itemData.enabled; });
57+
58+
if (typeof itemData.onClicked != "undefined")
59+
item.onTriggered.connect(function() { itemData.onClicked() });
60+
} else {
61+
item = Qt.createQmlObject(getComponentString(menuType), parentItem)
62+
item.title = itemData.text;
63+
parentItem.addMenu(item);
64+
createMenu(item, itemData.submenu.items, menuType, menuItemType, menuSeparatorType);
65+
overrideAddItem = true;
66+
}
67+
68+
if (!overrideAddItem)
69+
parentItem.addItem(item);
70+
}
71+
}
72+
73+
background: Rectangle {
74+
color: Material.backgroundColor // Load the color from the theme
75+
}
76+
77+
delegate: MenuBarItem {
78+
id: menuBarItem
79+
80+
function replaceText(txt)
81+
{
82+
var index = txt.indexOf("&");
83+
84+
if (index >= 0)
85+
txt = txt.replace(txt.substr(index, 2), ("<u>" + txt.substr(index + 1, 1) +"</u>"));
86+
87+
return txt;
88+
}
89+
90+
implicitHeight: contentItem.implicitHeight + topPadding + bottomPadding
91+
leftPadding: 10
92+
rightPadding: 10
93+
topPadding: 5
94+
bottomPadding: 5
95+
font.pointSize: 10
96+
Material.background: Qt.rgba(0, 0, 0, 0)
97+
Material.foreground: Material.theme == Material.Dark ? "white" : "black"
98+
contentItem: Label {
99+
text: replaceText(menuBarItem.text)
100+
font: menuBarItem.font
101+
}
102+
onDoubleClicked: clicked()
103+
}
104+
105+
function reload() {
106+
/*if(nativeMenuBarEnabled)
107+
{
108+
root.visible = false;
109+
return;
110+
}*/
111+
112+
var oldObjects = [];
113+
114+
for (var i = 0; i < priv.menuObjects.length; i++)
115+
oldObjects.push(priv.menuObjects[i]);
116+
117+
priv.menuObjects.length = 0;
118+
createMenuBar(root, "CustomMenu", "CustomMenuItem", "CustomMenuSeparator");
119+
120+
for (i = 0; i < oldObjects.length; i++)
121+
removeMenu(oldObjects[i]);
122+
}
123+
124+
/*Connections {
125+
target: // TODO: Add a class for the menu bar reload signal
126+
function onMenuBarReloadTriggered() {
127+
for(var i = 0; i < root.count; i++)
128+
root.menuAt(i).close();
129+
root.reload();
130+
}
131+
}*/
132+
133+
Component.onCompleted: reload();
134+
135+
/*onEnabledChanged: {
136+
if(platformMenuBarLoader.active)
137+
platformMenuBarLoader.item.reload();
138+
}
139+
140+
Loader {
141+
id: platformMenuBarLoader
142+
active: // whether the native menu bar is active
143+
144+
sourceComponent: Platform.MenuBar {
145+
id: platformMenuBar
146+
function reload() {
147+
clear();
148+
if(root.enabled)
149+
createMenuBar(platformMenuBar, "Platform.Menu", "Platform.MenuItem", "Platform.MenuSeparator");
150+
}
151+
152+
Connections {
153+
target: QmlUtils
154+
function onMenuBarReloadTriggered() {
155+
platformMenuBar.reload();
156+
}
157+
}
158+
159+
Component.onCompleted: reload();
160+
}
161+
}*/
162+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
import QtQuick
4+
import QtQuick.Controls
5+
6+
MenuItem {
7+
font.pointSize: 10;
8+
implicitHeight: 36;
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
import QtQuick
4+
import QtQuick.Controls
5+
6+
MenuSeparator {}

0 commit comments

Comments
 (0)