Putting a close button on QTabWidget - c++

I'm using a QTabWidget to render multiple documents in a window, and I want to draw a close button on each tab. I'm using Vista and Qt4, so the tab widget is a native windows control; this may affect the feasibility.
Does anyone know if it is possible to do this using the QTabWidget control, or do I have to create a custom widget? If creating a new widget is the only option, any pointers would be much appreciated; I'm relatively new to Qt.

Since Qt 4.5. If you just call setTabsClosable(true) on QTabWidget, you will have the close buttons but they won't be bound to an action.
You have to connect the tabCloseRequested(int) signal to one of your own slots if you want the buttons to do something.
MainWindow::MainWindow()
m_tabs = new QTabWidget();
m_tabs->setTabsClosable(true);
connect(m_tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
void MainWindow::closeTab(const int& index)
{
if (index == -1) {
return;
}
QWidget* tabItem = m_tabs->widget(index);
// Removes the tab at position index from this stack of widgets.
// The page widget itself is not deleted.
m_tabs->removeTab(index);
delete(tabItem);
tabItem = nullptr;
}

In 4.5 there is function
void setTabsClosable ( bool closeable )

Currently there is no way to do this with the stock QTabWidget, however the upcoming Qt 4.5 (planned to be released in March 2009) will have the ability to add close buttons to tabs either manually or by setting a QTabBar.TabsClosable property.
Until then, the only way to get close buttons is to subclass QTabWidget or QTabBar and add it manually (possible, but not trivial).

Related

Context Menu works for child but not parent Widget

I'm developing a desktop program that displays data in several QWidget windows, and I'm attempting to use a context menu to allow the user to copy/save an image of the window for use elsewhere. I encounter a pretty strange error when trying to get the context menu to appear in the window. I initially used the Qt Design mode to create the on_Plot_customContextMenuRequested(const QPoint &pos) slot for the entire window (entire Qwidget?), which did not work. When I create the on_SignalPlot_customContextMenuRequested slot, it works perfectly, but only on that specific widget, which is a subset of the entire window. I use identical code for each slot, and the debug output shows that the individual widget context menu request signal is emitted but the signal for the whole window is not. Is there a way to get it to work for the whole window?
Could the fact that the two child widgets take up the entire window cause the issue? I use a grid layout to ensure that the plots resize with the window.
(I'd show an image of the designer layout, but I don't have enough reputation.)
Does not work (code for whole window):
void Plot::on_Plot_customContextMenuRequested(const QPoint &pos)
{
qDebug()<<"plot context menu requested";
qDebug()<<pos;
QMenu* menu=new QMenu();
menu->addAction(copyWinAct);
menu->addAction(saveWinAct);
menu->exec(QCursor::pos());
}
Works Perfectly (code for individual plot/widget):
void Plot::on_SignalPlot_customContextMenuRequested(const QPoint &pos)
{
qDebug()<<"plot context menu requested";
qDebug()<<pos;
QMenu* menu=new QMenu();
menu->addAction(copyWinAct);
menu->addAction(saveWinAct);
menu->exec(QCursor::pos());
}
Thanks for your help.
If anyone else has this problem, I've found a solution. By connecting the customContextMenuRequested signal to one slot, each sub-widget will display the same context menu. Setting the overall widget to the same slot will make the whole window behave in the same manner. I added the following code to the class default constructor and created the corresponding slot to get everything to behave properly.
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuSlot(QPoint)));
QList<QWidget *> windowChildren=this->findChildren<QWidget *>();
foreach (QWidget *child, windowChildren)
{
child->setContextMenuPolicy(Qt::CustomContextMenu);
connect(child,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuSlot(QPoint)));
}
Good luck to anyone else fighting this problem.

Use custom tab bar with QMdiArea

I see that QMdiArea has a tabbed view mode. I want to be able to split the main window with two QMdiArea widgets and to be able to drag and drop tabs between each of them. I have already done it with a simple QTabWidget where I can set custom tab bar. At the same time I want to switch QMdiArea view mode thus using QTabWidget is not an option for me. But I don't see any methods to set custom tab bar within QMdiArea. I still have hope that it could be done. Can anyone suggest something?
Tested solution for Qt 4.8 (edit)
After some time of research I can suggest the following solution. You have to make a new class inheriting QMdiArea. Set its view mode to TabbedView to make the standart QTabBar to be constructed within QMdiArea. Then get all children and find QTabBar widget with QString(QObject::metaObject()->className()) == "QTabBar". Hide it. You will get a blank area above the document in TabbedView mode. Construct you custom tab bar and reparent it to your custom mdi area. Connect signals and slots that are fired and used when the sub windows and tabs are activated. You can have your custom tab bar as a class member of your custom mdi area.
If you have found this post useful please vote on it. Thanks.
Some code for example.
Looking for a standart QTabBar within a custom mdi area in its constructor:
m_pMdiAreaTabBar = NULL;
m_pMdiArea->setViewMode(QMdiArea::TabbedView);
QObjectList listChildren = m_pMdiArea->children();
for (QObjectList::Iterator i = listChildren.begin(); i != listChildren.end(); ++i)
{
if (QString((*i)->metaObject()->className()) == "QTabBar")
{
m_pMdiAreaTabBar = dynamic_cast<QTabBar*>(*i);
break;
}
}
Reparent:
m_pTabBar->setParent(m_pMdiArea);
Hiding:
if (m_pMdiAreaTabBar != 0) m_pMdiAreaTabBar->hide();
Signals & Slots used: QMdiArea::subWindowActivated(QMdiSubWindow*), QTabBar::currentChanged(int)

