Apparently setParent would crash without obvious reasons and no illegal pointers
-
So to make long story short here's the thing: I've somehow managed to make a tab splitter application and apparently I've figured out a way to move the tabs between the splitters and even windows. Now the real problem is whenever I make the tab moves by performing this trick:
TpTabWidget *newTab = new TpTabWidget(splitter); splitter->addTab(newTab); oldTab->removeEditor(editor, true); newTab->addEditor(editor);The app will crash on the
addEditorpart. And for a holistic view here's my relevant code. (For the prefix part you may just treat theTpas a variant ofQof subclassed Qt classes for the purpose of customising different functions)void TpMainWindow::onAction_V_L_M(bool) { TpTabWidget *oldTab = m_widget->tabs()->tab(); if (!oldTab || oldTab->count() <= 1) return; TpEditor *editor = oldTab->tab(); TpTabSplitter *splitter = m_widget->tabs(); if (!editor) return; TpTabWidget *newTab = new TpTabWidget(splitter); splitter->addTab(newTab); oldTab->removeEditor(editor, true); newTab->addEditor(editor); updateEditorsMap(); splitter->update(); m_widget->update(); }TpEditor *TpTabWidget::addEditor(TpEditor *editor) { editor->disconnect(); QFileIconProvider provider; const QIcon &fileIcon = provider.icon(QFileIconProvider::IconType::File); QString text; if (editor->filePath() == "") text = QString("Untitled %1").arg(editor->m_untitled); else text = QFileInfo(QFile(editor->filePath())).fileName(); editor->m_parent = this; editor->setParent(this); int index = addTab(editor, fileIcon, text); setTabToolTip(index, text); setCurrentIndex(index); connect(editor, &TpEditor::fileNameChanged, m_parent->m_parent->m_parent, &TpMainWindow::onEditorFileNameChanged); connect(editor, &TpEditor::checkBoxChecked, m_parent->m_parent->m_parent, &TpMainWindow::onEditorCheckBoxChecked); connect(editor, &TpEditor::positionChanged, m_parent->m_parent->m_parent, &TpMainWindow::onEditorPositionChanged); connect(editor, SIGNAL(selectionChanged()), m_parent->m_parent->m_parent, SLOT(onEditorSelectionChanged())); connect(editor, &TpEditor::punctuation, m_parent->m_parent->m_parent, &TpMainWindow::onEditorPunctuation); DEF_SETTINGS; editor->setAutoCompletionThreshold(GET_SETTINGS("Editor/Values/AutoCompletionThreshold", int)); editor->setCallTipsVisible(GET_SETTINGS("Editor/Values/CallTipsMaximum", int)); editor->setCaretWidth(GET_SETTINGS("Editor/Values/CaretLineWidth", int)); editor->setEdgeColumn(GET_SETTINGS("Editor/Values/EdgeColumn", int)); editor->setExtraAscent(GET_SETTINGS("Editor/Values/ExtraAscent", int)); editor->setExtraDescent(GET_SETTINGS("Editor/Values/ExtraDescent", int)); editor->setTabWidth(GET_SETTINGS("Editor/Values/TabWidth", int)); editor->setIndentationWidth(GET_SETTINGS("Editor/Values/TabWidth", int)); emit m_parent->tabsListChanged(m_parent->m_tabs.length()); emit editor->fileNameChanged(editor->m_filePath, text); editor->setFocus(); return editor; } void TpTabWidget::removeEditor(TpEditor *editor, bool noDelete) { if (indexOf(editor) < 0) { Q_ASSERT_X(false, Q_FUNC_INFO, "Editor not in the tab widget."); return; } editor->disconnect(); removeTab(indexOf(editor)); emit m_parent->tabsListChanged(m_parent->m_tabs.length()); if (!noDelete) { editor->m_parent = nullptr; // editor->deleteLater(); delete editor; } } void TpTabWidget::onBarDragged() // <-- slot emitted when the tab bar detects dragging and want to move from and to tabs, from and to windows { QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; int key = m_keyValue++; m_dragInfo.insert(key, {m_bar->tabToolTip(currentIndex()), tab()}); mimeData->setData(tabMimeType, QByteArray::number(key)); QPixmap pixmap = currentWidget()->grab(); drag->setMimeData(mimeData); drag->setPixmap(pixmap); Qt::DropAction action = drag->exec(Qt::DropAction::CopyAction | Qt::DropAction::MoveAction); if (action == Qt::DropAction::IgnoreAction) { if (count() <= 1) return; TpMainWindow *newWindow = new TpMainWindow(false, false, tab()); newWindow->show(); m_parent->m_parent->m_parent->updateDocumentDock(); } } void TpTabWidget::dragEnterEvent(QDragEnterEvent *event) { const QMimeData *mime = event->mimeData(); if (mime->hasUrls() || mime->hasText() || mime->hasFormat(tabMimeType)) event->acceptProposedAction(); } void TpTabWidget::dropEvent(QDropEvent *event) { const QMimeData *mimeData = event->mimeData(); if (mimeData) { if (mimeData->hasUrls()) { event->acceptProposedAction(); QStringList sl; for (const auto &item : mimeData->urls()) if (item.isLocalFile()) sl << item.toLocalFile(); if (sl.empty()) goto acceptor; TpOpenAssistant *assistant = new TpOpenAssistant(m_parent->m_parent->m_parent); assistant->openFiles(sl); event->accept(); return; } else if (mimeData->hasText()) { event->acceptProposedAction(); tab()->insert(mimeData->text()); event->accept(); return; } else if (mimeData->hasFormat(tabMimeType)) { event->acceptProposedAction(); int key = mimeData->data(tabMimeType).toInt(); auto it = m_dragInfo.find(key); if (it == m_dragInfo.end()) goto acceptor; TpTabInfo info = it.value(); m_dragInfo.erase(it); int idx = m_bar->tabAt(event->position().toPoint()); TpEditor *ed = info.widget(); ed->m_parent->removeEditor(ed, true); addEditor(ed); if (idx < count() && idx >= 0) { m_bar->moveTab(currentIndex(), idx); setCurrentIndex(idx); } m_parent->m_parent->m_parent->updateDocumentDock(); event->accept(); return; } } goto acceptor; acceptor: QTabWidget::dropEvent(event); }The
tabMimeTypeis just a string I've defined to differentiate between text and so, and to facilitate dragging solely byQMimeType:inline constexpr const char *const tabMimeType = "application/x-tabwidget.index";The debug information didn't show any illegal pointers or so. Fyr in Qt Creator for example, everything the debugger has shown was in grey and didn't have any problem I presume. Worse still if I comment out the
setParentline it'll beaddTab's crash later on. I till now sadly couldn't still diagnose what kind of problems is occurring.Huge thanks to anyone who could help me, thanks to all help, thanks in advance.
If you want more code to help me please don't hesitate to demand down below -
The problem has been solved. So it turns out that the
onTabsListChangedis the ultimate culprit that made the app crash. Seemingly the thing has been called multiple times due to the signal it bound to has been emitted multiple times also, resulting removing tab that has already been removed. Now I just have to remove the code or comment it out at least to resolve the issue. -
What does removeEditor() do? I would guess it deletes the widget.
Please provide a minimal, compilable example to reproduce your problem. -
Oh, the
removeEditoris justvoid TpTabWidget::removeEditor(TpEditor *editor, bool noDelete) { if (indexOf(editor) < 0) { Q_ASSERT_X(false, Q_FUNC_INFO, "Editor not in the tab widget."); return; } editor->disconnect(); removeTab(indexOf(editor)); emit m_parent->tabsListChanged(m_parent->m_tabs.length()); if (!noDelete) { editor->m_parent = nullptr; // editor->deleteLater(); delete editor; } }Where you preserve and do not delete the editor when you pass in the
trueparameter at the end of the method. -
Btw the tabListChanged
void TpMainWindow::onTabsListChanged(int length) { if (length > 0) { for (const auto &tab : m_widget->tabs()->m_tabs) if (tab->count() <= 0) m_widget->tabs()->removeTab(tab); } }I'm not sure if it relates, but I added it later on when I attempted to extend the functionalities of cross-parent tab dragging where you normally have to update and do whatever parent-shifting as one would normally do in Qt. Only then did it crash, before it was running properly and I could dissect one tab into two or three or more.
-
The problem has been solved. So it turns out that the
onTabsListChangedis the ultimate culprit that made the app crash. Seemingly the thing has been called multiple times due to the signal it bound to has been emitted multiple times also, resulting removing tab that has already been removed. Now I just have to remove the code or comment it out at least to resolve the issue. -
J JackMyson has marked this topic as solved