QMenu activated multiple times - c++

I was playing around with the Qt demo browser example mentioned here and noticed an anomaly when I tried making a minor change to the bookmark handling code.
My intention was to make the bookmarks in the toolbar open up in a new tab instead of the existing tab. It works perfectly for the bookmarks that are located directly on the bookmarks tab. But the bookmarks inside a folder are the ones which are behaving weirdly.
I modified the BookmarksToolBar::activated SLOT in the bookmarks.cpp to open the url in a new tab instead of existing tab. That's when I noticed that the SLOT is being called multiple times, the count being equal to the number of times the menu is rendered. i.e, the first time a menu item is activated, the SLOT is called once, the next time an item is activated, the SLOT gets called twice and so on.
I thought there must have been multiple signal-slot connections and thus I checked on the BookmarksToolBar::build() method where the signal-slot connection is done and found that the control flow enters the method only once. I am finding it hard to figure out how the SLOT is being called multiple times.
The project is question is an example project 'Tab browser' which comes with Qt and can be accessed by clicking on 'Examples' on the Qt-Creator welcome screen. Thus I did not post any source code here.
Any guidance or help in understanding the cause for this anomaly and possible solutions to fix it would be appreciated.

Found the cause of the problem and solution myself. The root of the problem is in modelmenu.cpp.
Apparently the ModelMenu::createMenu method connects the QMenu::triggered and QMenu::hovered signals to SLOT each time the method is called. The SLOT triggered emits the signal ModelMenu::activated.
Using Qt::UniqueConnection should solve the issue.
Replacing this:
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*)));
connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(hovered(QAction*)));
With this:
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*)),Qt::UniqueConnection);
connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(hovered(QAction*)),Qt::UniqueConnection);
Fixed the problem. Just leaving this here hoping this would help someone in future.

Related

duplicate spinbox decliration in QT causing build issue

im sure you get this a lot, but im still learning the ropes.
enter image description here
Here is an error I get because I created a second slot for a spinboxValue changed.
I can comment it out and run the program with no issue but the issue keeps returning.
what is the correct way to remove this slot.
For reference, i right clicked and selected the go to slot for a second time, thinking that it will take me to the slot that was already created.
The error is in a file that i did not create and can only access it by forcing the error to reoccurred (to my knowledge)

How do you disable a CComboBox in C++?

