PDA

View Full Version : QMdiArea : moving tab issue.



Satan2K
9th January 2011, 07:43
Hello everyone,

While designing an application with mdiArea and its tabbed view mode, i have an issue if i set its QTabBar movable : the connexions are not updating to the correct mdi window when moved. If you move the tabs, it will no more focus the correct window.

I'm surely using it wrong, but we never know if it's a bug (or a feature ;) ). I found the same behavior under Qt4.5 (linux), and Qt4.7.1 (windows)

Here's a quick and dirty made example


#include <QApplication>
#include <QtGui>

int main(int argc, char* argv[])
{
QApplication app(argc, argv);

QMdiArea *mdiArea = new QMdiArea();
mdiArea->setViewMode(QMdiArea::TabbedView);
mdiArea->findChild<QTabBar*>()->setMovable(true);

QMdiSubWindow *firstTab = mdiArea->addSubWindow(new QTextEdit("i'm the first tab"));
firstTab->setWindowTitle("first tab");
QMdiSubWindow *secondTab = mdiArea->addSubWindow(new QTextEdit("i'm the second tab"));
secondTab->setWindowTitle("second tab");

mdiArea->show();

return app.exec();
}


Thanks for your help, have a good day,

high_flyer
9th January 2011, 15:08
Without dwelling to long in your code, the follwing is not clear to me:

mdiArea->findChild<QTabBar*>()->setMovable(true);
You call this right after creating the MDI area, when it has no children yet.. actually I would say this line should crash, since the returned pointer should be null...
You should call this after you have added your children to the MDI.
Even if you would call this line in the right place have a look at the docs about it:

If there is more than one child matching the search, the most direct ancestor is returned. If there are several direct ancestors, it is undefined which one will be returned. In that case, findChildren() should be used.

Satan2K
9th January 2011, 15:19
When the viewMode is set to tabbed view, a MDI area always has a QTabBar widget.


int main(int argc, char* argv[])
{
QApplication app(argc, argv);

QMdiArea *mdiArea = new QMdiArea();
mdiArea->setViewMode(QMdiArea::TabbedView);
mdiArea->dumpObjectTree();
mdiArea->show();

return app.exec();
}


QMdiArea::
QWidget::qt_scrollarea_hcontainer
QScrollBar::
QBoxLayout::
QWidget::qt_scrollarea_vcontainer
QScrollBar::
QBoxLayout::
QWidget::
QTabBar:: // <= Here
QToolButton::
QToolButton::

And, as i can see on the doc, there's no other way to get access to its QTabBar widget.

Satan2K
10th January 2011, 06:40
So is it the correct behavior, or should i report it as a bug? :)

In the meantime, i changed completely the part using QMdiArea to an new object inheriting from QTabWidget, and i destroy its child widget when a tab is requested to be removed. (tabCloseRequested(int) to a custom slot)

tabObject->widget(index)->deleteLater();
tabObject->removeTab(index);

high_flyer
10th January 2011, 08:19
So is it the correct behavior, or should i report it as a bug?
I didn't have time to test this, so I don't know.
Hopefully someone else can comment on this too.

Ev_genus
10th January 2011, 11:01
In the meantime, i changed completely the part using QMdiArea to an new object inheriting from QTabWidget, and i destroy its child widget when a tab is requested to be removed. (tabCloseRequested(int) to a custom slot)

tabObject->widget(index)->deleteLater();
tabObject->removeTab(index);

Thanks a lot for your question. I've tried to make my own mdi-style widget with QTabBar but have many problems with destruction. First of this two lines is exactly what I need.

About QMdiArea. Since you hacked it to find mysterious QTabBar inside, you can't be sure about stable behavior in future. So I think this situation is a feature. (Or feature-lack in QMdiArea interface :()
:(

norobro
10th January 2011, 14:45
So is it the correct behavior, or should i report it as a bug? :)
Looks like a fix has been submitted for review: link (http://qt.gitorious.org/qt/qt/merge_requests/2522)

Satan2K
10th January 2011, 19:15
haha great, so I don't have to worry about reporting it. Thanks :)


Thanks a lot for your question. I've tried to make my own mdi-style widget with QTabBar but have many problems with destruction. First of this two lines is exactly what I need.

It's quite simple if you inherit from a QTabWidget. Here's the test example i quickly designed.



class UI_TabWidget : public QTabWidget
{
Q_OBJECT

public :
UI_TabWidget(QWidget *pParent = 0);
void openTab();

private slots :
void closeTab(int iTabIndex);
};



UI_TabWidget::UI_TabWidget(QWidget *pParent) : QTabWidget(pParent)
{
this->setMovable(true);
this->setTabsClosable(true);
QObject::connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
}

void UI_TabWidget::openTab()
{
//Here's a quick test widget
QTextEdit *pTextEdit = new TextEdit();
//Attaching it to a new tab
this->addTab(pTextEdit, "test");
}

void UI_TabWidget::closeTab(int iTabIndex)
{
this->widget(iTabIndex)->deleteLater();
this->removeTab(iTabIndex);
}

Feel free to attach a custom made widget in openTab too, and you'll be able to access its member with

myCustomWidget *pWidget = dynamic_cast <myCustomWidget*>(this->widget(iTabIndex));

Then you'll be able to make custom states to check before closing


if (!pWidget->m_bAllowedToClose)
//...

Have fun ;-)