PDA

View Full Version : My solution for a QTabWidget child as standalone window and vice versa



toffkriss
25th March 2010, 13:10
Hi,

some code for you to discuss, if you like.
I wrote a class, that detaches children of a QTabWidget and then also putting it back to the TabWidget. It works in the following way:
If you right click on a child of a QTabWidget, you get a custom menu, with only one entry: "Detach". If you click on it, the Widget becomes a Window and the tab is removed. If you now right click on that window, another custom menu shows up with a "Attach" entry. Clicking on that, the wdiget becomes a child of the QTabWidget again, at the old position, with the same TabText:

class WidgetDetacher : public QObject {
Q_OBJECT
public:
WidgetDetacher(QTabWidget* parent, QWidget* subject);
public slots:
void detachWidget();
void attachWidget();
void showContextMenu(const QPoint &pos);
private:
QWidget* _subject;
QTabWidget* _parentTabWidget;
QString _tabLabel;
int _tabPos;
};

WidgetDetacher::WidgetDetacher(QTabWidget* parent, QWidget* subject) :
QObject(parent) {
_parentTabWidget = parent;
_subject = subject;
if (_subject != 0) {
_subject->setContextMenuPolicy(Qt::CustomContextMenu);
connect(_subject, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showContextMenu(const QPoint &)));
}
}

void WidgetDetacher::detachWidget() {
if (_subject != 0) {
if (_subject->parentWidget() != 0) {
_tabPos = _parentTabWidget->currentIndex();
_tabLabel = _parentTabWidget->tabText(_tabPos);
_parentTabWidget->removeTab(_tabPos);
_subject->setParent(0);
_subject->show();
}
}
}

void WidgetDetacher::attachWidget() {
if (_subject != 0 && _subject->parentWidget() == 0) {
disconnect(_parentTabWidget, SIGNAL(destroyed(QObject*)), _subject, SLOT(close()));
_parentTabWidget->insertTab(_tabPos, _subject, _tabLabel);
_parentTabWidget->setCurrentIndex(_tabPos);
}

}

void WidgetDetacher::showContextMenu(const QPoint &pos) {
QMenu menu;
if (_subject != 0) {
if (_subject->parentWidget() != 0) {
menu.addAction(tr("Detach"), this, SLOT(detachWidget()));
} else {
menu.addAction(tr("Attach"), this, SLOT(attachWidget()));
}
menu.exec(((QWidget*) _subject)->mapToGlobal(pos));
}
}


There are currently two drawbacks:
If you have your own cusom menu in the childwidget, it gets messy.
If you close the Widget containing the TabWidget, the former child widget wont be closed, if detached. And because I dont want the user to close the Tab, so I disabled the clos button on the child widget.
I am still working on that.
It would be cool, if you could drag a Tab outside of the TabWidget, and if that would make the child widget become a window. But until i figured out, how to do that (if its even possible), it will stay this way.