void QtDNDTabBar::dropEvent(QDropEvent* dropEvent) { QtDNDTabBar* sourceTabBar = dynamic_cast<QtDNDTabBar*>(dropEvent->source()); if (sourceTabBar && dropEvent->mimeData() && dropEvent->mimeData()->data("action") == QByteArray("application/tab-detach")) { QtDNDTabBar* source = dynamic_cast<QtDNDTabBar*>(dropEvent->source()); int targetTabIndex = tabAt(dropEvent->pos()); QRect rect = tabRect(targetTabIndex); if (targetTabIndex >= 0 && (dropEvent->pos().x() - rect.left() - rect.width()/2 > 0)) { targetTabIndex++; } QWidget* tab = source->getDragWidget(); assert(tab); QTabWidget* targetTabWidget = dynamic_cast<QTabWidget*>(parentWidget()); QString tabText = source->getDragText(); /* * When you add a widget to an empty QTabWidget, it's automatically made the current widget. * Making the widget the current widget, widget->show() is called for the widget. Directly reacting * to that event, and adding the widget again to the QTabWidget results in undefined behavior. For * example the tab label is shown but the widget is neither has the old nor in the new QTabWidget as * parent. Blocking signals on the QWidget to be added to a QTabWidget prevents this behavior. */ targetTabWidget->setUpdatesEnabled(false); tab->blockSignals(true); targetTabWidget->insertTab(targetTabIndex, tab, tabText); dropEvent->acceptProposedAction(); tab->blockSignals(false); targetTabWidget->setUpdatesEnabled(true); onDropSucceeded(); } }