How to know if QDockWidget was undocked via the button or by dragging it?

I'm new to Qt and I don't know how to fix this.
I have a QDockWidget that is put in some position when the user clicks the undock button (I don't know it's name). When this happens the widget visibility changes twice because it sort of disappears and appears again but undocked. To put it in some position after it gets undocked I use this in the visibility changed event:
if (ui->searchBar->isFloating()) {
int x = (this->x() + this->width()) - 410;
int y = (this->y() + this->height()) - 70;
ui->searchBar->setGeometry(QRect(x,y,400,60));
}
The problem is that in Linux if I undock the widget by dragging it in stead of clicking the undock button, when I drop it in some place of the window it automatically moves to the position specified by the code above. It makes sense, however this doesn't happens in Windows(and I need the application to run in both OS). In Windows if you click the button it goes to the specified location but if you drag it then it stays in the position where you drop it.
To fix it I plan to use the above code only if the widget was not dragged but I'm not sure how to do this. Can somebody help me out or have a better idea on how to fix this?
QDockWidget has undocumented button named 'qt_dockwidget_floatbutton'.
You can access it like this:
QAbstractButton* button =
YourDockWidget->findChild<QAbstractButton*>("qt_dockwidget_floatbutton");
connect(button, SIGNAL(clicked()), this, SLOT(yourSlot()));
So you can put your code above to that slot to move your widget only if it was undocked via the button.

How can I add a QComboBox to the Main Toolbar in Qt Creator

I am writing a Text Editor on Qt Creator. I have a QPlainTextEdit as the central widget, and I want all the font-controlling tools in the main toolbar automatically added to all QMainWindow projects. When I try to drag and drop a QComboBox on to the main toolbar, A not-allowed icon is displayed.
Is there a way of doing this?
Thanks for your help in advance.
You can do what you want by calling the addWidget function of the QToolBar. So if you have called your main tool bar mainToolBar you can do in the constructor of your main window:
QComboBox* myComboBox = new QComboBox;
// Add values in the combo box
ui->mainToolBar->addWidget(myComboBox);
// make the connection between the combo box and a slot
Okay, looking a bit around in the cpp file I realized that I'm referring the wrong thing.
ui->mainToolBar->insertWidget(ui->actionLoadSettings, cbxSelect); will do the trick.

QDockWidget is closed if main window is minimized

I'm using Qt 4.7 on Windows 7 Ultimate 32 bit.
The QMainWindow of my program has a QDockWidget. I've noticed that if I minimize the main window by the minimize button on the title bar, after restoring it the dock widget is closed. I didn't write any support for a feature like this!
How does this happen and how to prevent this?
Thanks.
I encountered this error when writing my own application. I have QDockWidget with options for my application. Using Qt Creator I created menu with QAction actionMenu which was checkable. Then I connected QDockWidget and QAction like this:
QObject::connect(ui->dockWidget, SIGNAL(visibilityChanged(bool)),
ui->actionMenu, SLOT(setChecked(bool)));
QObject::connect(ui->actionMenu, SIGNAL(toggled(bool)),
ui->dockWidget, SLOT(setVisible(bool)));
The order of connection is not important. And then when I minimized application with QDockWidget being visible, after I restored it QDockWidget was closed and actionMenu was unchecked.
In fact there are two solutions. First which works for me is to use SIGNAL(triggered(bool)) instead of SIGNAL(toggled(bool)):
QObject::connect(ui->dockWidget, SIGNAL(visibilityChanged(bool)),
ui->actionMenu, SLOT(setChecked(bool)));
QObject::connect(ui->actionMenu, SIGNAL(triggered(bool)),
ui->dockWidget, SLOT(setVisible(bool)));
The second solution uses action which you can obtain from QDockWidget:
// Retrieve action from QDockWidget.
QAction *action = ui->dockWidget->toggleViewAction();
// Adjust any parameter you want.
action->setText(QString("&Menu"));
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
action->setStatusTip(QString("Press to show/hide menu widget."));
action->setChecked(true);
// Install action in the menu.
ui->menuOptions->addAction(action);
I know for sure that SIGNAL(toggled(bool)) was causing in my application closure of QDockWidget.
I faced the same problem... I managed to get rid of it by using a method called StoreWindowsLayout and RestoreWindowsLayout.
StoreWindowsLayout will save the content of the ByteArray returned by the Method QMainwindow::saveState().
RestoreWindowsLayout will restore that bytearray, and therefore your windows layout, the qdockwidget visibility state and so on...
I call StoreWindowsLayout on ApplicationMainFrm::changeEvent, on ApplicationMainFrm::closeEvent (it's likely this one you'll need) and in ApplicationMainFrm::hide().
Then I use restoreWindowsLayout in ApplicationMainFrm::showEvent.
Exemple of use of restoreWindowsLayout in my MainForm :
void ApplicationMainFrm::showEvent(QShowEvent* pEvent)
{
QMainWindow::showEvent(pEvent);
restoreWindowsLayout();
}
Hope it helps !