Changeset View
Changeset View
Standalone View
Standalone View
plugins/standardoutputview/outputwidget.cpp
Show First 20 Lines • Show All 189 Lines • ▼ Show 20 Line(s) | 68 | { | |||
---|---|---|---|---|---|
190 | foreach( int id, data->outputdata.keys() ) | 190 | foreach( int id, data->outputdata.keys() ) | ||
191 | { | 191 | { | ||
192 | changeModel( id ); | 192 | changeModel( id ); | ||
193 | changeDelegate( id ); | 193 | changeDelegate( id ); | ||
194 | } | 194 | } | ||
195 | enableActions(); | 195 | enableActions(); | ||
196 | } | 196 | } | ||
197 | 197 | | |||
198 | OutputWidget::~OutputWidget() | ||||
199 | { | ||||
200 | // Since QSharedPointer can't detect object destruction and our handled views/models objects | ||||
201 | // have QObject parents we must first clear out hash. This removes double-free problem which | ||||
202 | // happens when our objects are first destroyed from parent's destructor and sencond from | ||||
203 | // QSharedPointer destructor. | ||||
204 | m_views.clear(); | ||||
kossebau: Isn't m_views destroyed (and thus implicitely cleared) before reaching the ~QWidget and… | |||||
205 | | ||||
206 | // We also must manually destroy our widget here to prevent updateFilter() slot calling from | ||||
207 | // parent's destructor, which leads to segfault since m_views hash will be destroyed before | ||||
208 | // such call. | ||||
209 | delete m_tabwidget; | ||||
This here might be more the actual issue, preventing the updateFilter slot being invoked during destruction because tabwidget or stackwidget emitting signals on their subwidgets being removed, Not sure what is the better approach, only disconnecting from the currentChanged signals or straight deleting the widgets. Personally I tend to only handle the connections, and leave memory management of widgets completly to the Qt internals. kossebau: This here might be more the actual issue, preventing the updateFilter slot being invoked during… | |||||
210 | delete m_stackwidget; | ||||
211 | } | ||||
212 | | ||||
198 | void OutputWidget::clearModel() | 213 | void OutputWidget::clearModel() | ||
199 | { | 214 | { | ||
200 | auto view = qobject_cast<QAbstractItemView*>(currentWidget()); | 215 | auto view = qobject_cast<QAbstractItemView*>(currentWidget()); | ||
201 | if( !view || !view->isVisible()) | 216 | if( !view || !view->isVisible()) | ||
202 | return; | 217 | return; | ||
203 | 218 | | |||
204 | KDevelop::OutputModel *outputModel = nullptr; | 219 | KDevelop::OutputModel *outputModel = nullptr; | ||
205 | if (auto proxy = qobject_cast<QAbstractProxyModel*>(view->model())) { | 220 | if (auto proxy = qobject_cast<QAbstractProxyModel*>(view->model())) { | ||
▲ Show 20 Lines • Show All 432 Lines • ▼ Show 20 Line(s) | 645 | { | |||
638 | } | 653 | } | ||
639 | return index; | 654 | return index; | ||
640 | } | 655 | } | ||
641 | 656 | | |||
642 | void OutputWidget::outputFilter(const QString& filter) | 657 | void OutputWidget::outputFilter(const QString& filter) | ||
643 | { | 658 | { | ||
644 | QAbstractItemView *view = qobject_cast<QAbstractItemView*>(currentWidget()); | 659 | QAbstractItemView *view = qobject_cast<QAbstractItemView*>(currentWidget()); | ||
645 | if( !view ) | 660 | if( !view ) | ||
646 | return; | 661 | return; | ||
Please no drive-by changes to lines not touched otherwise, especially non-whitespace changes. That make the "git blame" annotations confusing. kossebau: Please no drive-by changes to lines not touched otherwise, especially non-whitespace changes. | |||||
647 | 662 | | |||
648 | auto fvIt = findFilteredView(view); | 663 | auto fvIt = findFilteredView(view); | ||
649 | auto proxyModel = qobject_cast<QSortFilterProxyModel*>(view->model()); | 664 | auto proxyModel = qobject_cast<QSortFilterProxyModel*>(view->model()); | ||
650 | if( !proxyModel ) | 665 | if( !proxyModel ) | ||
651 | { | 666 | { | ||
652 | proxyModel = new QSortFilterProxyModel(view->model()); | 667 | proxyModel = new QSortFilterProxyModel(view->model()); | ||
653 | proxyModel->setDynamicSortFilter(true); | 668 | proxyModel->setDynamicSortFilter(true); | ||
654 | proxyModel->setSourceModel(view->model()); | 669 | proxyModel->setSourceModel(view->model()); | ||
655 | fvIt->proxyModel = QSharedPointer<QSortFilterProxyModel>(proxyModel); | 670 | fvIt->proxyModel = QSharedPointer<QSortFilterProxyModel>(proxyModel); | ||
656 | view->setModel(proxyModel); | 671 | view->setModel(proxyModel); | ||
657 | } | 672 | } | ||
658 | QRegExp regExp(filter, Qt::CaseInsensitive); | 673 | QRegExp regExp(filter, Qt::CaseInsensitive); | ||
659 | proxyModel->setFilterRegExp(regExp); | 674 | proxyModel->setFilterRegExp(regExp); | ||
kossebau: Unrelated change? | |||||
660 | fvIt->filter = filter; | 675 | fvIt->filter = filter; | ||
661 | } | 676 | } | ||
662 | 677 | | |||
663 | void OutputWidget::updateFilter(int index) | 678 | void OutputWidget::updateFilter(int index) | ||
664 | { | 679 | { | ||
665 | QWidget *view = (data->type & KDevelop::IOutputView::MultipleView) | 680 | QWidget *view = (data->type & KDevelop::IOutputView::MultipleView) | ||
666 | ? m_tabwidget->widget(index) : m_stackwidget->widget(index); | 681 | ? m_tabwidget->widget(index) : m_stackwidget->widget(index); | ||
667 | auto fvIt = findFilteredView(qobject_cast<QAbstractItemView*>(view)); | 682 | auto fvIt = findFilteredView(qobject_cast<QAbstractItemView*>(view)); | ||
Show All 30 Lines |
Isn't m_views destroyed (and thus implicitely cleared) before reaching the ~QWidget and ~QObject destructors where then any QObject-child-tree memory management is done?
So do we really need to explicitly call this here?