Is there a way to prevent the hide operation of a toolbar? - c++

In Qt, if I right-click on a toolbar the menu will be shown that allows me to hide the toolbar. I need to disable this functionality because I don't want the toolbar to possible to hide. Is there a way to do this?

I was able to set the ContextMenuPolicy directly on the toolbar (not the main window), as long as I used either Qt::PreventContextMenu or Qt::ActionsContextMenu. Prevent eliminated the context menu and made right-click have no effect on the toolbar, while Actions made a nice context menu composed of the actions already in my toolbar. Qt::NoContextMenu didn't seem to have any effect.
toolbar->setContextMenuPolicy(Qt::PreventContextMenu);

Use setContextMenuPolicy (Qt::NoContextMenu) for the main window of the toolbar.

There are several ways to achieve this without having to alter the contextMenu functionality. See the following 3 PySide examples:
1. Disable the toggleViewAction of the QToolBar:
UnhidableToolBar = QToolBar()
UnhidableToolBar.toggleViewAction().setEnabled(False)
2. Connect to the visibilityChanged signal:
toolbar.visibilityChanged.connect(lambda: toolbar.setVisible(True))
3. Subclass QToolBar and use the hideEvent:
class UnhideableQToolBar(QToolBar):
def hideEvent(self, event):
self.setVisibile(True)
Recommendation:
While 2 & 3 are pretty dirty, solution 1 shows the toolbar in the context menu like a QDockWidget that has the feature DockWidgetClosable set. So either use solution 1 or if you want to remove the action have a look at Steven's answer.

Override QMainWindow::createPopupMenu() e.g.
QMenu* MyApp::createPopupMenu()
{
QMenu* filteredMenu = QMainWindow::createPopupMenu();
filteredMenu->removeAction( mUnhidableToolBar->toggleViewAction() );
return filteredMenu;
}
Note that the other answers that suggest disabling the context menu will only work if you want to disable hiding/showing of all toolbars and all dock widgets.

Inherit QToolbar and reimplement contextMenuEvent().

The simplest thing to do is:
self.toolbar.toggleViewAction().setVisible(False)
Unlike self.toolbar.toggleViewAction().setEnabled(False), which still shows the disabled popup if you're right-clicking the toolbar for any reason.

Related

QtDialog with close button but hidden toolbar, minimize and maximize buttons

