How to clear QML Menu correctly - qt

I have a dynamicaly created Menu. The code below is just to understand the hierarchy
Menu {
id: mainMenu
MenuItem {
text: "item"
}
Menu {
title: "submenu"
MenuItem {
text: "submenuitem"
}
}
}
Now I need to remove all mainMenu's content. As I can see in the documentation, Menu have methods removeItem, takeItem and takeMenu. Using takeMenu and count property I can access menu's children and remove them recursively. But what if I don't know the order and type of menu items? Item has not property count. I need some universal solution that can remove the item itself, and if it is a menu then remove all it's children.

I don't know if it's the cleanest solution, but it works well to clear your example.
while(mainMenu.items.length > 0)
mainMenu.removeItem(mainMenu.items[0]);
You don't need to go recursively because when you remove an Item, all its childItems are removed with it.

Related

QML MenuBar hovering items with mouse pressed

Using Qt Quick Controls 2, you can create a "traditional" menu bar like this:
ApplicationWindow {
id: window
width: 320
height: 260
visible: true
menuBar: MenuBar {
Menu {
title: qsTr("&File")
Action { text: qsTr("&New...") }
Action { text: qsTr("&Open...") }
Action { text: qsTr("&Save") }
Action { text: qsTr("Save &As...") }
MenuSeparator { }
Action { text: qsTr("&Quit") }
}
Menu {
title: qsTr("&Edit")
Action { text: qsTr("Cu&t") }
Action { text: qsTr("&Copy") }
Action { text: qsTr("&Paste") }
}
Menu {
title: qsTr("&Help")
Action { text: qsTr("&About") }
}
}
}
This works ok, but when the user presses on a menu and then drag the mouse while pressed, on the menus are not hovered. In order to hover over the menus, the mouse cannot be in a pressed state (using Qt Widgets https://doc.qt.io/qt-5/qtwidgets-mainwindows-menus-example.html this is not needed).
Is there a way to make the MenuBar, hover over items while the mouse is pressed?
When you did through this doc
https://doc.qt.io/qt-5/qml-qtquick-controls2-action.html
You then go to this doc and have high hopes when reading about "hoverEnabled"
https://doc.qt.io/qt-5/qml-qtquick-controls2-toolbutton-members.html
You really need these two signals entered() exited() from a MouseArea.
https://doc.qt.io/qt-5/qml-qtquick-mousearea.html
The short hopeful hack is to see if the documentation is "just wrong" and somewhere deep in the class structure they declared a MouseArea for a button and you really do get entered() and exited().
How else would you be able to implement hoverEnabled()? The "widget" has to know the mouse entered and did not yet exit. They may well be consuming that, but you should be able to dig through the source and find child entity that you can connect to the signal of.
There is not an easy way.
The underlying issue is that MenuItem is implemented as a Button.
When you press a button and release on another button, none of them register a click.
However, on traditional menus, if you press an item and release on another one, the item that registers the release is triggered.
The public API offered by QtQuick Controls 2 does not seem to offer a way to easily change this. So to get what you want Isee the following solutions:
Use Qt.labs.platform to build your menus, these will be native menus so they should have the correct behavior. However it still in a preview state and i have not tested them.
Reimplement MenuItem. Since it is part of Qt Quick Controls 2 it is easy to reimplement your own MenuItem, see Qt documentation. However, you will have to use MouseArea to catch user inputs and force the behavior you want.
EDIT
The 2nd solution won't work. In Qt once an Item (or a QWidget) accepts a press event, it grabs the mouse until it is released. So reimplementing MenuItem and adding MouseArea to them won't help.
Knowing that it seems that the solution would to reproduce what QMenu is doing: You need to have a single Item responsible for handling mouse events. So you should not let each MenuItem handles mouse events individually. Instead you should handle mouse events at the Menu or MenuBar level, process the events and manually change the MenuItems.
At this point I do not know if it is easier to customize Menu and MenuItem or to jus write your own Menu from scratch.

How to display model in QML with pages?

I have problem with displaying model with pages, and I can't find what is proper way to do this.
I have ListView which has model of 15 rectangles like in the picture below.
There is property currentPage which is changed when clicking the buttons. I want to be able to display:
0-4 elements in the first page
5-9 in the second
And last 5 on the third page.
I know that I can create them for example FirstPage.qml, SecondPage.qml... And use them directly, but I want to display Items from model. The ListView is not important it can be any component but I want to use model.
What is the best way to achieve this? Any idea suggestion is welcome.
ListView has a method called positionViewAtIndex() that will allow you to specify which item to scroll to. So for your case, you could do something like this:
Button {
id: previousBtn
onClicked: {
listView.positionViewAtIndex(listView.currentIndex - 5);
}
}
Button {
id: nextBtn
onClicked: {
listView.positionViewAtIndex(listView.currentIndex + 5);
}
}

Event target inherited by child doesn't effect parent React

My question is basically how can I have a child style event affect the parent. Right now I'm using event target to change the style of a table cell I'm hovering over, but whenever I hover over a child with text in it the child changes but the parent does not which doesn't look very good. Here's my code.
hoverBackground = (e) => {
if (e.target.classList.contains(this.state.calendarNavi) || e.target.classList.contains(this.state.calendarNaviEmpty)) {
e.target.style.background = 'darkgrey'
} else {
e.target.style.background = "#b1a18b"
e.target.style.color = "white"
}
}
I've looked for answers for a while but I couldn't find one most people are trying to prevent the child from effecting the parent, but I'm having the opposite problem. I want the child to change the style of the parent and vise versa.
Here's the table data, I'm using Material Design Bootstrap for basic layouts:
<td key={d} day={`${d}`} dayName={`${currentWeekDay}`} month={`${this.month()}`} onMouseEnter={this.hoverBackground} onMouseLeave={this.hoverBackgroundExit} className={`calendar-day ${currentDay} ${currentWeek} railway`} style={currentStyle}>
<MDBContainer>
<MDBRow>
<MDBCol>
{d}
</MDBCol>
</MDBRow>
</MDBContainer>
</td>
P.S. Sorry for the messy looking code, I still have to clean this component up a bit. Also I'm open to better ways of handling this hover event if anyone has suggestions.
I rubber ducked! The problem was using event.target vs using event.currentTarget

How to make a submenu within a MenuButton in JavaFX?

I'm trying to add a submenu to my MenuButton and it doesn't seem to be able to accept a Menu as a child. Is it possible to do this, or do I need to use some other kind of menu? My menu is set up like this:
class DotMenuButton: MenuButton() {
item("item 1").action {
//action 1
}
item("item 2").action {
//action 2
}
//here is where I would like a submenu
menu("sub menu") {
item("sub menu item 1").action {
//sub menu action 1
}
}
}
I am using TornadoFX but if there is a way to do this in plain JavaFX I can adapt it. Any suggestions would be appreciated.
Edit: As of tornadofx 1.7.19-SNAPSHOT the above code now works. :-)
I have committed support for submenus in MenuButton, so your code above will now work with the the latest snapshot release.

