diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2022-07-05 18:09:19 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2022-07-07 08:19:27 +0000 |
commit | 7f94e68b748d3d8e6d0c99358b2eb8019beaf75f (patch) | |
tree | 42cbf276f9eb1c2adcfae92ce66db263ce3d58df /src/plugins/projectexplorer/appoutputpane.cpp | |
parent | fd4110519197627d9bffbae3c51c9b201ed84be2 (diff) |
ProjectExplorer: Fix index confusion in app output pane
There's a QTabWidget and a list of RunControlTabs, whose indexes got
confused in several places.
Fix this and decrease the likelihood of the problem occurring again by
never using indexes for the RunControlTab list.
Fixes: QTCREATORBUG-27743
Change-Id: I8a83b0c802fe76a09b4eba0da999a52fdeb6ddac
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/projectexplorer/appoutputpane.cpp')
-rw-r--r-- | src/plugins/projectexplorer/appoutputpane.cpp | 196 |
1 files changed, 100 insertions, 96 deletions
diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index bb96e200f7..bf37e7ce8d 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -259,42 +259,44 @@ AppOutputPane::~AppOutputPane() delete m_handler; } -int AppOutputPane::currentIndex() const +AppOutputPane::RunControlTab *AppOutputPane::currentTab() { - if (const QWidget *w = m_tabWidget->currentWidget()) - return indexOf(w); - return -1; + return tabFor(m_tabWidget->currentWidget()); +} + +const AppOutputPane::RunControlTab *AppOutputPane::currentTab() const +{ + return tabFor(m_tabWidget->currentWidget()); } RunControl *AppOutputPane::currentRunControl() const { - const int index = currentIndex(); - if (index != -1) - return m_runControlTabs.at(index).runControl; + if (const RunControlTab * const tab = currentTab()) + return tab->runControl; return nullptr; } -int AppOutputPane::indexOf(const RunControl *rc) const +AppOutputPane::RunControlTab *AppOutputPane::tabFor(const RunControl *rc) { - for (int i = m_runControlTabs.size() - 1; i >= 0; i--) - if (m_runControlTabs.at(i).runControl == rc) - return i; - return -1; + const auto it = std::find_if(m_runControlTabs.begin(), m_runControlTabs.end(), + [rc](RunControlTab &t) { return t.runControl == rc; }); + if (it == m_runControlTabs.end()) + return nullptr; + return it; } -int AppOutputPane::indexOf(const QWidget *outputWindow) const +AppOutputPane::RunControlTab *AppOutputPane::tabFor(const QWidget *outputWindow) { - for (int i = m_runControlTabs.size() - 1; i >= 0; i--) - if (m_runControlTabs.at(i).window == outputWindow) - return i; - return -1; + const auto it = std::find_if(m_runControlTabs.begin(), m_runControlTabs.end(), + [outputWindow](RunControlTab &t) { return t.window == outputWindow; }); + if (it == m_runControlTabs.end()) + return nullptr; + return it; } -int AppOutputPane::tabWidgetIndexOf(int runControlIndex) const +const AppOutputPane::RunControlTab *AppOutputPane::tabFor(const QWidget *outputWindow) const { - if (runControlIndex >= 0 && runControlIndex < m_runControlTabs.size()) - return m_tabWidget->indexOf(m_runControlTabs.at(runControlIndex).window); - return -1; + return const_cast<AppOutputPane *>(this)->tabFor(outputWindow); } void AppOutputPane::updateCloseActions() @@ -366,10 +368,9 @@ void AppOutputPane::setFocus() void AppOutputPane::updateFilter() { - const int index = currentIndex(); - if (index != -1) { - m_runControlTabs.at(index).window->updateFilterProperties( - filterText(), filterCaseSensitivity(), filterUsesRegexp(), filterIsInverted()); + if (RunControlTab * const tab = currentTab()) { + tab->window->updateFilterProperties(filterText(), filterCaseSensitivity(), + filterUsesRegexp(), filterIsInverted()); } } @@ -409,28 +410,30 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc) const CommandLine thisCommand = rc->commandLine(); const FilePath thisWorkingDirectory = rc->workingDirectory(); const Environment thisEnvironment = rc->environment(); - const int tabIndex = Utils::indexOf(m_runControlTabs, [&](const RunControlTab &tab) { + const auto tab = std::find_if(m_runControlTabs.begin(), m_runControlTabs.end(), + [&](const RunControlTab &tab) { if (!tab.runControl || tab.runControl->isRunning()) return false; return thisCommand == tab.runControl->commandLine() && thisWorkingDirectory == tab.runControl->workingDirectory() && thisEnvironment == tab.runControl->environment(); }); - if (tabIndex != -1) { - RunControlTab &tab = m_runControlTabs[tabIndex]; + if (tab != m_runControlTabs.end()) { // Reuse this tab - if (tab.runControl) - tab.runControl->initiateFinish(); - tab.runControl = rc; - tab.window->reset(); - rc->setupFormatter(tab.window->outputFormatter()); + if (tab->runControl) + tab->runControl->initiateFinish(); + tab->runControl = rc; + tab->window->reset(); + rc->setupFormatter(tab->window->outputFormatter()); - handleOldOutput(tab.window); + handleOldOutput(tab->window); // Update the title. + const int tabIndex = m_tabWidget->indexOf(tab->window); + QTC_ASSERT(tabIndex != -1, return); m_tabWidget->setTabText(tabIndex, rc->displayName()); - tab.window->scrollToBottom(); + tab->window->scrollToBottom(); qCDebug(appOutputLog) << "AppOutputPane::createNewOutputWindow: Reusing tab" << tabIndex << "for" << rc; return; @@ -492,29 +495,29 @@ void AppOutputPane::updateFromSettings() void AppOutputPane::appendMessage(RunControl *rc, const QString &out, OutputFormat format) { - const int index = indexOf(rc); - if (index != -1) { - Core::OutputWindow *window = m_runControlTabs.at(index).window; - QString stringToWrite; - if (format == NormalMessageFormat || format == ErrorMessageFormat) { - stringToWrite = QTime::currentTime().toString(); - stringToWrite += ": "; - } - stringToWrite += out; - window->appendMessage(stringToWrite, format); - if (format != NormalMessageFormat) { - RunControlTab &tab = m_runControlTabs[index]; - switch (tab.behaviorOnOutput) { - case AppOutputPaneMode::FlashOnOutput: - flash(); - break; - case AppOutputPaneMode::PopupOnFirstOutput: - tab.behaviorOnOutput = AppOutputPaneMode::FlashOnOutput; - Q_FALLTHROUGH(); - case AppOutputPaneMode::PopupOnOutput: - popup(NoModeSwitch); - break; - } + RunControlTab * const tab = tabFor(rc); + if (!tab) + return; + + QString stringToWrite; + if (format == NormalMessageFormat || format == ErrorMessageFormat) { + stringToWrite = QTime::currentTime().toString(); + stringToWrite += ": "; + } + stringToWrite += out; + tab->window->appendMessage(stringToWrite, format); + + if (format != NormalMessageFormat) { + switch (tab->behaviorOnOutput) { + case AppOutputPaneMode::FlashOnOutput: + flash(); + break; + case AppOutputPaneMode::PopupOnFirstOutput: + tab->behaviorOnOutput = AppOutputPaneMode::FlashOnOutput; + Q_FALLTHROUGH(); + case AppOutputPaneMode::PopupOnOutput: + popup(NoModeSwitch); + break; } } } @@ -567,42 +570,39 @@ void AppOutputPane::loadSettings() void AppOutputPane::showTabFor(RunControl *rc) { - m_tabWidget->setCurrentIndex(tabWidgetIndexOf(indexOf(rc))); + if (RunControlTab * const tab = tabFor(rc)) + m_tabWidget->setCurrentWidget(tab->window); } void AppOutputPane::setBehaviorOnOutput(RunControl *rc, AppOutputPaneMode mode) { - const int index = indexOf(rc); - if (index != -1) - m_runControlTabs[index].behaviorOnOutput = mode; + if (RunControlTab * const tab = tabFor(rc)) + tab->behaviorOnOutput = mode; } void AppOutputPane::reRunRunControl() { - const int index = currentIndex(); - const RunControlTab &tab = m_runControlTabs.at(index); - QTC_ASSERT(tab.runControl, return); - QTC_ASSERT(index != -1 && !tab.runControl->isRunning(), return); + RunControlTab * const tab = currentTab(); + QTC_ASSERT(tab, return); + QTC_ASSERT(tab->runControl, return); + QTC_ASSERT(!tab->runControl->isRunning(), return); - handleOldOutput(tab.window); - tab.window->scrollToBottom(); - tab.runControl->initiateReStart(); + handleOldOutput(tab->window); + tab->window->scrollToBottom(); + tab->runControl->initiateReStart(); } void AppOutputPane::attachToRunControl() { - const int index = currentIndex(); - QTC_ASSERT(index != -1, return); - RunControl *rc = m_runControlTabs.at(index).runControl; - QTC_ASSERT(rc && rc->isRunning(), return); + RunControl * const rc = currentRunControl(); + QTC_ASSERT(rc, return); + QTC_ASSERT(rc->isRunning(), return); ExtensionSystem::Invoker<void>(debuggerPlugin(), "attachExternalApplication", rc); } void AppOutputPane::stopRunControl() { - const int index = currentIndex(); - QTC_ASSERT(index != -1, return); - RunControl *rc = m_runControlTabs.at(index).runControl; + RunControl * const rc = currentRunControl(); QTC_ASSERT(rc, return); if (rc->isRunning()) { @@ -632,22 +632,22 @@ QList<RunControl *> AppOutputPane::allRunControls() const void AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode) { - int index = indexOf(m_tabWidget->widget(tabIndex)); - QTC_ASSERT(index != -1, return); + QWidget * const tabWidget = m_tabWidget->widget(tabIndex); + RunControlTab *tab = tabFor(tabWidget); + QTC_ASSERT(tab, return); - RunControl *runControl = m_runControlTabs[index].runControl; - Core::OutputWindow *window = m_runControlTabs[index].window; + RunControl *runControl = tab->runControl; + Core::OutputWindow *window = tab->window; qCDebug(appOutputLog) << "AppOutputPane::closeTab tab" << tabIndex << runControl << window; // Prompt user to stop if (closeTabMode == CloseTabWithPrompt) { - QWidget *tabWidget = m_tabWidget->widget(tabIndex); if (runControl && runControl->isRunning() && !runControl->promptToStop()) return; // The event loop has run, thus the ordering might have changed, a tab might // have been closed, so do some strange things... tabIndex = m_tabWidget->indexOf(tabWidget); - index = indexOf(tabWidget); - if (tabIndex == -1 || index == -1) + tab = tabFor(tabWidget); + if (tabIndex == -1 || !tab) return; } @@ -656,7 +656,8 @@ void AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode) if (runControl) runControl->initiateFinish(); // Will self-destruct. - m_runControlTabs.removeAt(index); + Utils::erase(m_runControlTabs, [tab](const RunControlTab &t) { + return t.runControl == tab->runControl; }); updateCloseActions(); setFilteringEnabled(m_tabWidget->count() > 0); @@ -732,12 +733,11 @@ void AppOutputPane::enableButtons(const RunControl *rc) void AppOutputPane::tabChanged(int i) { - const int index = indexOf(m_tabWidget->widget(i)); - if (i != -1 && index != -1) { - const RunControlTab &controlTab = m_runControlTabs[index]; - controlTab.window->updateFilterProperties(filterText(), filterCaseSensitivity(), - filterUsesRegexp(), filterIsInverted()); - enableButtons(controlTab.runControl); + RunControlTab * const controlTab = tabFor(m_tabWidget->widget(i)); + if (i != -1 && controlTab) { + controlTab->window->updateFilterProperties(filterText(), filterCaseSensitivity(), + filterUsesRegexp(), filterIsInverted()); + enableButtons(controlTab->runControl); } else { enableDefaultButtons(); } @@ -747,12 +747,15 @@ void AppOutputPane::contextMenuRequested(const QPoint &pos, int index) { const QList<QAction *> actions = {m_closeCurrentTabAction, m_closeAllTabsAction, m_closeOtherTabsAction}; QAction *action = QMenu::exec(actions, m_tabWidget->mapToGlobal(pos), nullptr, m_tabWidget); - const int currentIdx = index != -1 ? index : currentIndex(); + if (action == m_closeAllTabsAction) { + closeTabs(AppOutputPane::CloseTabWithPrompt); + return; + } + + const int currentIdx = index != -1 ? index : m_tabWidget->currentIndex(); if (action == m_closeCurrentTabAction) { if (currentIdx >= 0) closeTab(currentIdx); - } else if (action == m_closeAllTabsAction) { - closeTabs(AppOutputPane::CloseTabWithPrompt); } else if (action == m_closeOtherTabsAction) { for (int t = m_tabWidget->count() - 1; t >= 0; t--) if (t != currentIdx) @@ -781,16 +784,17 @@ void AppOutputPane::slotRunControlFinished() void AppOutputPane::slotRunControlFinished2(RunControl *sender) { - const int senderIndex = indexOf(sender); + const RunControlTab * const tab = tabFor(sender); // This slot is queued, so the stop() call in closeTab might lead to this slot, after closeTab already cleaned up - if (senderIndex == -1) + if (!tab) return; // Enable buttons for current RunControl *current = currentRunControl(); - qCDebug(appOutputLog) << "AppOutputPane::runControlFinished" << sender << senderIndex + qCDebug(appOutputLog) << "AppOutputPane::runControlFinished" << sender + << m_tabWidget->indexOf(tab->window) << "current" << current << m_runControlTabs.size(); if (current && current == sender) |