I'm working on an Qt app. I should create a pop-up window that has only a close button with no toolbar, minimize and maximize buttons.
Any idea how to do this?
I don't know by "no toolbar" you mean "no title bar" or not, but this example can help you. Anyway, by using the following code you can have a window with just close button, and "title bar":
window->setWindowFlags(Qt::Window | Qt::WindowCloseButtonHint);
If you don't want the title bar too, try to remove it and design it by yourself.
you could change the window-flags. But your expected window calls for a QDialog: has no menu-bar and just a close-button (out of the box).
Else refer to this ( https://doc.qt.io/qt-5/qtwidgets-widgets-windowflags-example.html ) and set the flag for Qt::WindowCloseButtonHint.
If you use setWindowFlags(Qt::Window | Qt::FramelessWindowHint); you will get rid of the title bar, but with it all buttons that live on the titlebar, including the close button.
This will mean you will need to implement a way to move the window, as the title bar is used for this purpose. See this answer
Then implement your own titlebar class with a close button that you can put at the top of your dialog.
Unfortunately you don't have any control over the system titlebar appearance, so it's not possible to stylesheet your way out of this problem.

Embedding dialogs in main dialog and switching them with button click in MFC

I have a design like below:
So basically, I want to embed three dialogs in the application main dialog and switch between them, for each button click i.e., button 1 will show dialog one , button 2 will hide dialog 1 and show dialog 2 .. and so on.
Each dialog will be having a different design and functions.
I tried using CPropertySheet class to Add pages but its GUI is different. It has either option for navigating the dialogs using next / back button , or from a tab control.
None of which is as per my requirement.
So I want to know is it possible to have a design like this in MFC ? If yes how? Which Class/ control should I use.
Any help will be appreciated.
What you can do is use a normal CDialog class, add your buttons to it and also create a frame/rect as a placeholder for where your embedded dialogs are to appear. The following piece of code will create and position your embedded dialog.
CRect rect;
CWnd *pHost = GetDlgItem(ID_OF_YOUR_FRAME_RECT);
pHost->GetWindowRect(&rect);
ScreenToClient(&rect);
pDialog->Create(ID_OF_YOUR_DIALOG, this);
pDialog->MoveWindow(&rect);
pDialog->ShowWindow(SW_SHOW);
On button clicks, you hide the previously shown dialog (SW_HIDE) and show your selected dialog(SW_SHOW) with ShowWindow(...).
If you create your embedded dialogs with IDD_FORMVIEW style in the add resource editor it'll have the proper styles for embedding.
Another option is probably to use an embedded PropertySheet and hide the tab row and programatically change the tabs on the button clicks. I just find it to be too much fuzz with borders, positioning, validation and such for my liking.
If you have the MFC Feature Pack, that first came with VS2008 SP1 and is in all later versions, you might like to consider CMFCPropertySheet. There are a number of examples on the linked page, that are very similar to your design.
For example, this:
What worked for me just using dialog based application is SetParent() method. Dont know why nobody mentioned it. It seems to work fine.
I am doing like below:
VERIFY(pDlg1.Create(PanelDlg::IDD, this));
VERIFY(pDlg2.Create(PanelDlg2::IDD, this));
VERIFY(pDlg3.Create(PanelDlg2::IDD, this));
::SetParent(pDlg1.GetSafeHwnd(), this->m_hWnd);
::SetParent(pDlg2.GetSafeHwnd(), this->m_hWnd);
::SetParent(pDlg3.GetSafeHwnd(), this->m_hWnd);
Now I can show or hide a child dialog at will (button clicks) as below:
pDlg1.ShowWindow(SW_SHOW);
pDlg2.ShowWindow(SW_HIDE);
pDlg3.ShowWindow(SW_HIDE);

How to prevent closing QMessageBox after clicking a button

I have 3 buttons on QMessageBox added by QMessageBox::addButton() method. Is it possible to prevent closing the message box if a button has been clicked? By default every button closes the window, but I don't want to do it for one button.
One interesting way to approach it that worked for me is to completely disconnect the signals for the target button created, and then re-add the intended functionality. This won't work for everyone, especially if the button isn't created this way and/or you still want to close the dialog correctly. (There might be a way to add it back and/or simulate the behavior with QDialog::accept, QDialog::reject, QDialog::done - haven't tried yet.)
Example:
QMessageBox *msgBox = new QMessageBox(this);
QAbstractButton *doNotCloseButton = msgBox->addButton(tr("This button will not close anything"), QMessageBox::ActionRole);
// Disconnect all events - this will prevent the button from closing the dialog
doNotCloseButton->disconnect();
connect(doNotCloseButton, &QAbstractButton::clicked, this, [=](){ doNotCloseButton->setText("See? Still open!"); });
If you can get a pointer to the QMessageBox widget, you can try to install a QObject::eventFilter on it which filters the QEvent::Close.
Just had the same problem but I wanted to add a checkbox and it kept closing the dialog on clicked even with the ButtonRole set to QMessageBox::ActionRole (tried others too). For this scenario I just called blockSignals(true) on the QCheckBox and now it allows check/uncheck behaviour without closing the dialog. Luckily QCheckBox works fine without signals but assume you want a signal from your button.
They should likely add a new role that doesn't close the dialog as it's a pain to derive a class for simple customizations.
I looked through the addButton() functions overloads, but there is no custom behavior for the buttons you add with this method. They will behave like the standard buttons on a messagebox should.
However if you want to create a fully customizable dialog, then your best option is to extend the QDialog class and use whatever controlls you like on it.
Thanks to #Albert's Answer, I found that this also possible in python:
messagebox = QMessageBox()
button = QPushButton("This button will not close anything")
messagebox.addButton(button, QMessageBox.ButtonRole.NoRole)
button.disconnect()

Creating a tree-view with buttons? in QT

I am trying to make a dialog box like below in QT, the only problem is I have no idea what the widget is called. The bar on the left is like a tree-view widget, but when you click on it, it updates the text on the right. Does anybody happen to know what the widget is called or what widget(s) are required to perform this? I am using QT C++ on Windows.
There is an example with Qt showing you how to do this.
https://doc-snapshots.qt.io/4.8/dialogs-configdialog.html
If you're using Qt Creator as IDE, you can find it under the "Demos and Examples" tab in the Welcome Screen too.
It uses a QListWidget for the selector, and QStackedWidget to control the different pages. Connect the currentItemChanged signal of the list widget to change what page should be shown. Everything you'll need is in configdialog.cpp.
If you realy need to add QPushButton into QListWidget, use setItemWidget, or into ListView use QAbstractItemView::setIndexWidget

How do I change properties of buttons within button boxes in Qt Designer?

I have been searching online to no avail. Does anyone know how to access a button in a button box (created using the "Dialog with Buttons Right" template)?
In Designer, select the OK or Cancel button. Then open the property editor and scroll down to the QDialogButtonBox section. You can then expand the standardButtons item to see the various buttons that are available. Other properties, such as the centerButtons property, are also available.
However, designer gives you very little control over the button box.
In code, you can do many other things, such as change the text that appears on the "standard buttons." From the documentation:
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
moreButton = new QPushButton(tr("&More"));
moreButton->setCheckable(true);
moreButton->setAutoDefault(false);
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(findButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(moreButton, QDialogButtonBox::ActionRole);
As long as you give the button box a name in designer, you can set these properties in code.
I am writing this answer for the Python community. I am using PySide and faced a similar problem. I have a QDialogButtonBox and I would like to have my own buttons instead of the default ones.
I am using PySide which is more or less the exact replica of the c++ code, so I believe other c++ developers can also get something from it.
Here how I would do that:
my_ok_button = QtGui.QPushButton("My Ok Button")
my_cancel_button = QtGui.QPushButton("My Cancel Button")
ok_cancel_button = QtGui.QDialogButtonBox(QtCore.Qt.Horizontal)
ok_cancel_button.addButton(my_ok_button, QtGui.QDialogButtonBox.ButtonRole.AcceptRole)
ok_cancel_button.addButton(my_cancel_button, QtGui.QDialogButtonBox.ButtonRole.RejectRole)
I would then insert my button box to my layout like ususal:
layout.addWidget(ok_cancel_button, 1, 1)
Now later in my code I can do anything with my button. Lets change its name:
my_ok_button.setText("Some Other Name")
So then things to note here is that:
you must set the role of the buttons in the addButton() method if you
want to use functionalities given by standard buttons. E.g. if you
wish to do something like below, you need to have the button roles
set.
ok_cancel_button.accepted.connect(self.ok_method_handler)
ok_cancel_button.rejected.connect(self.close)
More information can be found here.