Adding css with jQuery based on class

Seeking a solution to my problem...
I partially found an answer from another thread on here, using this script
$(function () {
$(".myclass").hover(function ()
{}, function ()
{
$(".myclass>li").fadeTo(200, 1)
});
$(".myclass>li").hoverIntent(function ()
{
$(this).attr("id", "current");
$(this).siblings().fadeTo(200, .6);
$(this).fadeTo(300, 1)
}, function ()
{
$(".myclass>li").removeAttr("id");
$(this).fadeTo(200, 1)
})})
When an item in the list is hovered, the script fades all other items out. Original demo is here http://jsbin.com/usobe
This works OK on my site, though the list ( a grid of thumbnails) is part of a bigger slider script, which loads "previews" via ajax. When a list item is clicked a hidden section expands on the page, and the slider script assigns the list item a class "active".
When the hidden section is open I would like the activated thumbnail to remain at 1 opacity, while the rest are faded to .6, exactly as it is with the hover effect using the script above. What I am trying to achieve becomes obvious when you click a thumbnail to activate the ajax script. Is it possible to use the active class to make this happen i.e. if class is not active set to .6 opacity?
Thanks in advance
----EDIT
Thanks everyone for suggestions - I am not having much luck so far! Using the code above, would it be possible to modify it so that when a list item is clicked it holds the specified levels of opacity? That would do nicely, I think. Then I could use onclick I guess to fade all items back to full opacity when the hidden div is closed.
I'm trying to guess how your code work, for what I understand you should do something like this:
// this is the selector that gets the click on the thumbnail
$('li.item').click(function() {
// fade all the thumbnails to op 1.0
$('#li.item').css('opacity', '.6');
// let the active thumbnail to 1.0
$(this).css('opacity', 1);
//show your hidden div
});
Then, when you close the hidden div:
$('div#hiddenDiv').onClose(function()
// about to close
$(this).fadeTo('fast', 1);
});
You could use an on click targeting the zetaThumbs li elements, set the current target to 1 and its siblings to .6
$('.zetaThumbs li').click(function(){
$(this).css({'opacity':1}).siblings().css({'opacity':.6});
})

Resources