I've searched this extensively, and the answer I came up with about 20 times is to use CWnd::EnableWindow(FALSE). Currently, I have:
GetDlgItem(myComboBox)->EnableWindow(FALSE);
Instead of disabling the ComboBox, now the entire Dialog doesn't show up, and since it's a modal dialog (or at least I'm guessing that's the reason), the entire program gets locked up because I can't close the dialog if it's not there.
Is there a way to disable editing to this box without making it disappear entirely; similar to what SetReadOnly() does for a CEdit?
Edit:
Suddenly, the syntax above started working the next morning. I'm still not entirely sure why it didn't work in the first place.
EnableWindow(FALSE) is the correct function to call but your syntax looks like it may be incorrect (but it's hard to say with such a minimal example).
Is myComboBox an instance of CComboBox? If so, I'd expect to see:
myComboBox.EnableWindow(FALSE);
or, using the associated resource ID:
((CComboBox*)GetDlgItem(IDC_MY_COMBO_BOX))->EnableWindow(FALSE);
Threading issues or duplicate resource ID's can also cause weird issues.
It seems you are trying to call EnableWindow() from a different thread than the dialog's
You could try this, and see if it works for you:
GetDlgItem(myComboBox)->PostMessage(WM_ENABLE, (WPARAM)FALSE);

wxToolBar with dropdown menu: no reaction on selected item

I'm using a wxToolBar which makes use of a drop-down menu with following code (simplified):
g_toolBar1->AddTool(TOOLBAR_CMD_CONTROL_DROPDOWN,_("Control elements"),MainWin::getBitmap(gearsXPM,"gears"),wxNullBitmap,wxITEM_DROPDOWN);
custParent->Connect(TOOLBAR_CMD_CONTROL_DROPDOWN,wxEVT_COMMAND_TOOL_CLICKED,wxCommandEventHandler(DrawCanvasSwitcher::OnToolbar),NULL,g_drawCanvas);
wxMenu *controlMenu=new wxMenu;
// following is repeated several times to have more than onw drop-down item
// (*it) is an iterator to an container holding the required data
wxMenuItem *item=new wxMenuItem(controlMenu,wxID_ANY,(*it)->m_entityParams.m_name,(*it)->m_entityParams.m_shorthelp);
controlMenu->Append(item);
item->SetBitmap(*(*it)->m_entityParams.m_bmToolbar);
item->SetId((*it)->m_wxID);
custParent->Connect(item->GetId(),wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED,wxCommandEventHandler(DrawCanvasSwitcher::OnMenu),NULL,g_drawCanvas);
g_toolBar1->SetDropdownMenu(TOOLBAR_CMD_CONTROL_DROPDOWN,controlMenu);
g_toolBar1->Realize();
So the first Connect() is successful and when clicking the top toolbar item, I end up in DrawCanvasSwitcher::OnToolbar(). The second Connect() - which is simply copied from a different position in same file and where it works fine for normal menu items - does not work, I never get an event in DrawCanvasSwitcher::OnMenu() when selecting a toolbar drop-down item. The event type is the same as used in the toolbar-sample that comes with wxWidgets 3.1. g_drawCancas and custParent all are valid (and work for plain menu items).
So what could be the reason why I do not reveice events on clicked drop-down items?
Edit: using wxEVT_COMMAND_MENU_SELECTED instead of wxEVT_COMMAND_TOOL_DROPDOWN_CLICKED does not make any difference, still no event...
I don't see anything obviously wrong in the code, so, as always, the best thing to do would be to try to simplify it as much as possible and/or try doing the same thing in the toolbar sample to see if you can reproduce the problem there.
One thing I'd try would be to specify (*it)->m_wxID immediately when creating the menu item, instead of setting it later. It should work as written, of course, but it's rather uncommon to do it like this, so perhaps there is a bug somewhere there.
If you do manage to reproduce the problem in the toolbar sample (e.g. just remove the event table entry for MyFrame::OnToolDropdown() there and use Connect() instead), please do report it as a bug, mentioning your platform.
And, finally, although it's completely unrelated to your problem, there is really no reason whatsoever to use Connect() instead of Bind() with wxWidgets 3.x, you should really switch to the latter for better compile-time safety and flexibility.

Move QToolButton to different layouts by just pressing it?

I have here two different layouts, and one QToolButton. My goal is to transfer that button between the two layouts when I click it. I figured this code would work,
snippet:
void DominionLinux::on_toolButton_clicked(string state)
{
if (state=="Disabled"){
ui->verticalLayout_Enabled->addWidget(ui->toolButton);
state = "Enabled";
}
else if (state=="Enabled"){
ui->verticalLayout_Disabled->addWidget(ui->toolButton);
state = "Disabled";
}
}
By default, state == "Disabled". When I test the UI in QTCreator, the first time I click, it works; the button dissapears from one template, and appears on the other. The second time I click when its on the other template, it doesn't. When compiling, I get this warning:
*QMetaObject::connectSlotsByName: No matching signal for on_toolButton_clicked(string)*
Any ideas why the slot stops working?
Any ideas why the slot stops working?
You are missing the signal declaration at the place of the connect as the warning also hints. Also, it seems that you are passing either the slot as the signal to the connect method. A signal should not have the same name as a slot in a Qt application.
Other than that, you may wanna reconsider your design about disabling and enabling a button. Putting them into separate layers is not the appropriate way of doing it.
Moreover, you should probably avoid raw strings for representing states in general. It is better to use enumerations, or boolean for "toggle states".

(Qt) How to check if a QTextEdit widget text was changed from a QTabWidget

I have a QTabWidget parented by a QMainWindow that manages QTextEdit widgets.
I'd like to know when content was changed in one the tabs and to know which one.
I've been trying to google a solution but after many changed lines in my code and architecture changes of my class.
My last try was:
QTextEdit* curr_text_edit = /*slots were used to get this pointer*/;
connect(curr_text_edit, SIGNAL(textChanged()), this, SLOT(marquerChangement()));
but the slot "marquerChangement()" is never called. Any ideas?
If marquerChangement() is not being called, there can only be two possible reasons. First is that the QTextEdit represented by curr_text_edit never emits a signal (in other words, perhaps you've got the wrong QTextEdit?).
Another possibility is that your call to connect failed. This signal/slot connection is done at runtime, not compile time. Failures here typically just get printed to stdout, and then the program goes happily on its way. Check your application output to see if you get a message about a signal or a slot not found.