diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts
index 5bffaae6359..16a28c2f650 100644
--- a/share/qtcreator/translations/qtcreator_ru.ts
+++ b/share/qtcreator/translations/qtcreator_ru.ts
@@ -130,12 +130,71 @@
Анализатор
+
+ AnchorButtons
+
+ Anchor item to the top.
+ Привязка элемента к верхнему краю.
+
+
+ Anchor item to the bottom.
+ Привязка элемента к нижнему краю.
+
+
+ Anchor item to the left.
+ Привязка элемента к левому краю.
+
+
+ Anchor item to the right.
+ Привязка элемента к правому краю.
+
+
+ Fill parent item.
+ Заполнить родительский элемент.
+
+
+ Anchor item vertically.
+ Вертикальная привязка элемента.
+
+
+ Anchor item horizontally.
+ Горизонтальная привязка элемента.
+
+
AnchorRow
Target
Цель
+
+ Margin
+ Внешний отступ
+
+
+ Anchor to the top of the target.
+ Привязка к верхнему краю цели.
+
+
+ Anchor to the left of the target.
+ Привязка к левому краю цели.
+
+
+ Anchor to the vertical center of the target.
+ Привязка к вертикальному центру цели.
+
+
+ Anchor to the horizontal center of the target.
+ Привязка к горизонтальному центру цели.
+
+
+ Anchor to the bottom of the target.
+ Привязка к нижнему краю цели.
+
+
+ Anchor to the right of the target.
+ Привязка к правому краю цели.
+
Android::AndroidBuildApkStep
@@ -1903,7 +1962,7 @@ Install an SDK of at least API version %1.
%1 tests passed.
- %1 тестов прошли успешно.
+ %1 тестов прошло успешно.
No errors detected.
@@ -3241,7 +3300,7 @@ Warning: this is an experimental feature and might lead to failing to execute th
The kit has a Qt version, but no C++ compiler.
- У комплекта задан профил Qt, но нет компилятора C++.
+ У комплекта задан профиль Qt, но нет компилятора C++.
Name:
@@ -4476,7 +4535,7 @@ For example, "Revision: 15" will leave the branch at revision 15.
A seed of 0 means no randomization. A value of 1 uses the current time any other value is used as random seed generator.
- 0 отключает случайный порядок. Значение 1 использует текущее время, любой другое используется для генерации случайной последовательности.
+ 0 отключает случайный порядок. Значение 1 использует текущее время, любое другое используется для генерации случайной последовательности.
Catch or ignore system errors.
@@ -7116,6 +7175,10 @@ p, li { white-space: pre-wrap; }
Recent
Недавний
+
+ Open Color Dialog
+ Открыть выбор цвета
+
Defines the start angle for the conical gradient. The value is in degrees (0-360).
Определяет начальный угол для конического градиента. Значение в градусах от 0 до 360.
@@ -9120,11 +9183,11 @@ Do you want to kill it?
Cycle Mode Selector Styles
- Зациклить стили режима выбора
+ Зациклить стили режима выбора
Mode Selector Style
- Стиль режима выбора
+ Стиль режима выбора
Icons and Text
@@ -16270,7 +16333,7 @@ You can choose another communication channel here, such as a serial line or cust
Creation Time in ms
- Время создания в мс
+ Время создания, мс
<empty>
@@ -17359,7 +17422,7 @@ Rebuilding the project might help.
Drag Margin
- Поле перетаскивания
+ Зона перетаскивания
Defines the distance from the screen edge within which drag actions will open the drawer.
@@ -18417,6 +18480,10 @@ will also disable the following plugins:
Determines whether the Flickable will give a feeling that the edges of the view are soft, rather than a hard physical boundary.
Определяет, будет ли Flickable создавать ощущение, что края у вида мягкие, а не жесткие физические границы.
+
+ Describes whether the user can interact with the Flickable. A user cannot drag or flick a Flickable that is not interactive.
+ Определяет, может ли пользователь влиять на Flickable. Пользователь не может перетягивать или сдвигать Flickable, если он не интерактивен.
+
Press delay
Задержка нажатия
@@ -18443,7 +18510,7 @@ will also disable the following plugins:
Margins
- Отступы
+ Внешние отступы
Flick direction
@@ -20499,7 +20566,7 @@ Commit now?
DCommit
- Дельта фиксация (dcommit)
+ Дельта фиксация (dcommit)
Manage Remotes...
@@ -23443,7 +23510,7 @@ Error: %5
Margins
- Отступы
+ Внешние отступы
Row span
@@ -23954,7 +24021,7 @@ Error: %5
MarginSection
Margin
- Поле
+ Внешний отступ
Vertical
@@ -23998,7 +24065,7 @@ Error: %5
Margins
- Отступы
+ Внешние отступы
The margins around the item.
@@ -25088,7 +25155,7 @@ Error: %5
Drag margin
- Перетаскиваемый край
+ Зона перетаскивания
Flick deceleration
@@ -25795,12 +25862,12 @@ Error: %5
Self Samples
- Собственных семплов
+ Собственных семплов
Self in Percent
х.з. как переводить
- Собственное в процентах
+ Собственное в процентах
@@ -26741,7 +26808,7 @@ Error: %5
Build/Deployment canceled
- Сборка/разворачивание отменено
+ Сборка/развёртывание отменено
When executing step "%1"
@@ -26754,7 +26821,7 @@ Error: %5
Deployment
Category for deployment issues listed under 'Issues'
- Разворачивание
+ Развёртывание
Autotests
@@ -26763,11 +26830,11 @@ Error: %5
Canceled build/deployment.
- Сборка/разворачивание было отменено.
+ Сборка/развёртывание было отменено.
Error while building/deploying project %1 (kit: %2)
- Ошибка при сборке/разворачивании проекта %1 (комплект: %2)
+ Ошибка при сборке/развёртывании проекта %1 (комплект: %2)
The kit %1 has configuration issues which might be the root cause for this problem.
@@ -27022,21 +27089,21 @@ Error: %5
Deploy
Display name of the deploy build step list. Used as part of the labels in the project window.
- Разваорачивание
+ Развёртывание
Deploy locally
Default DeployConfiguration display name
- Локальное разворачивание
+ Локальное развёртывание
Deploy Configuration
Display name of the default deploy configuration
- Конфигурация разворачивания
+ Конфигурация развёртывания
Deploy Settings
- Настройки разворачивания
+ Настройки развёртывания
@@ -27054,7 +27121,7 @@ Error: %5
ProjectExplorer::DeploymentDataView
Files to deploy:
- Разворачиваемые файлы:
+ Файлы для развёртывания:
@@ -27360,11 +27427,11 @@ Error: %5
Append Path...
- Добавить после пути...
+ Добавить после пути...
Prepend Path...
- Добавить перед путём...
+ Добавить перед путём...
&Batch Edit...
@@ -27987,7 +28054,7 @@ Excluding: %2
Synchronize active kit, build, and deploy configuration between projects.
- Сихронизировать у проектов текущий комплект и конфигурации сборки и разворачивания.
+ Сихронизировать у проектов текущий комплект и конфигурации сборки и развёртывания.
@@ -28492,7 +28559,7 @@ What should Qt Creator do now?
Deploy
- Разворачивание
+ Развёртывание
Run
@@ -28520,7 +28587,7 @@ What should Qt Creator do now?
<b>Deploy:</b> %1
- <b>Разворачивание:</b> %1
+ <b>Развёртывание:</b> %1
<b>Run:</b> %1
@@ -28544,7 +28611,7 @@ What should Qt Creator do now?
Deploy: <b>%1</b><br/>
- Разворачивание: <b>%1</b><br/>
+ Развёртывание: <b>%1</b><br/>
Run: <b>%1</b><br/>
@@ -28687,11 +28754,11 @@ What should Qt Creator do now?
Always build project before deploying it
- Всегда собирать проект перед разворачиванием
+ Всегда собирать проект перед развёртыванием
Always deploy project before running it
- Всегда разворачивать проект перед запуском
+ Всегда развёртывать проект перед запуском
Always ask before stopping applications
@@ -29053,7 +29120,7 @@ to project "%2".
Deployment
- Разворачивание
+ Развёртывание
Method:
@@ -29082,7 +29149,7 @@ to project "%2".
Cancel Build && Remove Deploy Configuration
- Отменить сборку и удалить конфигурацию разворачивания
+ Отменить сборку и удалить конфигурацию развёртывания
Do Not Remove
@@ -29090,27 +29157,27 @@ to project "%2".
Remove Deploy Configuration %1?
- Удаление конфигурации разворачивания %1
+ Удаление конфигурации развёртывания %1
The deploy configuration <b>%1</b> is currently being built.
- В данный момент идёт сборка с использованием конфигурации разворачивания <b>%1</b>.
+ В данный момент идёт сборка с использованием конфигурации развёртывания <b>%1</b>.
Do you want to cancel the build process and remove the Deploy Configuration anyway?
- Остановить процесс сборки и удалить конфигурацию разворачивания?
+ Остановить процесс сборки и удалить конфигурацию развёртывания?
Remove Deploy Configuration?
- Удаление конфигурации разворачивания
+ Удаление конфигурации развёртывания
Do you really want to delete deploy configuration <b>%1</b>?
- Желаете удалить конфигурацию разворачивания <b>%1</b>?
+ Желаете удалить конфигурацию развёртывания <b>%1</b>?
New name for deploy configuration <b>%1</b>:
- Новое название конфигурации разворачивания <b>%1</b>:
+ Новое название конфигурации развёртывания <b>%1</b>:
@@ -30027,7 +30094,7 @@ to project "%2".
QML File (Qt Quick 2)
- Файл QML (Qt Quck 2)
+ Файл QML (Qt Quick 2)
Creates a scratch buffer using a temporary file.
@@ -31178,7 +31245,7 @@ Please close all running instances of your application before starting a build.<
Deploy configurations:
- Конфигурации разворачивания:
+ Конфигурации развёртывания:
Run configurations:
@@ -31581,7 +31648,7 @@ Rename %2 to %3 anyway?
Run Without Deployment
- Запустить без разворачивания
+ Запустить без развёртывания
New Subproject...
@@ -33828,7 +33895,7 @@ Neither the path to the library nor the path to its includes is added to the .pr
Qmake has subtle bugs that can be triggered if source and build directory are not at the same level.
- Qmake содержит ошибку, возникающую при нахождении каталогов сборки и исходников на разных уровнях.
+ Qmake содержит ошибку, которая может проявляться, если каталоги сборки и исходников находятся на разных уровнях.
Run qmake on every build
@@ -38341,7 +38408,7 @@ Saving failed.
Qnx::Internal::QnxDeployQtLibrariesDialog
Qt library to deploy:
- Разворачиваемая Qt:
+ Библиотека Qt для развёртывания:
Deploy
@@ -38765,6 +38832,10 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
Type
Тип
+
+ Change the type of this item.
+ Меняет тип этого элемента.
+
id
идентификатор
@@ -42948,7 +43019,7 @@ Specifies how backspace interacts with indentation.
Timeout in ms:
- Таймаут в мс:
+ Таймаут, мс:
Inserts the common prefix of available completion items.
@@ -47925,7 +47996,7 @@ What do you want to do?
Multi-paradigm language for creating highly dynamic applications.
- Многопарадигмый язый для создания высокодинамичных приложений.
+ Мультипарадигменный язык для создания высокодинамичных приложений.
Run your concepts and prototypes on your final hardware.
diff --git a/src/libs/utils/touchbar/touchbar_mac.mm b/src/libs/utils/touchbar/touchbar_mac.mm
index ee5a45bf720..dfaf6700873 100644
--- a/src/libs/utils/touchbar/touchbar_mac.mm
+++ b/src/libs/utils/touchbar/touchbar_mac.mm
@@ -177,7 +177,7 @@ static NSImage *iconToTemplateNSImage(const QIcon &icon)
{
self = [super init];
[self setButtonType:NSButtonTypeMomentaryPushIn];
- self.bezelStyle = NSRoundedBezelStyle;
+ self.bezelStyle = NSBezelStyleRounded;
self.target = self;
self.action = @selector(trigger:);
_qaction = qaction;
@@ -208,7 +208,7 @@ static NSImage *iconToTemplateNSImage(const QIcon &icon)
{
self = [super init];
[self setButtonType:NSButtonTypeMomentaryPushIn];
- self.bezelStyle = NSRoundedBezelStyle;
+ self.bezelStyle = NSBezelStyleRounded;
self.target = self;
self.action = @selector(trigger:);
_parent = parent;
diff --git a/src/plugins/clangtools/CMakeLists.txt b/src/plugins/clangtools/CMakeLists.txt
index 93195bdfb9b..f5f2c2a84c9 100644
--- a/src/plugins/clangtools/CMakeLists.txt
+++ b/src/plugins/clangtools/CMakeLists.txt
@@ -14,7 +14,6 @@ add_qtc_plugin(ClangTools
clangfixitsrefactoringchanges.cpp clangfixitsrefactoringchanges.h
clangselectablefilesdialog.cpp clangselectablefilesdialog.h clangselectablefilesdialog.ui
clangtidyclazyrunner.cpp clangtidyclazyrunner.h
- clangtidyclazytool.cpp clangtidyclazytool.h
clangtool.cpp clangtool.h
clangtoolruncontrol.cpp clangtoolruncontrol.h
clangtoolrunner.cpp clangtoolrunner.h
@@ -29,6 +28,7 @@ add_qtc_plugin(ClangTools
clangtoolsprojectsettingswidget.cpp clangtoolsprojectsettingswidget.h clangtoolsprojectsettingswidget.ui
clangtoolssettings.cpp clangtoolssettings.h
clangtoolsutils.cpp clangtoolsutils.h
+ runsettingswidget.cpp runsettingswidget.h runsettingswidget.ui
settingswidget.cpp settingswidget.h settingswidget.ui
)
diff --git a/src/plugins/clangtools/clangselectablefilesdialog.cpp b/src/plugins/clangtools/clangselectablefilesdialog.cpp
index c9fce5552ff..6541ca46bc5 100644
--- a/src/plugins/clangtools/clangselectablefilesdialog.cpp
+++ b/src/plugins/clangtools/clangselectablefilesdialog.cpp
@@ -266,16 +266,6 @@ private:
}
};
-enum { GlobalSettings , CustomSettings };
-
-static Core::Id diagnosticConfiguration(ClangToolsProjectSettings *settings)
-{
- Core::Id id = settings->diagnosticConfig();
- if (id.isValid())
- return id;
- return ClangToolsSettings::instance()->savedDiagnosticConfigId();
-}
-
SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
const FileInfos &allFileInfos)
: QDialog(nullptr)
@@ -292,36 +282,7 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
m_ui->buttons->setStandardButtons(QDialogButtonBox::Cancel);
m_ui->buttons->addButton(m_analyzeButton, QDialogButtonBox::AcceptRole);
- CppTools::ClangDiagnosticConfigsSelectionWidget *diagnosticWidget = m_ui->diagnosticWidget;
-
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
- m_customDiagnosticConfig = diagnosticConfiguration(settings);
-
- if (settings->useGlobalSettings()) {
- m_ui->globalOrCustom->setCurrentIndex(GlobalSettings);
- diagnosticWidget->refresh(ClangToolsSettings::instance()->savedDiagnosticConfigId());
- diagnosticWidget->setEnabled(false);
- } else {
- m_ui->globalOrCustom->setCurrentIndex(CustomSettings);
- diagnosticWidget->refresh(m_customDiagnosticConfig);
- diagnosticWidget->setEnabled(true);
- }
-
- connect(m_ui->globalOrCustom,
- QOverload::of(&QComboBox::currentIndexChanged),
- [=](int index){
- diagnosticWidget->setEnabled(index == CustomSettings);
- if (index == CustomSettings)
- diagnosticWidget->refresh(m_customDiagnosticConfig);
- else
- diagnosticWidget->refresh(ClangToolsSettings::instance()->savedDiagnosticConfigId());
- });
- connect(diagnosticWidget,
- &ClangDiagnosticConfigsSelectionWidget::currentConfigChanged,
- [this](const Core::Id ¤tConfigId) {
- if (m_ui->globalOrCustom->currentIndex() == CustomSettings)
- m_customDiagnosticConfig = currentConfigId;
- });
// Restore selection
if (settings->selectedDirs().isEmpty() && settings->selectedFiles().isEmpty())
@@ -333,16 +294,6 @@ SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo,
connect(m_filesModel.get(), &QAbstractItemModel::dataChanged, [this]() {
m_analyzeButton->setEnabled(m_filesModel->hasCheckedFiles());
});
-
- connect(CppTools::codeModelSettings().data(), &CppTools::CppCodeModelSettings::changed,
- this, [=]() {
- if (m_ui->globalOrCustom->currentIndex() == CustomSettings) {
- diagnosticWidget->refresh(m_customDiagnosticConfig);
- } else {
- diagnosticWidget->refresh(
- ClangToolsSettings::instance()->savedDiagnosticConfigId());
- }
- });
}
SelectableFilesDialog::~SelectableFilesDialog() = default;
@@ -356,11 +307,6 @@ void SelectableFilesDialog::accept()
{
ClangToolsProjectSettings *settings = ClangToolsProjectSettingsManager::getSettings(m_project);
- // Save diagnostic configuration
- settings->setUseGlobalSettings(m_ui->globalOrCustom->currentIndex() == GlobalSettings);
- settings->setDiagnosticConfig(m_customDiagnosticConfig);
-
- // Save file selection
QSet checkedDirs;
QSet checkedFiles;
m_filesModel->minimalSelection(checkedDirs, checkedFiles);
diff --git a/src/plugins/clangtools/clangselectablefilesdialog.ui b/src/plugins/clangtools/clangselectablefilesdialog.ui
index 267b36364a2..834f3fc1894 100644
--- a/src/plugins/clangtools/clangselectablefilesdialog.ui
+++ b/src/plugins/clangtools/clangselectablefilesdialog.ui
@@ -11,66 +11,14 @@
- Analyzer Configuration
+ Files to Analyze
-
-
-
- General
+
+
+ true
-
-
-
-
-
-
-
-
-
-
- Global Settings
-
-
- -
-
- Custom Settings
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
- Files to Analyze
-
-
-
-
-
-
- true
-
-
-
-
-
@@ -85,13 +33,6 @@
-
-
- CppTools::ClangDiagnosticConfigsSelectionWidget
- QWidget
- cpptools/clangdiagnosticconfigsselectionwidget.h
-
-
diff --git a/src/plugins/clangtools/clangtidyclazytool.cpp b/src/plugins/clangtools/clangtidyclazytool.cpp
deleted file mode 100644
index 85be64da49c..00000000000
--- a/src/plugins/clangtools/clangtidyclazytool.cpp
+++ /dev/null
@@ -1,569 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "clangtidyclazytool.h"
-
-#include "clangfixitsrefactoringchanges.h"
-#include "clangselectablefilesdialog.h"
-#include "clangtoolruncontrol.h"
-#include "clangtoolsconstants.h"
-#include "clangtoolsdiagnosticmodel.h"
-#include "clangtoolslogfilereader.h"
-#include "clangtoolsdiagnosticview.h"
-#include "clangtoolsprojectsettings.h"
-#include "clangtoolssettings.h"
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-
-using namespace Core;
-using namespace CppTools;
-using namespace Debugger;
-using namespace ProjectExplorer;
-using namespace Utils;
-
-namespace ClangTools {
-namespace Internal {
-
-static ClangTidyClazyTool *s_instance;
-
-class ApplyFixIts
-{
-public:
- class RefactoringFileInfo
- {
- public:
- bool isValid() const { return file.isValid(); }
-
- FixitsRefactoringFile file;
- QVector diagnosticItems;
- bool hasScheduledFixits = false;
- };
-
- ApplyFixIts(const QVector &diagnosticItems)
- {
- for (DiagnosticItem *diagnosticItem : diagnosticItems) {
- const QString &filePath = diagnosticItem->diagnostic().location.filePath;
- QTC_ASSERT(!filePath.isEmpty(), continue);
-
- // Get or create refactoring file
- RefactoringFileInfo &fileInfo = m_refactoringFileInfos[filePath];
- if (!fileInfo.isValid())
- fileInfo.file = FixitsRefactoringFile(filePath);
-
- // Append item
- fileInfo.diagnosticItems += diagnosticItem;
- if (diagnosticItem->fixItStatus() == FixitStatus::Scheduled)
- fileInfo.hasScheduledFixits = true;
- }
- }
-
- static void addFixitOperations(DiagnosticItem *diagnosticItem,
- const FixitsRefactoringFile &file, bool apply)
- {
- if (!diagnosticItem->hasNewFixIts())
- return;
-
- // Did we already created the fixit operations?
- ReplacementOperations currentOps = diagnosticItem->fixitOperations();
- if (!currentOps.isEmpty()) {
- for (ReplacementOperation *op : currentOps)
- op->apply = apply;
- return;
- }
-
- // Collect/construct the fixit operations
- ReplacementOperations replacements;
-
- for (const ExplainingStep &step : diagnosticItem->diagnostic().explainingSteps) {
- if (!step.isFixIt)
- continue;
-
- const Debugger::DiagnosticLocation start = step.ranges.first();
- const Debugger::DiagnosticLocation end = step.ranges.last();
- const int startPos = file.position(start.filePath, start.line, start.column);
- const int endPos = file.position(start.filePath, end.line, end.column);
-
- auto op = new ReplacementOperation;
- op->pos = startPos;
- op->length = endPos - startPos;
- op->text = step.message;
- op->fileName = start.filePath;
- op->apply = apply;
-
- replacements += op;
- }
-
- diagnosticItem->setFixitOperations(replacements);
- }
-
- void apply(ClangToolsDiagnosticModel *model)
- {
- for (auto it = m_refactoringFileInfos.begin(); it != m_refactoringFileInfos.end(); ++it) {
- RefactoringFileInfo &fileInfo = it.value();
-
- QVector itemsScheduledOrSchedulable;
- QVector itemsScheduled;
- QVector itemsSchedulable;
-
- // Construct refactoring operations
- for (DiagnosticItem *diagnosticItem : fileInfo.diagnosticItems) {
- const FixitStatus fixItStatus = diagnosticItem->fixItStatus();
-
- const bool isScheduled = fixItStatus == FixitStatus::Scheduled;
- const bool isSchedulable = fileInfo.hasScheduledFixits
- && fixItStatus == FixitStatus::NotScheduled;
-
- if (isScheduled || isSchedulable) {
- addFixitOperations(diagnosticItem, fileInfo.file, isScheduled);
- itemsScheduledOrSchedulable += diagnosticItem;
- if (isScheduled)
- itemsScheduled += diagnosticItem;
- else
- itemsSchedulable += diagnosticItem;
- }
- }
-
- // Collect replacements
- ReplacementOperations ops;
- for (DiagnosticItem *item : itemsScheduledOrSchedulable)
- ops += item->fixitOperations();
-
- if (ops.empty())
- continue;
-
- // Apply file
- QVector itemsApplied;
- QVector itemsFailedToApply;
- QVector itemsInvalidated;
-
- fileInfo.file.setReplacements(ops);
- model->removeWatchedPath(ops.first()->fileName);
- if (fileInfo.file.apply()) {
- itemsApplied = itemsScheduled;
- } else {
- itemsFailedToApply = itemsScheduled;
- itemsInvalidated = itemsSchedulable;
- }
- model->addWatchedPath(ops.first()->fileName);
-
- // Update DiagnosticItem state
- for (DiagnosticItem *diagnosticItem : itemsScheduled)
- diagnosticItem->setFixItStatus(FixitStatus::Applied);
- for (DiagnosticItem *diagnosticItem : itemsFailedToApply)
- diagnosticItem->setFixItStatus(FixitStatus::FailedToApply);
- for (DiagnosticItem *diagnosticItem : itemsInvalidated)
- diagnosticItem->setFixItStatus(FixitStatus::Invalidated);
- }
- }
-
-private:
- QMap m_refactoringFileInfos;
-};
-
-ClangTidyClazyTool::ClangTidyClazyTool()
- : ClangTool("Clang-Tidy and Clazy")
-{
- setObjectName("ClangTidyClazyTool");
- s_instance = this;
-
- m_diagnosticFilterModel = new DiagnosticFilterModel(this);
- m_diagnosticFilterModel->setSourceModel(m_diagnosticModel);
- m_diagnosticFilterModel->setDynamicSortFilter(true);
-
- m_diagnosticView = new DiagnosticView;
- initDiagnosticView();
- m_diagnosticView->setModel(m_diagnosticFilterModel);
- m_diagnosticView->setSortingEnabled(true);
- m_diagnosticView->sortByColumn(Debugger::DetailedErrorView::DiagnosticColumn,
- Qt::AscendingOrder);
- m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
- m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Diagnostics"));
-
- foreach (auto * const model,
- QList({m_diagnosticModel, m_diagnosticFilterModel})) {
- connect(model, &QAbstractItemModel::rowsInserted,
- this, &ClangTidyClazyTool::handleStateUpdate);
- connect(model, &QAbstractItemModel::rowsRemoved,
- this, &ClangTidyClazyTool::handleStateUpdate);
- connect(model, &QAbstractItemModel::modelReset,
- this, &ClangTidyClazyTool::handleStateUpdate);
- connect(model, &QAbstractItemModel::layoutChanged, // For QSortFilterProxyModel::invalidate()
- this, &ClangTidyClazyTool::handleStateUpdate);
- }
-
- // Go to previous diagnostic
- auto action = new QAction(this);
- action->setDisabled(true);
- action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
- action->setToolTip(tr("Go to previous diagnostic."));
- connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goBack);
- m_goBack = action;
-
- // Go to next diagnostic
- action = new QAction(this);
- action->setDisabled(true);
- action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
- action->setToolTip(tr("Go to next diagnostic."));
- connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goNext);
- m_goNext = action;
-
- // Load diagnostics from file
- action = new QAction(this);
- action->setIcon(Utils::Icons::OPENFILE_TOOLBAR.icon());
- action->setToolTip(tr("Load Diagnostics from YAML Files exported with \"-export-fixes\"."));
- connect(action, &QAction::triggered, this, &ClangTidyClazyTool::loadDiagnosticsFromFiles);
- m_loadExported = action;
-
- // Clear data
- action = new QAction(this);
- action->setDisabled(true);
- action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
- action->setToolTip(tr("Clear"));
- connect(action, &QAction::triggered, [this](){
- m_clear->setEnabled(false);
- m_diagnosticModel->clear();
- Debugger::showPermanentStatusMessage(QString());
- });
- m_clear = action;
-
- // Expand/Collapse
- action = new QAction(this);
- action->setDisabled(true);
- action->setCheckable(true);
- action->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon());
- action->setToolTip(tr("Expand All"));
- connect(action, &QAction::toggled, [this](bool checked){
- if (checked) {
- m_expandCollapse->setToolTip(tr("Collapse All"));
- m_diagnosticView->expandAll();
- } else {
- m_expandCollapse->setToolTip(tr("Expand All"));
- m_diagnosticView->collapseAll();
- }
- });
- m_expandCollapse = action;
-
- // Filter line edit
- m_filterLineEdit = new Utils::FancyLineEdit();
- m_filterLineEdit->setFiltering(true);
- m_filterLineEdit->setPlaceholderText(tr("Filter Diagnostics"));
- m_filterLineEdit->setHistoryCompleter("CppTools.ClangTidyClazyIssueFilter", true);
- connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, [this](const QString &filter) {
- m_diagnosticFilterModel->setFilterRegExp(
- QRegExp(filter, Qt::CaseSensitive, QRegExp::WildcardUnix));
- });
-
- // Apply fixits button
- m_applyFixitsButton = new QToolButton;
- m_applyFixitsButton->setText(tr("Apply Fixits"));
- m_applyFixitsButton->setEnabled(false);
- connect(m_diagnosticModel,
- &ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
- [this](int c) {
- m_applyFixitsButton->setEnabled(c);
- static_cast(m_diagnosticView.data())->setSelectedFixItsCount(c);
- });
- connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
- QVector diagnosticItems;
- m_diagnosticModel->forItemsAtLevel<2>([&](DiagnosticItem *item){
- diagnosticItems += item;
- });
-
- ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
- });
-
- ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
- const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
- "Clang project to search for diagnostics.");
-
- m_perspective.addWindow(m_diagnosticView, Perspective::SplitVertical, nullptr);
-
- action = new QAction(tr("Clang-Tidy and Clazy..."), this);
- action->setToolTip(toolTip);
- menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
- Debugger::Constants::G_ANALYZER_TOOLS);
- QObject::connect(action, &QAction::triggered, this, [this]() {
- startTool(ClangTidyClazyTool::FileSelection::AskUser);
- });
- QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
- QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
- action->setEnabled(m_startAction->isEnabled());
- });
-
- QObject::connect(m_startOnCurrentFileAction, &QAction::triggered, this, [this] {
- startTool(ClangTidyClazyTool::FileSelection::CurrentFile);
- });
-
- m_perspective.addToolBarAction(m_startAction);
- m_perspective.addToolBarAction(m_startOnCurrentFileAction);
- m_perspective.addToolBarAction(m_stopAction);
- m_perspective.addToolBarAction(m_loadExported);
- m_perspective.addToolBarAction(m_clear);
- m_perspective.addToolBarAction(m_goBack);
- m_perspective.addToolBarAction(m_goNext);
- m_perspective.addToolBarAction(m_expandCollapse);
- m_perspective.addToolBarWidget(m_filterLineEdit);
- m_perspective.addToolBarWidget(m_applyFixitsButton);
-
- updateRunActions();
-
- connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
- this, &ClangTidyClazyTool::updateRunActions);
-
-}
-
-ClangTidyClazyTool *ClangTidyClazyTool::instance()
-{
- return s_instance;
-}
-
-static ClangDiagnosticConfig getDiagnosticConfig(Project *project)
-{
- ClangToolsProjectSettings *projectSettings = ClangToolsProjectSettingsManager::getSettings(
- project);
-
- Core::Id diagnosticConfigId;
- if (projectSettings->useGlobalSettings())
- diagnosticConfigId = ClangToolsSettings::instance()->savedDiagnosticConfigId();
- else
- diagnosticConfigId = projectSettings->diagnosticConfig();
-
- const ClangDiagnosticConfigsModel configsModel(
- CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
-
- QTC_ASSERT(configsModel.hasConfigWithId(diagnosticConfigId), return ClangDiagnosticConfig());
- return configsModel.configWithId(diagnosticConfigId);
-}
-
-void ClangTidyClazyTool::startTool(FileSelection fileSelection)
-{
- Project *project = SessionManager::startupProject();
- QTC_ASSERT(project, return);
- QTC_ASSERT(project->activeTarget(), return);
-
- auto runControl = new RunControl(Constants::CLANGTIDYCLAZY_RUN_MODE);
- runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
- runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
- runControl->setTarget(project->activeTarget());
-
- const FileInfos fileInfos = collectFileInfos(project, fileSelection);
- if (fileInfos.empty())
- return;
-
- const bool preventBuild = fileSelection == FileSelection::CurrentFile;
- auto clangTool = new ClangToolRunWorker(runControl,
- getDiagnosticConfig(project),
- fileInfos,
- preventBuild);
-
- m_stopAction->disconnect();
- connect(m_stopAction, &QAction::triggered, runControl, [runControl] {
- runControl->appendMessage(tr("Clang-Tidy and Clazy tool stopped by user."),
- NormalMessageFormat);
- runControl->initiateStop();
- });
-
- connect(runControl, &RunControl::stopped, this, [this, clangTool] {
- bool success = clangTool->success();
- setToolBusy(false);
- m_running = false;
- handleStateUpdate();
- updateRunActions();
- emit finished(success);
- });
-
- m_perspective.select();
-
- m_diagnosticModel->clear();
-
- setToolBusy(true);
- m_diagnosticFilterModel->setProject(project);
- m_running = true;
- handleStateUpdate();
- updateRunActions();
-
- ProjectExplorerPlugin::startRunControl(runControl);
-}
-
-void ClangTidyClazyTool::updateRunActions()
-{
- if (m_toolBusy) {
- QString tooltipText = tr("Clang-Tidy and Clazy are still running.");
-
- m_startAction->setEnabled(false);
- m_startAction->setToolTip(tooltipText);
-
- m_startOnCurrentFileAction->setEnabled(false);
- m_startOnCurrentFileAction->setToolTip(tooltipText);
-
- m_stopAction->setEnabled(true);
- m_loadExported->setEnabled(false);
- m_clear->setEnabled(false);
- } else {
- QString toolTipStart = m_startAction->text();
- QString toolTipStartOnCurrentFile = m_startOnCurrentFileAction->text();
-
- Project *project = SessionManager::startupProject();
- Target *target = project ? project->activeTarget() : nullptr;
- const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
- bool canRun = target && project->projectLanguages().contains(cxx)
- && ToolChainKitAspect::toolChain(target->kit(), cxx);
- if (!canRun)
- toolTipStart = toolTipStartOnCurrentFile = tr("This is not a C/C++ project.");
-
- m_startAction->setEnabled(canRun);
- m_startAction->setToolTip(toolTipStart);
-
- m_startOnCurrentFileAction->setEnabled(canRun);
- m_startOnCurrentFileAction->setToolTip(toolTipStartOnCurrentFile);
-
- m_stopAction->setEnabled(false);
- m_loadExported->setEnabled(true);
- m_clear->setEnabled(m_diagnosticModel->diagnostics().count());
- }
-}
-
-void ClangTidyClazyTool::loadDiagnosticsFromFiles()
-{
- // Ask user for files
- const QStringList filePaths
- = QFileDialog::getOpenFileNames(Core::ICore::mainWindow(),
- tr("Select YAML Files with Diagnostics"),
- QDir::homePath(),
- tr("YAML Files (*.yml *.yaml);;All Files (*)"));
- if (filePaths.isEmpty())
- return;
-
- // Load files
- Diagnostics diagnostics;
- QString errors;
- for (const QString &filePath : filePaths) {
- QString currentError;
- diagnostics << readExportedDiagnostics(Utils::FilePath::fromString(filePath),
- {},
- ¤tError);
-
- if (!currentError.isEmpty()) {
- if (!errors.isEmpty())
- errors.append("\n");
- errors.append(currentError);
- }
- }
-
- // Show errors
- if (!errors.isEmpty())
- AsynchronousMessageBox::critical(tr("Error Loading Diagnostics"), errors);
-
- // Show imported
- m_diagnosticModel->clear();
- onNewDiagnosticsAvailable(diagnostics);
-}
-
-void ClangTidyClazyTool::handleStateUpdate()
-{
- QTC_ASSERT(m_goBack, return);
- QTC_ASSERT(m_goNext, return);
- QTC_ASSERT(m_diagnosticModel, return);
- QTC_ASSERT(m_diagnosticFilterModel, return);
-
- const int issuesFound = m_diagnosticModel->diagnostics().count();
- const int issuesVisible = m_diagnosticFilterModel->rowCount();
- m_goBack->setEnabled(issuesVisible > 1);
- m_goNext->setEnabled(issuesVisible > 1);
- m_clear->setEnabled(issuesFound > 0);
- m_expandCollapse->setEnabled(issuesVisible);
-
- m_loadExported->setEnabled(!m_running);
-
- QString message;
- if (m_running) {
- if (issuesFound)
- message = tr("Running - %n diagnostics", nullptr, issuesFound);
- else
- message = tr("Running - No diagnostics");
- } else {
- if (issuesFound)
- message = tr("Finished - %n diagnostics", nullptr, issuesFound);
- else
- message = tr("Finished - No diagnostics");
- }
-
- Debugger::showPermanentStatusMessage(message);
-}
-
-Diagnostics ClangTidyClazyTool::read(OutputFileFormat outputFileFormat,
- const QString &logFilePath,
- const QString &mainFilePath,
- const QSet &projectFiles,
- QString *errorMessage) const
-{
- const auto acceptFromFilePath = [projectFiles](const Utils::FilePath &filePath) {
- return projectFiles.contains(filePath);
- };
-
- if (outputFileFormat == OutputFileFormat::Yaml) {
- return readExportedDiagnostics(Utils::FilePath::fromString(logFilePath),
- acceptFromFilePath,
- errorMessage);
- }
- return readSerializedDiagnostics(Utils::FilePath::fromString(logFilePath),
- Utils::FilePath::fromString(mainFilePath),
- acceptFromFilePath,
- errorMessage);
-}
-
-void ClangTidyClazyTool::onNewDiagnosticsAvailable(const Diagnostics &diagnostics)
-{
- ClangTool::onNewDiagnosticsAvailable(diagnostics);
- if (!m_diagnosticFilterModel->filterRegExp().pattern().isEmpty())
- m_diagnosticFilterModel->invalidateFilter();
-}
-
-} // namespace Internal
-} // namespace ClangTools
-
diff --git a/src/plugins/clangtools/clangtidyclazytool.h b/src/plugins/clangtools/clangtidyclazytool.h
deleted file mode 100644
index be964381174..00000000000
--- a/src/plugins/clangtools/clangtidyclazytool.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "clangtool.h"
-
-#include
-
-QT_BEGIN_NAMESPACE
-class QToolButton;
-QT_END_NAMESPACE
-
-namespace Utils { class FancyLineEdit; }
-
-namespace ClangTools {
-namespace Internal {
-
-class DiagnosticFilterModel;
-
-const char ClangTidyClazyPerspectiveId[] = "ClangTidyClazy.Perspective";
-
-class ClangTidyClazyTool final : public ClangTool
-{
- Q_OBJECT
-
-public:
- ClangTidyClazyTool();
-
- static ClangTidyClazyTool *instance();
-
- void startTool(FileSelection fileSelection) final;
-
- Diagnostics read(OutputFileFormat outputFileFormat,
- const QString &logFilePath,
- const QString &mainFilePath,
- const QSet &projectFiles,
- QString *errorMessage) const final;
-
- void onNewDiagnosticsAvailable(const Diagnostics &diagnostics) override;
-
-private:
- void handleStateUpdate() final;
-
- void updateRunActions();
- void loadDiagnosticsFromFiles();
-
- DiagnosticFilterModel *m_diagnosticFilterModel = nullptr;
-
- Utils::FancyLineEdit *m_filterLineEdit = nullptr;
- QToolButton *m_applyFixitsButton = nullptr;
-
- QAction *m_goBack = nullptr;
- QAction *m_goNext = nullptr;
- QAction *m_loadExported = nullptr;
- QAction *m_clear = nullptr;
- QAction *m_expandCollapse = nullptr;
-
- Utils::Perspective m_perspective{ClangTidyClazyPerspectiveId, tr("Clang-Tidy and Clazy")};
-};
-
-} // namespace Internal
-} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp
index a2ffb83c7b0..da9e022b038 100644
--- a/src/plugins/clangtools/clangtool.cpp
+++ b/src/plugins/clangtools/clangtool.cpp
@@ -25,10 +25,16 @@
#include "clangtool.h"
+#include "clangfixitsrefactoringchanges.h"
#include "clangselectablefilesdialog.h"
+#include "clangtoolruncontrol.h"
#include "clangtoolsconstants.h"
#include "clangtoolsdiagnostic.h"
#include "clangtoolsdiagnosticmodel.h"
+#include "clangtoolsdiagnosticview.h"
+#include "clangtoolslogfilereader.h"
+#include "clangtoolsprojectsettings.h"
+#include "clangtoolssettings.h"
#include "clangtoolsutils.h"
#include
@@ -36,6 +42,7 @@
#include
#include
#include
+#include
#include
@@ -44,19 +51,22 @@
#include
#include
#include
-#include
#include
+#include
#include
+#include
#include
#include
#include
+#include
#include
#include
#include
using namespace Core;
+using namespace CppTools;
using namespace Debugger;
using namespace ProjectExplorer;
using namespace Utils;
@@ -64,6 +74,142 @@ using namespace Utils;
namespace ClangTools {
namespace Internal {
+static ClangTool *s_instance;
+
+class ApplyFixIts
+{
+public:
+ class RefactoringFileInfo
+ {
+ public:
+ bool isValid() const { return file.isValid(); }
+
+ FixitsRefactoringFile file;
+ QVector diagnosticItems;
+ bool hasScheduledFixits = false;
+ };
+
+ ApplyFixIts(const QVector &diagnosticItems)
+ {
+ for (DiagnosticItem *diagnosticItem : diagnosticItems) {
+ const QString &filePath = diagnosticItem->diagnostic().location.filePath;
+ QTC_ASSERT(!filePath.isEmpty(), continue);
+
+ // Get or create refactoring file
+ RefactoringFileInfo &fileInfo = m_refactoringFileInfos[filePath];
+ if (!fileInfo.isValid())
+ fileInfo.file = FixitsRefactoringFile(filePath);
+
+ // Append item
+ fileInfo.diagnosticItems += diagnosticItem;
+ if (diagnosticItem->fixItStatus() == FixitStatus::Scheduled)
+ fileInfo.hasScheduledFixits = true;
+ }
+ }
+
+ static void addFixitOperations(DiagnosticItem *diagnosticItem,
+ const FixitsRefactoringFile &file, bool apply)
+ {
+ if (!diagnosticItem->hasNewFixIts())
+ return;
+
+ // Did we already created the fixit operations?
+ ReplacementOperations currentOps = diagnosticItem->fixitOperations();
+ if (!currentOps.isEmpty()) {
+ for (ReplacementOperation *op : currentOps)
+ op->apply = apply;
+ return;
+ }
+
+ // Collect/construct the fixit operations
+ ReplacementOperations replacements;
+
+ for (const ExplainingStep &step : diagnosticItem->diagnostic().explainingSteps) {
+ if (!step.isFixIt)
+ continue;
+
+ const Debugger::DiagnosticLocation start = step.ranges.first();
+ const Debugger::DiagnosticLocation end = step.ranges.last();
+ const int startPos = file.position(start.filePath, start.line, start.column);
+ const int endPos = file.position(start.filePath, end.line, end.column);
+
+ auto op = new ReplacementOperation;
+ op->pos = startPos;
+ op->length = endPos - startPos;
+ op->text = step.message;
+ op->fileName = start.filePath;
+ op->apply = apply;
+
+ replacements += op;
+ }
+
+ diagnosticItem->setFixitOperations(replacements);
+ }
+
+ void apply(ClangToolsDiagnosticModel *model)
+ {
+ for (auto it = m_refactoringFileInfos.begin(); it != m_refactoringFileInfos.end(); ++it) {
+ RefactoringFileInfo &fileInfo = it.value();
+
+ QVector itemsScheduledOrSchedulable;
+ QVector itemsScheduled;
+ QVector itemsSchedulable;
+
+ // Construct refactoring operations
+ for (DiagnosticItem *diagnosticItem : fileInfo.diagnosticItems) {
+ const FixitStatus fixItStatus = diagnosticItem->fixItStatus();
+
+ const bool isScheduled = fixItStatus == FixitStatus::Scheduled;
+ const bool isSchedulable = fileInfo.hasScheduledFixits
+ && fixItStatus == FixitStatus::NotScheduled;
+
+ if (isScheduled || isSchedulable) {
+ addFixitOperations(diagnosticItem, fileInfo.file, isScheduled);
+ itemsScheduledOrSchedulable += diagnosticItem;
+ if (isScheduled)
+ itemsScheduled += diagnosticItem;
+ else
+ itemsSchedulable += diagnosticItem;
+ }
+ }
+
+ // Collect replacements
+ ReplacementOperations ops;
+ for (DiagnosticItem *item : itemsScheduledOrSchedulable)
+ ops += item->fixitOperations();
+
+ if (ops.empty())
+ continue;
+
+ // Apply file
+ QVector itemsApplied;
+ QVector itemsFailedToApply;
+ QVector itemsInvalidated;
+
+ fileInfo.file.setReplacements(ops);
+ model->removeWatchedPath(ops.first()->fileName);
+ if (fileInfo.file.apply()) {
+ itemsApplied = itemsScheduled;
+ } else {
+ itemsFailedToApply = itemsScheduled;
+ itemsInvalidated = itemsSchedulable;
+ }
+ model->addWatchedPath(ops.first()->fileName);
+
+ // Update DiagnosticItem state
+ for (DiagnosticItem *diagnosticItem : itemsScheduled)
+ diagnosticItem->setFixItStatus(FixitStatus::Applied);
+ for (DiagnosticItem *diagnosticItem : itemsFailedToApply)
+ diagnosticItem->setFixItStatus(FixitStatus::FailedToApply);
+ for (DiagnosticItem *diagnosticItem : itemsInvalidated)
+ diagnosticItem->setFixItStatus(FixitStatus::Invalidated);
+ }
+ }
+
+private:
+ QMap m_refactoringFileInfos;
+};
+
static FileInfos sortedFileInfos(const QVector &projectParts)
{
FileInfos fileInfos;
@@ -93,9 +239,24 @@ static FileInfos sortedFileInfos(const QVector &proj
return fileInfos;
}
-ClangTool::ClangTool(const QString &name)
- : m_name(name)
+static RunSettings runSettings(Project *project)
{
+ auto *projectSettings = ClangToolsProjectSettingsManager::getSettings(project);
+ if (projectSettings->useGlobalSettings())
+ return ClangToolsSettings::instance()->runSettings();
+ return projectSettings->runSettings();
+}
+
+ClangTool *ClangTool::instance()
+{
+ return s_instance;
+}
+
+ClangTool::ClangTool()
+ : m_name("Clang-Tidy and Clazy")
+{
+ setObjectName("ClangTidyClazyTool");
+ s_instance = this;
m_diagnosticModel = new ClangToolsDiagnosticModel(this);
const Utils::Icon RUN_FILE_OVERLAY(
@@ -120,6 +281,150 @@ ClangTool::ClangTool(const QString &name)
m_startOnCurrentFileAction = action;
m_stopAction = Debugger::createStopAction();
+
+ m_diagnosticFilterModel = new DiagnosticFilterModel(this);
+ m_diagnosticFilterModel->setSourceModel(m_diagnosticModel);
+ m_diagnosticFilterModel->setDynamicSortFilter(true);
+
+ m_diagnosticView = new DiagnosticView;
+ initDiagnosticView();
+ m_diagnosticView->setModel(m_diagnosticFilterModel);
+ m_diagnosticView->setSortingEnabled(true);
+ m_diagnosticView->sortByColumn(Debugger::DetailedErrorView::DiagnosticColumn,
+ Qt::AscendingOrder);
+ m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
+ m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Diagnostics"));
+
+ foreach (auto * const model,
+ QList({m_diagnosticModel, m_diagnosticFilterModel})) {
+ connect(model, &QAbstractItemModel::rowsInserted,
+ this, &ClangTool::handleStateUpdate);
+ connect(model, &QAbstractItemModel::rowsRemoved,
+ this, &ClangTool::handleStateUpdate);
+ connect(model, &QAbstractItemModel::modelReset,
+ this, &ClangTool::handleStateUpdate);
+ connect(model, &QAbstractItemModel::layoutChanged, // For QSortFilterProxyModel::invalidate()
+ this, &ClangTool::handleStateUpdate);
+ }
+
+ // Go to previous diagnostic
+ action = new QAction(this);
+ action->setDisabled(true);
+ action->setIcon(Utils::Icons::PREV_TOOLBAR.icon());
+ action->setToolTip(tr("Go to previous diagnostic."));
+ connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goBack);
+ m_goBack = action;
+
+ // Go to next diagnostic
+ action = new QAction(this);
+ action->setDisabled(true);
+ action->setIcon(Utils::Icons::NEXT_TOOLBAR.icon());
+ action->setToolTip(tr("Go to next diagnostic."));
+ connect(action, &QAction::triggered, m_diagnosticView, &DetailedErrorView::goNext);
+ m_goNext = action;
+
+ // Load diagnostics from file
+ action = new QAction(this);
+ action->setIcon(Utils::Icons::OPENFILE_TOOLBAR.icon());
+ action->setToolTip(tr("Load Diagnostics from YAML Files exported with \"-export-fixes\"."));
+ connect(action, &QAction::triggered, this, &ClangTool::loadDiagnosticsFromFiles);
+ m_loadExported = action;
+
+ // Clear data
+ action = new QAction(this);
+ action->setDisabled(true);
+ action->setIcon(Utils::Icons::CLEAN_TOOLBAR.icon());
+ action->setToolTip(tr("Clear"));
+ connect(action, &QAction::triggered, [this](){
+ m_clear->setEnabled(false);
+ m_diagnosticModel->clear();
+ Debugger::showPermanentStatusMessage(QString());
+ });
+ m_clear = action;
+
+ // Expand/Collapse
+ action = new QAction(this);
+ action->setDisabled(true);
+ action->setCheckable(true);
+ action->setIcon(Utils::Icons::EXPAND_ALL_TOOLBAR.icon());
+ action->setToolTip(tr("Expand All"));
+ connect(action, &QAction::toggled, [this](bool checked){
+ if (checked) {
+ m_expandCollapse->setToolTip(tr("Collapse All"));
+ m_diagnosticView->expandAll();
+ } else {
+ m_expandCollapse->setToolTip(tr("Expand All"));
+ m_diagnosticView->collapseAll();
+ }
+ });
+ m_expandCollapse = action;
+
+ // Filter line edit
+ m_filterLineEdit = new Utils::FancyLineEdit();
+ m_filterLineEdit->setFiltering(true);
+ m_filterLineEdit->setPlaceholderText(tr("Filter Diagnostics"));
+ m_filterLineEdit->setHistoryCompleter("CppTools.ClangTidyClazyIssueFilter", true);
+ connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, [this](const QString &filter) {
+ m_diagnosticFilterModel->setFilterRegExp(
+ QRegExp(filter, Qt::CaseSensitive, QRegExp::WildcardUnix));
+ });
+
+ // Apply fixits button
+ m_applyFixitsButton = new QToolButton;
+ m_applyFixitsButton->setText(tr("Apply Fixits"));
+ m_applyFixitsButton->setEnabled(false);
+ connect(m_diagnosticModel,
+ &ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
+ [this](int c) {
+ m_applyFixitsButton->setEnabled(c);
+ static_cast(m_diagnosticView.data())->setSelectedFixItsCount(c);
+ });
+ connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
+ QVector diagnosticItems;
+ m_diagnosticModel->forItemsAtLevel<2>([&](DiagnosticItem *item){
+ diagnosticItems += item;
+ });
+
+ ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
+ });
+
+ ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
+ const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
+ "Clang project to search for diagnostics.");
+
+ m_perspective.addWindow(m_diagnosticView, Perspective::SplitVertical, nullptr);
+
+ action = new QAction(tr("Clang-Tidy and Clazy..."), this);
+ action->setToolTip(toolTip);
+ menu->addAction(ActionManager::registerAction(action, "ClangTidyClazy.Action"),
+ Debugger::Constants::G_ANALYZER_TOOLS);
+ QObject::connect(action, &QAction::triggered, this, [this]() {
+ startTool(ClangTool::FileSelection::AskUser);
+ });
+ QObject::connect(m_startAction, &QAction::triggered, action, &QAction::triggered);
+ QObject::connect(m_startAction, &QAction::changed, action, [action, this] {
+ action->setEnabled(m_startAction->isEnabled());
+ });
+
+ QObject::connect(m_startOnCurrentFileAction, &QAction::triggered, this, [this] {
+ startTool(ClangTool::FileSelection::CurrentFile);
+ });
+
+ m_perspective.addToolBarAction(m_startAction);
+ m_perspective.addToolBarAction(m_startOnCurrentFileAction);
+ m_perspective.addToolBarAction(m_stopAction);
+ m_perspective.addToolBarAction(m_loadExported);
+ m_perspective.addToolBarAction(m_clear);
+ m_perspective.addToolBarAction(m_goBack);
+ m_perspective.addToolBarAction(m_goNext);
+ m_perspective.addToolBarAction(m_expandCollapse);
+ m_perspective.addToolBarWidget(m_filterLineEdit);
+ m_perspective.addToolBarWidget(m_applyFixitsButton);
+
+ updateRunActions();
+
+ connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::updateRunActions,
+ this, &ClangTool::updateRunActions);
}
ClangTool::~ClangTool()
@@ -127,6 +432,78 @@ ClangTool::~ClangTool()
delete m_diagnosticView;
}
+void ClangTool::selectPerspective()
+{
+ m_perspective.select();
+}
+
+void ClangTool::startTool(ClangTool::FileSelection fileSelection)
+{
+ Project *project = SessionManager::startupProject();
+ QTC_ASSERT(project, return);
+ QTC_ASSERT(project->activeTarget(), return);
+
+ auto runControl = new RunControl(Constants::CLANGTIDYCLAZY_RUN_MODE);
+ runControl->setDisplayName(tr("Clang-Tidy and Clazy"));
+ runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
+ runControl->setTarget(project->activeTarget());
+
+ const FileInfos fileInfos = collectFileInfos(project, fileSelection);
+ if (fileInfos.empty())
+ return;
+
+ const bool preventBuild = fileSelection == FileSelection::CurrentFile;
+ auto clangTool = new ClangToolRunWorker(runControl,
+ runSettings(project),
+ fileInfos,
+ preventBuild);
+
+ m_stopAction->disconnect();
+ connect(m_stopAction, &QAction::triggered, runControl, [runControl] {
+ runControl->appendMessage(tr("Clang-Tidy and Clazy tool stopped by user."),
+ NormalMessageFormat);
+ runControl->initiateStop();
+ });
+
+ connect(runControl, &RunControl::stopped, this, [this, clangTool] {
+ bool success = clangTool->success();
+ setToolBusy(false);
+ m_running = false;
+ handleStateUpdate();
+ updateRunActions();
+ emit finished(success);
+ });
+
+ m_perspective.select();
+
+ m_diagnosticModel->clear();
+
+ setToolBusy(true);
+ m_diagnosticFilterModel->setProject(project);
+ m_running = true;
+ handleStateUpdate();
+ updateRunActions();
+
+ ProjectExplorerPlugin::startRunControl(runControl);
+}
+
+Diagnostics ClangTool::read(OutputFileFormat outputFileFormat, const QString &logFilePath, const QString &mainFilePath, const QSet &projectFiles, QString *errorMessage) const
+{
+ const auto acceptFromFilePath = [projectFiles](const Utils::FilePath &filePath) {
+ return projectFiles.contains(filePath);
+ };
+
+ if (outputFileFormat == OutputFileFormat::Yaml) {
+ return readExportedDiagnostics(Utils::FilePath::fromString(logFilePath),
+ acceptFromFilePath,
+ errorMessage);
+ }
+ return readSerializedDiagnostics(Utils::FilePath::fromString(logFilePath),
+ Utils::FilePath::fromString(mainFilePath),
+ acceptFromFilePath,
+ errorMessage);
+}
+
FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelection) const
{
auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project);
@@ -174,6 +551,42 @@ void ClangTool::initDiagnosticView()
m_diagnosticView->setAutoScroll(false);
}
+void ClangTool::loadDiagnosticsFromFiles()
+{
+ // Ask user for files
+ const QStringList filePaths
+ = QFileDialog::getOpenFileNames(Core::ICore::mainWindow(),
+ tr("Select YAML Files with Diagnostics"),
+ QDir::homePath(),
+ tr("YAML Files (*.yml *.yaml);;All Files (*)"));
+ if (filePaths.isEmpty())
+ return;
+
+ // Load files
+ Diagnostics diagnostics;
+ QString errors;
+ for (const QString &filePath : filePaths) {
+ QString currentError;
+ diagnostics << readExportedDiagnostics(Utils::FilePath::fromString(filePath),
+ {},
+ ¤tError);
+
+ if (!currentError.isEmpty()) {
+ if (!errors.isEmpty())
+ errors.append("\n");
+ errors.append(currentError);
+ }
+ }
+
+ // Show errors
+ if (!errors.isEmpty())
+ AsynchronousMessageBox::critical(tr("Error Loading Diagnostics"), errors);
+
+ // Show imported
+ m_diagnosticModel->clear();
+ onNewDiagnosticsAvailable(diagnostics);
+}
+
QSet ClangTool::diagnostics() const
{
return Utils::filtered(m_diagnosticModel->diagnostics(), [](const Diagnostic &diagnostic) {
@@ -186,6 +599,78 @@ void ClangTool::onNewDiagnosticsAvailable(const Diagnostics &diagnostics)
{
QTC_ASSERT(m_diagnosticModel, return);
m_diagnosticModel->addDiagnostics(diagnostics);
+ if (!m_diagnosticFilterModel->filterRegExp().pattern().isEmpty())
+ m_diagnosticFilterModel->invalidateFilter();
+}
+
+void ClangTool::updateRunActions()
+{
+ if (m_toolBusy) {
+ QString tooltipText = tr("Clang-Tidy and Clazy are still running.");
+
+ m_startAction->setEnabled(false);
+ m_startAction->setToolTip(tooltipText);
+
+ m_startOnCurrentFileAction->setEnabled(false);
+ m_startOnCurrentFileAction->setToolTip(tooltipText);
+
+ m_stopAction->setEnabled(true);
+ m_loadExported->setEnabled(false);
+ m_clear->setEnabled(false);
+ } else {
+ QString toolTipStart = m_startAction->text();
+ QString toolTipStartOnCurrentFile = m_startOnCurrentFileAction->text();
+
+ Project *project = SessionManager::startupProject();
+ Target *target = project ? project->activeTarget() : nullptr;
+ const Core::Id cxx = ProjectExplorer::Constants::CXX_LANGUAGE_ID;
+ bool canRun = target && project->projectLanguages().contains(cxx)
+ && ToolChainKitAspect::toolChain(target->kit(), cxx);
+ if (!canRun)
+ toolTipStart = toolTipStartOnCurrentFile = tr("This is not a C/C++ project.");
+
+ m_startAction->setEnabled(canRun);
+ m_startAction->setToolTip(toolTipStart);
+
+ m_startOnCurrentFileAction->setEnabled(canRun);
+ m_startOnCurrentFileAction->setToolTip(toolTipStartOnCurrentFile);
+
+ m_stopAction->setEnabled(false);
+ m_loadExported->setEnabled(true);
+ m_clear->setEnabled(m_diagnosticModel->diagnostics().count());
+ }
+}
+
+void ClangTool::handleStateUpdate()
+{
+ QTC_ASSERT(m_goBack, return);
+ QTC_ASSERT(m_goNext, return);
+ QTC_ASSERT(m_diagnosticModel, return);
+ QTC_ASSERT(m_diagnosticFilterModel, return);
+
+ const int issuesFound = m_diagnosticModel->diagnostics().count();
+ const int issuesVisible = m_diagnosticFilterModel->rowCount();
+ m_goBack->setEnabled(issuesVisible > 1);
+ m_goNext->setEnabled(issuesVisible > 1);
+ m_clear->setEnabled(issuesFound > 0);
+ m_expandCollapse->setEnabled(issuesVisible);
+
+ m_loadExported->setEnabled(!m_running);
+
+ QString message;
+ if (m_running) {
+ if (issuesFound)
+ message = tr("Running - %n diagnostics", nullptr, issuesFound);
+ else
+ message = tr("Running - No diagnostics");
+ } else {
+ if (issuesFound)
+ message = tr("Finished - %n diagnostics", nullptr, issuesFound);
+ else
+ message = tr("Finished - No diagnostics");
+ }
+
+ Debugger::showPermanentStatusMessage(message);
}
void ClangTool::setToolBusy(bool busy)
diff --git a/src/plugins/clangtools/clangtool.h b/src/plugins/clangtools/clangtool.h
index c0b1565260f..b61ed1ac448 100644
--- a/src/plugins/clangtools/clangtool.h
+++ b/src/plugins/clangtools/clangtool.h
@@ -29,38 +29,56 @@
#include "clangtoolsdiagnostic.h"
#include "clangtoolslogfilereader.h"
+#include
+
#include
#include
-namespace Debugger { class DetailedErrorView; }
-namespace Utils { class FilePath; }
+QT_BEGIN_NAMESPACE
+class QToolButton;
+QT_END_NAMESPACE
+
+namespace Debugger {
+class DetailedErrorView;
+}
+namespace Utils {
+class FilePath;
+class FancyLineEdit;
+} // namespace Utils
namespace ClangTools {
namespace Internal {
class ClangToolsDiagnosticModel;
class Diagnostic;
+class DiagnosticFilterModel;
+
+const char ClangTidyClazyPerspectiveId[] = "ClangTidyClazy.Perspective";
class ClangTool : public QObject
{
Q_OBJECT
public:
- ClangTool(const QString &name);
+ static ClangTool *instance();
+
+ ClangTool();
~ClangTool() override;
+ void selectPerspective();
+
enum class FileSelection {
AllFiles,
CurrentFile,
AskUser,
};
- virtual void startTool(FileSelection fileSelection) = 0;
+ void startTool(FileSelection fileSelection);
- virtual Diagnostics read(OutputFileFormat outputFileFormat,
+ Diagnostics read(OutputFileFormat outputFileFormat,
const QString &logFilePath,
const QString &mainFilePath,
const QSet &projectFiles,
- QString *errorMessage) const = 0;
+ QString *errorMessage) const;
FileInfos collectFileInfos(ProjectExplorer::Project *project,
FileSelection fileSelection) const;
@@ -70,7 +88,7 @@ public:
const QString &name() const;
- virtual void onNewDiagnosticsAvailable(const Diagnostics &diagnostics);
+ void onNewDiagnosticsAvailable(const Diagnostics &diagnostics);
QAction *startAction() const { return m_startAction; }
QAction *startOnCurrentFileAction() const { return m_startOnCurrentFileAction; }
@@ -78,11 +96,14 @@ public:
signals:
void finished(bool success); // For testing.
-protected:
- virtual void handleStateUpdate() = 0;
+private:
+ void updateRunActions();
+ void handleStateUpdate();
void setToolBusy(bool busy);
+
void initDiagnosticView();
+ void loadDiagnosticsFromFiles();
ClangToolsDiagnosticModel *m_diagnosticModel = nullptr;
QPointer m_diagnosticView;
@@ -93,6 +114,19 @@ protected:
bool m_running = false;
bool m_toolBusy = false;
+ DiagnosticFilterModel *m_diagnosticFilterModel = nullptr;
+
+ Utils::FancyLineEdit *m_filterLineEdit = nullptr;
+ QToolButton *m_applyFixitsButton = nullptr;
+
+ QAction *m_goBack = nullptr;
+ QAction *m_goNext = nullptr;
+ QAction *m_loadExported = nullptr;
+ QAction *m_clear = nullptr;
+ QAction *m_expandCollapse = nullptr;
+
+ Utils::Perspective m_perspective{ClangTidyClazyPerspectiveId, tr("Clang-Tidy and Clazy")};
+
private:
const QString m_name;
};
diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp
index dc22e7a39b6..2af11aa7eff 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.cpp
+++ b/src/plugins/clangtools/clangtoolruncontrol.cpp
@@ -26,9 +26,9 @@
#include "clangtoolruncontrol.h"
#include "clangtidyclazyrunner.h"
-#include "clangtidyclazytool.h"
#include "clangtool.h"
#include "clangtoolslogfilereader.h"
+#include "clangtoolsprojectsettings.h"
#include "clangtoolssettings.h"
#include "clangtoolsutils.h"
@@ -40,7 +40,9 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -116,7 +118,7 @@ namespace Internal {
static ClangTool *tool()
{
- return ClangTidyClazyTool::instance();
+ return ClangTool::instance();
}
class ProjectBuilder : public RunWorker
@@ -219,19 +221,28 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
return debug;
}
+static ClangDiagnosticConfig diagnosticConfig(const Core::Id &diagConfigId)
+{
+ const ClangDiagnosticConfigsModel configsModel(
+ CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
+
+ QTC_ASSERT(configsModel.hasConfigWithId(diagConfigId), return ClangDiagnosticConfig());
+ return configsModel.configWithId(diagConfigId);
+}
+
ClangToolRunWorker::ClangToolRunWorker(RunControl *runControl,
- const ClangDiagnosticConfig &diagnosticConfig,
+ const RunSettings &runSettings,
const FileInfos &fileInfos,
bool preventBuild)
: RunWorker(runControl)
- , m_temporaryDir("clangtools-XXXXXX")
- , m_diagnosticConfig(diagnosticConfig)
+ , m_diagnosticConfig(diagnosticConfig(runSettings.diagnosticConfigId()))
, m_fileInfos(fileInfos)
+ , m_temporaryDir("clangtools-XXXXXX")
{
setId("ClangTidyClazyRunner");
setSupportsReRunning(false);
- if (!preventBuild && ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) {
+ if (!preventBuild && runSettings.buildBeforeAnalysis()) {
m_projectBuilder = new ProjectBuilder(runControl);
addStartDependency(m_projectBuilder);
}
@@ -272,11 +283,9 @@ void ClangToolRunWorker::start()
TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID);
ProjectExplorerPlugin::saveModifiedFiles();
- if (ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) {
- if (m_projectBuilder && !m_projectBuilder->success()) {
- reportFailure();
- return;
- }
+ if (m_projectBuilder && !m_projectBuilder->success()) {
+ reportFailure();
+ return;
}
const QString &toolName = tool()->name();
@@ -337,7 +346,7 @@ void ClangToolRunWorker::start()
// Start process(es)
qCDebug(LOG) << "Environment:" << m_environment;
m_runners.clear();
- const int parallelRuns = ClangToolsSettings::instance()->savedSimultaneousProcesses();
+ const int parallelRuns = m_runSettings.parallelJobs();
QTC_ASSERT(parallelRuns >= 1, reportFailure(); return);
m_success = true;
@@ -491,7 +500,7 @@ void ClangToolRunWorker::finalize()
TaskHub::addTask(Task::Error, msg, Debugger::Constants::ANALYZERTASK_ID);
Target *target = runControl()->target();
if (target && !target->activeBuildConfiguration()->buildDirectory().exists()
- && !ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) {
+ && !m_runSettings.buildBeforeAnalysis()) {
msg = tr("%1: You might need to build the project to generate or update source "
"files. To build automatically, enable \"Build the project before starting "
"analysis\".")
diff --git a/src/plugins/clangtools/clangtoolruncontrol.h b/src/plugins/clangtools/clangtoolruncontrol.h
index 842350a7f41..bfada9e5029 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.h
+++ b/src/plugins/clangtools/clangtoolruncontrol.h
@@ -26,6 +26,7 @@
#pragma once
#include "clangfileinfo.h"
+#include "clangtoolssettings.h"
#include
#include
@@ -66,7 +67,7 @@ class ClangToolRunWorker : public ProjectExplorer::RunWorker
public:
ClangToolRunWorker(ProjectExplorer::RunControl *runControl,
- const CppTools::ClangDiagnosticConfig &diagnosticConfig,
+ const RunSettings &runSettings,
const FileInfos &fileInfos,
bool preventBuild);
@@ -93,15 +94,15 @@ private:
void finalize();
-protected:
+private:
+ RunSettings m_runSettings;
+ CppTools::ClangDiagnosticConfig m_diagnosticConfig;
+ FileInfos m_fileInfos;
+
ProjectBuilder *m_projectBuilder = nullptr;
Utils::Environment m_environment;
Utils::TemporaryDirectory m_temporaryDir;
-private:
- CppTools::ClangDiagnosticConfig m_diagnosticConfig;
- FileInfos m_fileInfos;
-
CppTools::ProjectInfo m_projectInfoBeforeBuild;
CppTools::ProjectInfo m_projectInfo;
QString m_targetTriple;
diff --git a/src/plugins/clangtools/clangtools.pro b/src/plugins/clangtools/clangtools.pro
index a089f1edb77..6173e2eec10 100644
--- a/src/plugins/clangtools/clangtools.pro
+++ b/src/plugins/clangtools/clangtools.pro
@@ -21,7 +21,6 @@ SOURCES += \
clangtoolsdiagnosticview.cpp \
clangtoolsprojectsettingswidget.cpp \
clangtidyclazyrunner.cpp \
- clangtidyclazytool.cpp \
clangtool.cpp \
clangtoolruncontrol.cpp \
clangtoolrunner.cpp \
@@ -32,6 +31,7 @@ SOURCES += \
clangtoolsprojectsettings.cpp \
clangtoolssettings.cpp \
clangtoolsutils.cpp \
+ runsettingswidget.cpp \
settingswidget.cpp \
HEADERS += \
@@ -41,7 +41,6 @@ HEADERS += \
clangtoolsdiagnosticview.h \
clangtoolsprojectsettingswidget.h \
clangtidyclazyrunner.h \
- clangtidyclazytool.h \
clangtool.h \
clangtoolruncontrol.h \
clangtoolrunner.h \
@@ -54,11 +53,13 @@ HEADERS += \
clangtoolsprojectsettings.h \
clangtoolssettings.h \
clangtoolsutils.h \
+ runsettingswidget.h \
settingswidget.h \
FORMS += \
clangselectablefilesdialog.ui \
clangtoolsprojectsettingswidget.ui \
+ runsettingswidget.ui \
settingswidget.ui \
equals(TEST, 1) {
diff --git a/src/plugins/clangtools/clangtools.qbs b/src/plugins/clangtools/clangtools.qbs
index 32146f87c0d..daca2934c19 100644
--- a/src/plugins/clangtools/clangtools.qbs
+++ b/src/plugins/clangtools/clangtools.qbs
@@ -39,8 +39,6 @@ QtcPlugin {
"clangselectablefilesdialog.ui",
"clangtidyclazyrunner.cpp",
"clangtidyclazyrunner.h",
- "clangtidyclazytool.cpp",
- "clangtidyclazytool.h",
"clangtool.cpp",
"clangtool.h",
"clangtoolruncontrol.cpp",
@@ -68,6 +66,9 @@ QtcPlugin {
"clangtoolsutils.h",
"clangtoolsplugin.cpp",
"clangtoolsplugin.h",
+ "runsettingswidget.cpp",
+ "runsettingswidget.h",
+ "runsettingswidget.ui",
"settingswidget.cpp",
"settingswidget.h",
"settingswidget.ui",
diff --git a/src/plugins/clangtools/clangtoolslogfilereader.cpp b/src/plugins/clangtools/clangtoolslogfilereader.cpp
index 59ea741c253..1fe490a6bf3 100644
--- a/src/plugins/clangtools/clangtoolslogfilereader.cpp
+++ b/src/plugins/clangtools/clangtoolslogfilereader.cpp
@@ -417,7 +417,7 @@ Diagnostics readExportedDiagnostics(const Utils::FilePath &logFilePath,
try {
YAML::Node document = YAML::LoadFile(logFilePath.toString().toStdString());
for (const auto &diagNode : document["Diagnostics"]) {
- // clazy omits the "DiagnosticMessage" node.
+ // Since llvm/clang 9.0 the diagnostic items are wrapped in a "DiagnosticMessage" node.
const auto msgNode = diagNode["DiagnosticMessage"];
const YAML::Node &node = msgNode ? msgNode : diagNode;
diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp
index fed9cb21506..12031dc5890 100644
--- a/src/plugins/clangtools/clangtoolsplugin.cpp
+++ b/src/plugins/clangtools/clangtoolsplugin.cpp
@@ -25,10 +25,10 @@
#include "clangtoolsplugin.h"
+#include "clangtool.h"
#include "clangtoolsconstants.h"
-#include "clangtoolsprojectsettingswidget.h"
-#include "clangtidyclazytool.h"
#include "clangtoolsprojectsettings.h"
+#include "clangtoolsprojectsettingswidget.h"
#include "settingswidget.h"
#ifdef WITH_TESTS
@@ -88,24 +88,17 @@ public:
return m_widget;
}
- void apply() override
- {
- ClangToolsSettings::instance()->writeSettings();
- }
-
- void finish() override
- {
- delete m_widget;
- }
+ void apply() override { m_widget->apply(); }
+ void finish() override { delete m_widget; }
private:
- QPointer m_widget;
+ QPointer m_widget;
};
class ClangToolsPluginPrivate
{
public:
- ClangTidyClazyTool clangTidyClazyTool;
+ ClangTool clangTool;
ClangToolsOptionsPage optionsPage;
ClangToolsProjectSettingsManager settingsManager;
};
@@ -122,9 +115,8 @@ bool ClangToolsPlugin::initialize(const QStringList &arguments, QString *errorSt
d = new ClangToolsPluginPrivate;
- ActionManager::registerAction(d->clangTidyClazyTool.startAction(),
- Constants::RUN_ON_PROJECT);
- ActionManager::registerAction(d->clangTidyClazyTool.startOnCurrentFileAction(),
+ ActionManager::registerAction(d->clangTool.startAction(), Constants::RUN_ON_PROJECT);
+ ActionManager::registerAction(d->clangTool.startOnCurrentFileAction(),
Constants::RUN_ON_CURRENT_FILE);
auto panelFactory = new ProjectPanelFactory();
diff --git a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
index 5d711a8aef2..2ed19354f2f 100644
--- a/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
+++ b/src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp
@@ -25,8 +25,8 @@
#include "clangtoolspreconfiguredsessiontests.h"
+#include "clangtool.h"
#include "clangtoolsdiagnostic.h"
-#include "clangtidyclazytool.h"
#include "clangtoolsutils.h"
#include
@@ -121,13 +121,13 @@ void PreconfiguredSessionTests::testPreconfiguredSession()
QVERIFY(switchToProjectAndTarget(project, target));
- ClangTidyClazyTool::instance()->startTool(ClangTidyClazyTool::FileSelection::AllFiles);
- QSignalSpy waitUntilAnalyzerFinished(ClangTidyClazyTool::instance(), SIGNAL(finished(bool)));
+ ClangTool::instance()->startTool(ClangTool::FileSelection::AllFiles);
+ QSignalSpy waitUntilAnalyzerFinished(ClangTool::instance(), SIGNAL(finished(bool)));
QVERIFY(waitUntilAnalyzerFinished.wait(30000));
const QList arguments = waitUntilAnalyzerFinished.takeFirst();
const bool analyzerFinishedSuccessfully = arguments.first().toBool();
QVERIFY(analyzerFinishedSuccessfully);
- QCOMPARE(ClangTidyClazyTool::instance()->diagnostics().count(), 0);
+ QCOMPARE(ClangTool::instance()->diagnostics().count(), 0);
}
static QList validProjects(const QList projectsOfSession)
diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.cpp b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
index 6c2597789d6..005897b49cc 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettings.cpp
+++ b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
@@ -34,8 +34,9 @@
namespace ClangTools {
namespace Internal {
+static const char SETTINGS_KEY_MAIN[] = "ClangTools";
+static const char SETTINGS_PREFIX[] = "ClangTools.";
static const char SETTINGS_KEY_USE_GLOBAL_SETTINGS[] = "ClangTools.UseGlobalSettings";
-static const char SETTINGS_KEY_DIAGNOSTIC_CONFIG[] = "ClangTools.DiagnosticConfig";
static const char SETTINGS_KEY_SELECTED_DIRS[] = "ClangTools.SelectedDirs";
static const char SETTINGS_KEY_SELECTED_FILES[] = "ClangTools.SelectedFiles";
static const char SETTINGS_KEY_SUPPRESSED_DIAGS[] = "ClangTools.SuppressedDiagnostics";
@@ -78,22 +79,53 @@ void ClangToolsProjectSettings::removeAllSuppressedDiagnostics()
emit suppressedDiagnosticsChanged();
}
+static QVariantMap convertToMapFromVersionBefore410(ProjectExplorer::Project *p)
+{
+ // These keys haven't changed.
+ const QStringList keys = {
+ SETTINGS_KEY_SELECTED_DIRS,
+ SETTINGS_KEY_SELECTED_FILES,
+ SETTINGS_KEY_SUPPRESSED_DIAGS,
+ SETTINGS_KEY_USE_GLOBAL_SETTINGS,
+ "ClangTools.BuildBeforeAnalysis",
+ };
+
+ QVariantMap map;
+ for (const QString &key : keys)
+ map.insert(key, p->namedSettings(key));
+
+ map.insert(SETTINGS_PREFIX + QString(diagnosticConfigIdKey),
+ p->namedSettings("ClangTools.DiagnosticConfig"));
+
+ return map;
+}
+
void ClangToolsProjectSettings::load()
{
- const QVariant useGlobalVariant = m_project->namedSettings(SETTINGS_KEY_USE_GLOBAL_SETTINGS);
- m_useGlobalSettings = useGlobalVariant.isValid() ? useGlobalVariant.toBool() : true;
- m_diagnosticConfig = Core::Id::fromSetting(
- m_project->namedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG));
+ // Load map
+ QVariantMap map = m_project->namedSettings(SETTINGS_KEY_MAIN).toMap();
+
+ bool write;
+ if (map.isEmpty()) {
+ if (!m_project->namedSettings(SETTINGS_KEY_SELECTED_DIRS).isNull()) {
+ map = convertToMapFromVersionBefore410(m_project);
+ write = true;
+ } else {
+ return; // Use defaults
+ }
+ }
+
+ // Read map
+ m_useGlobalSettings = map.value(SETTINGS_KEY_USE_GLOBAL_SETTINGS).toBool();
auto toFileName = [](const QString &s) { return Utils::FilePath::fromString(s); };
-
- const QStringList dirs = m_project->namedSettings(SETTINGS_KEY_SELECTED_DIRS).toStringList();
+ const QStringList dirs = map.value(SETTINGS_KEY_SELECTED_DIRS).toStringList();
m_selectedDirs = Utils::transform(dirs, toFileName);
- const QStringList files = m_project->namedSettings(SETTINGS_KEY_SELECTED_FILES).toStringList();
+ const QStringList files = map.value(SETTINGS_KEY_SELECTED_FILES).toStringList();
m_selectedFiles = Utils::transform(files, toFileName);
- const QVariantList list = m_project->namedSettings(SETTINGS_KEY_SUPPRESSED_DIAGS).toList();
+ const QVariantList list = map.value(SETTINGS_KEY_SUPPRESSED_DIAGS).toList();
foreach (const QVariant &v, list) {
const QVariantMap diag = v.toMap();
const QString fp = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_FILEPATH).toString();
@@ -113,48 +145,37 @@ void ClangToolsProjectSettings::load()
uniquifier);
}
emit suppressedDiagnosticsChanged();
+
+ m_runSettings.fromMap(map, SETTINGS_PREFIX);
+
+ if (write)
+ store(); // Store new settings format
}
void ClangToolsProjectSettings::store()
{
- m_project->setNamedSettings(SETTINGS_KEY_USE_GLOBAL_SETTINGS, m_useGlobalSettings);
- m_project->setNamedSettings(SETTINGS_KEY_DIAGNOSTIC_CONFIG, m_diagnosticConfig.toSetting());
+ QVariantMap map;
+ map.insert(SETTINGS_KEY_USE_GLOBAL_SETTINGS, m_useGlobalSettings);
const QStringList dirs = Utils::transform(m_selectedDirs, &Utils::FilePath::toString);
- m_project->setNamedSettings(SETTINGS_KEY_SELECTED_DIRS, dirs);
+ map.insert(SETTINGS_KEY_SELECTED_DIRS, dirs);
const QStringList files = Utils::transform(m_selectedFiles, &Utils::FilePath::toString);
- m_project->setNamedSettings(SETTINGS_KEY_SELECTED_FILES, files);
+ map.insert(SETTINGS_KEY_SELECTED_FILES, files);
QVariantList list;
- foreach (const SuppressedDiagnostic &diag, m_suppressedDiagnostics) {
+ for (const SuppressedDiagnostic &diag : m_suppressedDiagnostics) {
QVariantMap diagMap;
diagMap.insert(SETTINGS_KEY_SUPPRESSED_DIAGS_FILEPATH, diag.filePath.toString());
diagMap.insert(SETTINGS_KEY_SUPPRESSED_DIAGS_MESSAGE, diag.description);
diagMap.insert(SETTINGS_KEY_SUPPRESSED_DIAGS_UNIQIFIER, diag.uniquifier);
list << diagMap;
}
- m_project->setNamedSettings(SETTINGS_KEY_SUPPRESSED_DIAGS, list);
-}
+ map.insert(SETTINGS_KEY_SUPPRESSED_DIAGS, list);
-bool ClangToolsProjectSettings::useGlobalSettings() const
-{
- return m_useGlobalSettings;
-}
+ m_runSettings.toMap(map, SETTINGS_PREFIX);
-void ClangToolsProjectSettings::setUseGlobalSettings(bool useGlobalSettings)
-{
- m_useGlobalSettings = useGlobalSettings;
-}
-
-Core::Id ClangToolsProjectSettings::diagnosticConfig() const
-{
- return m_diagnosticConfig;
-}
-
-void ClangToolsProjectSettings::setDiagnosticConfig(const Core::Id &diagnosticConfig)
-{
- m_diagnosticConfig = diagnosticConfig;
+ m_project->setNamedSettings(SETTINGS_KEY_MAIN, map);
}
ClangToolsProjectSettingsManager::ClangToolsProjectSettingsManager()
diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.h b/src/plugins/clangtools/clangtoolsprojectsettings.h
index 0a6aa477d34..aaf045f056c 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettings.h
+++ b/src/plugins/clangtools/clangtoolsprojectsettings.h
@@ -25,7 +25,7 @@
#pragma once
-#include
+#include "clangtoolssettings.h"
#include
#include
@@ -70,11 +70,11 @@ public:
ClangToolsProjectSettings(ProjectExplorer::Project *project);
~ClangToolsProjectSettings() override;
- bool useGlobalSettings() const;
- void setUseGlobalSettings(bool useGlobalSettings);
+ bool useGlobalSettings() const { return m_useGlobalSettings; }
+ void setUseGlobalSettings(bool useGlobalSettings) { m_useGlobalSettings = useGlobalSettings; }
- Core::Id diagnosticConfig() const;
- void setDiagnosticConfig(const Core::Id &diagnosticConfig);
+ RunSettings runSettings() const { return m_runSettings; }
+ void setRunSettings(const RunSettings &settings) { m_runSettings = settings; }
QSet selectedDirs() const { return m_selectedDirs; }
void setSelectedDirs(const QSet &value) { m_selectedDirs = value; }
@@ -95,10 +95,14 @@ private:
void store();
ProjectExplorer::Project *m_project;
+
bool m_useGlobalSettings = true;
- Core::Id m_diagnosticConfig;
+
+ RunSettings m_runSettings;
+
QSet m_selectedDirs;
QSet m_selectedFiles;
+
SuppressedDiagnosticsList m_suppressedDiagnostics;
};
diff --git a/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp b/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
index 3e380aa9af3..c5b7c53a682 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
+++ b/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
@@ -26,8 +26,12 @@
#include "clangtoolsprojectsettingswidget.h"
#include "ui_clangtoolsprojectsettingswidget.h"
+#include "clangtool.h"
+#include "clangtoolsconstants.h"
#include "clangtoolsprojectsettings.h"
+#include
+
#include
#include
@@ -56,12 +60,46 @@ private:
SuppressedDiagnosticsList m_diagnostics;
};
+enum { UseGlobalSettings, UseCustomSettings }; // Values in sync with m_ui->globalCustomComboBox
+
ProjectSettingsWidget::ProjectSettingsWidget(ProjectExplorer::Project *project, QWidget *parent) :
QWidget(parent),
m_ui(new Ui::ProjectSettingsWidget)
, m_projectSettings(ClangToolsProjectSettingsManager::getSettings(project))
{
m_ui->setupUi(this);
+
+ // Use global/custom settings
+ const int globalOrCustomIndex = m_projectSettings->useGlobalSettings() ? UseGlobalSettings
+ : UseCustomSettings;
+ m_ui->globalCustomComboBox->setCurrentIndex(globalOrCustomIndex);
+ onGlobalCustomChanged(globalOrCustomIndex);
+ connect(m_ui->globalCustomComboBox,
+ QOverload::of(&QComboBox::currentIndexChanged),
+ this,
+ &ProjectSettingsWidget::onGlobalCustomChanged);
+
+ // Restore global settings
+ connect(m_ui->restoreGlobal, &QPushButton::clicked, this, [this]() {
+ m_ui->runSettingsWidget->fromSettings(ClangToolsSettings::instance()->runSettings());
+ });
+
+ // Links
+ connect(m_ui->gotoGlobalSettingsLabel, &QLabel::linkActivated, [](const QString &){
+ Core::ICore::showOptionsDialog(ClangTools::Constants::SETTINGS_PAGE_ID);
+ });
+
+ connect(m_ui->gotoAnalyzerModeLabel, &QLabel::linkActivated, [](const QString &){
+ ClangTool::instance()->selectPerspective();
+ });
+
+ // Run options
+ m_ui->runSettingsWidget->fromSettings(m_projectSettings->runSettings());
+ connect(m_ui->runSettingsWidget, &RunSettingsWidget::changed, [this]() {
+ m_projectSettings->setRunSettings(m_ui->runSettingsWidget->toSettings());
+ });
+
+ // Suppressed diagnostics
auto * const model = new SuppressedDiagnosticsModel(this);
model->setDiagnostics(m_projectSettings->suppressedDiagnostics());
connect(m_projectSettings, &ClangToolsProjectSettings::suppressedDiagnosticsChanged,
@@ -86,6 +124,14 @@ ProjectSettingsWidget::~ProjectSettingsWidget()
delete m_ui;
}
+void ProjectSettingsWidget::onGlobalCustomChanged(int index)
+{
+ const bool useGlobal = index == UseGlobalSettings;
+ m_ui->runSettingsWidget->setEnabled(!useGlobal);
+ m_ui->restoreGlobal->setEnabled(!useGlobal);
+ m_projectSettings->setUseGlobalSettings(useGlobal);
+}
+
void ProjectSettingsWidget::updateButtonStates()
{
updateButtonStateRemoveSelected();
diff --git a/src/plugins/clangtools/clangtoolsprojectsettingswidget.h b/src/plugins/clangtools/clangtoolsprojectsettingswidget.h
index f9153f75a63..680431cc6ea 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettingswidget.h
+++ b/src/plugins/clangtools/clangtoolsprojectsettingswidget.h
@@ -44,6 +44,8 @@ public:
~ProjectSettingsWidget() override;
private:
+ void onGlobalCustomChanged(int index);
+
void updateButtonStates();
void updateButtonStateRemoveSelected();
void updateButtonStateRemoveAll();
diff --git a/src/plugins/clangtools/clangtoolsprojectsettingswidget.ui b/src/plugins/clangtools/clangtoolsprojectsettingswidget.ui
index c120d3bb95f..b8263a450a7 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettingswidget.ui
+++ b/src/plugins/clangtools/clangtoolsprojectsettingswidget.ui
@@ -6,20 +6,41 @@
0
0
- 400
- 300
+ 615
+ 399
-
+
-
-
-
+
+
-
+
+ Use Global Settings
+
+
+ -
+
+ Use Customized Settings
+
+
+
+
+ -
+
- Suppressed diagnostics:
+ Restore Global Settings
+
+
+
+ -
+
+
+ <a href="target">Show Global Settings</a>
@@ -36,52 +57,79 @@
-
-
- -
-
-
-
-
- QAbstractItemView::SingleSelection
+
+
+ <a href="target">Go to Analyzer</a>
- -
-
-
-
-
-
- Remove Selected
-
-
-
- -
-
-
- Remove All
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
+ -
+
+
+ -
+
+
+ Suppressed diagnostics
+
+
+
-
+
+
-
+
+
+ QAbstractItemView::SingleSelection
+
+
+
+ -
+
+
-
+
+
+ Remove Selected
+
+
+
+ -
+
+
+ Remove All
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ClangTools::Internal::RunSettingsWidget
+ QWidget
+ clangtools/runsettingswidget.h
+ 1
+
+
diff --git a/src/plugins/clangtools/clangtoolssettings.cpp b/src/plugins/clangtools/clangtoolssettings.cpp
index 86f152f6603..07b9592a8ee 100644
--- a/src/plugins/clangtools/clangtoolssettings.cpp
+++ b/src/plugins/clangtools/clangtoolssettings.cpp
@@ -29,21 +29,38 @@
#include
-#include
-#include
-
-#include
#include
-static const char simultaneousProcessesKey[] = "simultaneousProcesses";
-static const char buildBeforeAnalysisKey[] = "buildBeforeAnalysis";
-static const char diagnosticConfigIdKey[] = "diagnosticConfigId";
-static const char clangTidyExecutableKey[] = "clangTidyExecutable";
-static const char clazyStandaloneExecutableKey[] = "clazyStandaloneExecutable";
+static const char clangTidyExecutableKey[] = "ClangTidyExecutable";
+static const char clazyStandaloneExecutableKey[] = "ClazyStandaloneExecutable";
+
+static const char parallelJobsKey[] = "ParallelJobs";
+static const char buildBeforeAnalysisKey[] = "BuildBeforeAnalysis";
+
+static const char oldDiagnosticConfigIdKey[] = "diagnosticConfigId";
namespace ClangTools {
namespace Internal {
+RunSettings::RunSettings()
+ : m_parallelJobs(qMax(0, QThread::idealThreadCount() / 2))
+{
+}
+
+void RunSettings::fromMap(const QVariantMap &map, const QString &prefix)
+{
+ m_diagnosticConfigId = Core::Id::fromSetting(map.value(prefix + diagnosticConfigIdKey));
+ m_parallelJobs = map.value(prefix + parallelJobsKey).toInt();
+ m_buildBeforeAnalysis = map.value(prefix + buildBeforeAnalysisKey).toBool();
+}
+
+void RunSettings::toMap(QVariantMap &map, const QString &prefix) const
+{
+ map.insert(prefix + diagnosticConfigIdKey, m_diagnosticConfigId.toSetting());
+ map.insert(prefix + parallelJobsKey, m_parallelJobs);
+ map.insert(prefix + buildBeforeAnalysisKey, m_buildBeforeAnalysis);
+}
+
ClangToolsSettings::ClangToolsSettings()
{
readSettings();
@@ -55,134 +72,69 @@ ClangToolsSettings *ClangToolsSettings::instance()
return &instance;
}
-int ClangToolsSettings::savedSimultaneousProcesses() const
+static QVariantMap convertToMapFromVersionBefore410(QSettings *s)
{
- return m_savedSimultaneousProcesses;
-}
+ const char oldParallelJobsKey[] = "simultaneousProcesses";
+ const char oldBuildBeforeAnalysisKey[] = "buildBeforeAnalysis";
-int ClangToolsSettings::simultaneousProcesses() const
-{
- return m_simultaneousProcesses;
-}
+ QVariantMap map;
+ map.insert(diagnosticConfigIdKey, s->value(oldDiagnosticConfigIdKey));
+ map.insert(parallelJobsKey, s->value(oldParallelJobsKey));
+ map.insert(buildBeforeAnalysisKey, s->value(oldBuildBeforeAnalysisKey));
-void ClangToolsSettings::setSimultaneousProcesses(int processes)
-{
- m_simultaneousProcesses = processes;
-}
+ s->remove(oldDiagnosticConfigIdKey);
+ s->remove(oldParallelJobsKey);
+ s->remove(oldBuildBeforeAnalysisKey);
-bool ClangToolsSettings::savedBuildBeforeAnalysis() const
-{
- return m_savedBuildBeforeAnalysis;
-}
-
-bool ClangToolsSettings::buildBeforeAnalysis() const
-{
- return m_buildBeforeAnalysis;
-}
-
-void ClangToolsSettings::setBuildBeforeAnalysis(bool build)
-{
- m_buildBeforeAnalysis = build;
-}
-
-Core::Id ClangToolsSettings::savedDiagnosticConfigId() const
-{
- return m_savedDiagnosticConfigId;
-}
-
-Core::Id ClangToolsSettings::diagnosticConfigId() const
-{
- return m_diagnosticConfigId;
-}
-
-void ClangToolsSettings::setDiagnosticConfigId(Core::Id id)
-{
- m_diagnosticConfigId = id;
-}
-
-void ClangToolsSettings::updateSavedBuildBeforeAnalysiIfRequired()
-{
- if (m_savedBuildBeforeAnalysis == m_buildBeforeAnalysis)
- return;
- m_savedBuildBeforeAnalysis = m_buildBeforeAnalysis;
- emit buildBeforeAnalysisChanged(m_savedBuildBeforeAnalysis);
-}
-
-QString ClangToolsSettings::savedClazyStandaloneExecutable() const
-{
- return m_savedClazyStandaloneExecutable;
-}
-
-QString ClangToolsSettings::savedClangTidyExecutable() const
-{
- return m_savedClangTidyExecutable;
-}
-
-QString ClangToolsSettings::clazyStandaloneExecutable() const
-{
- return m_clazyStandaloneExecutable;
-}
-
-void ClangToolsSettings::setClazyStandaloneExecutable(const QString &path)
-{
- m_clazyStandaloneExecutable = path;
-}
-
-QString ClangToolsSettings::clangTidyExecutable() const
-{
- return m_clangTidyExecutable;
-}
-
-void ClangToolsSettings::setClangTidyExecutable(const QString &path)
-{
- m_clangTidyExecutable = path;
+ return map;
}
void ClangToolsSettings::readSettings()
{
- QSettings *settings = Core::ICore::settings();
- settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(Constants::SETTINGS_ID);
+ m_clangTidyExecutable = s->value(clangTidyExecutableKey).toString();
+ m_clazyStandaloneExecutable = s->value(clazyStandaloneExecutableKey).toString();
- const int defaultSimultaneousProcesses = qMax(0, QThread::idealThreadCount() / 2);
- m_savedSimultaneousProcesses = m_simultaneousProcesses
- = settings->value(QString(simultaneousProcessesKey),
- defaultSimultaneousProcesses).toInt();
+ bool write = false;
- m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
+ QVariantMap map;
+ if (!s->value(oldDiagnosticConfigIdKey).isNull()) {
+ map = convertToMapFromVersionBefore410(s);
+ write = true;
+ } else {
+ QVariantMap defaults;
+ defaults.insert(diagnosticConfigIdKey, m_runSettings.diagnosticConfigId().toSetting());
+ defaults.insert(parallelJobsKey, m_runSettings.parallelJobs());
+ defaults.insert(buildBeforeAnalysisKey, m_runSettings.buildBeforeAnalysis());
+ map = defaults;
+ for (QVariantMap::ConstIterator it = defaults.constBegin(); it != defaults.constEnd(); ++it)
+ map.insert(it.key(), s->value(it.key(), it.value()));
+ }
- m_savedClangTidyExecutable = m_clangTidyExecutable
- = settings->value(QLatin1String(clangTidyExecutableKey)).toString();
- m_savedClazyStandaloneExecutable = m_clazyStandaloneExecutable
- = settings->value(QLatin1String(clazyStandaloneExecutableKey)).toString();
+ // Run settings
+ m_runSettings.fromMap(map);
- m_diagnosticConfigId = Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
- if (!m_diagnosticConfigId.isValid())
- m_diagnosticConfigId = "Builtin.TidyAndClazy";
+ s->endGroup();
- m_savedDiagnosticConfigId = m_diagnosticConfigId;
-
- updateSavedBuildBeforeAnalysiIfRequired();
-
- settings->endGroup();
+ if (write)
+ writeSettings();
}
void ClangToolsSettings::writeSettings()
{
- QSettings *settings = Core::ICore::settings();
- settings->beginGroup(QString(Constants::SETTINGS_ID));
- settings->setValue(QString(simultaneousProcessesKey), m_simultaneousProcesses);
- settings->setValue(QString(buildBeforeAnalysisKey), m_buildBeforeAnalysis);
- settings->setValue(QString(clangTidyExecutableKey), m_clangTidyExecutable);
- settings->setValue(QString(clazyStandaloneExecutableKey), m_clazyStandaloneExecutable);
- settings->setValue(QString(diagnosticConfigIdKey), m_diagnosticConfigId.toSetting());
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(Constants::SETTINGS_ID);
- m_savedSimultaneousProcesses = m_simultaneousProcesses;
- m_savedDiagnosticConfigId = m_diagnosticConfigId;
- m_savedClangTidyExecutable = m_clangTidyExecutable;
- m_savedClazyStandaloneExecutable = m_clazyStandaloneExecutable;
- updateSavedBuildBeforeAnalysiIfRequired();
+ s->setValue(clangTidyExecutableKey, m_clangTidyExecutable);
+ s->setValue(clazyStandaloneExecutableKey, m_clazyStandaloneExecutable);
- settings->endGroup();
+ QVariantMap map;
+ m_runSettings.toMap(map);
+ for (QVariantMap::ConstIterator it = map.constBegin(); it != map.constEnd(); ++it)
+ s->setValue(it.key(), it.value());
+
+ s->endGroup();
}
} // namespace Internal
diff --git a/src/plugins/clangtools/clangtoolssettings.h b/src/plugins/clangtools/clangtoolssettings.h
index 402845d20f3..893dbd23f9e 100644
--- a/src/plugins/clangtools/clangtoolssettings.h
+++ b/src/plugins/clangtools/clangtoolssettings.h
@@ -27,61 +27,61 @@
#include
-#include
#include
namespace ClangTools {
namespace Internal {
-// TODO: Remove need for "saved* members
-class ClangToolsSettings : public QObject
+const char diagnosticConfigIdKey[] = "DiagnosticConfigId";
+
+class RunSettings
+{
+public:
+ RunSettings();
+
+ void fromMap(const QVariantMap &map, const QString &prefix = QString());
+ void toMap(QVariantMap &map, const QString &prefix = QString()) const;
+
+ Core::Id diagnosticConfigId() const { return m_diagnosticConfigId; }
+ void setDiagnosticConfigId(const Core::Id &id) { m_diagnosticConfigId = id; }
+
+ bool buildBeforeAnalysis() const { return m_buildBeforeAnalysis; }
+ void setBuildBeforeAnalysis(bool yesno) { m_buildBeforeAnalysis = yesno; }
+
+ int parallelJobs() const { return m_parallelJobs; }
+ void setParallelJobs(int jobs) { m_parallelJobs = jobs; }
+
+private:
+ Core::Id m_diagnosticConfigId = "Builtin.TidyAndClazy"; // TODO
+ int m_parallelJobs = -1;
+ bool m_buildBeforeAnalysis = true;
+};
+
+class ClangToolsSettings
{
- Q_OBJECT
public:
static ClangToolsSettings *instance();
-
void writeSettings();
- int savedSimultaneousProcesses() const;
- bool savedBuildBeforeAnalysis() const;
- Core::Id savedDiagnosticConfigId() const;
- QString savedClangTidyExecutable() const;
- QString savedClazyStandaloneExecutable() const;
+ QString clangTidyExecutable() const { return m_clangTidyExecutable; }
+ void setClangTidyExecutable(const QString &path) { m_clangTidyExecutable = path; }
- int simultaneousProcesses() const;
- void setSimultaneousProcesses(int processes);
+ QString clazyStandaloneExecutable() const { return m_clazyStandaloneExecutable; }
+ void setClazyStandaloneExecutable(const QString &path) { m_clazyStandaloneExecutable = path; }
- bool buildBeforeAnalysis() const;
- void setBuildBeforeAnalysis(bool build);
-
- Core::Id diagnosticConfigId() const;
- void setDiagnosticConfigId(Core::Id id);
-
- QString clangTidyExecutable() const;
- void setClangTidyExecutable(const QString &path);
-
- QString clazyStandaloneExecutable() const;
- void setClazyStandaloneExecutable(const QString &path);
-
-signals:
- void buildBeforeAnalysisChanged(bool checked) const;
+ RunSettings runSettings() const { return m_runSettings; }
+ void setRunSettings(const RunSettings &settings) { m_runSettings = settings; }
private:
ClangToolsSettings();
void readSettings();
- void updateSavedBuildBeforeAnalysiIfRequired();
-
- int m_simultaneousProcesses = -1;
- int m_savedSimultaneousProcesses = -1;
- bool m_buildBeforeAnalysis = false;
- bool m_savedBuildBeforeAnalysis= false;
+ // Executables
QString m_clangTidyExecutable;
- QString m_savedClangTidyExecutable;
QString m_clazyStandaloneExecutable;
- QString m_savedClazyStandaloneExecutable;
- Core::Id m_diagnosticConfigId;
- Core::Id m_savedDiagnosticConfigId;
+
+ // Run settings
+ RunSettings m_runSettings;
};
} // namespace Internal
diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp
index b8546c58bdd..79b7bfcc946 100644
--- a/src/plugins/clangtools/clangtoolsunittests.cpp
+++ b/src/plugins/clangtools/clangtoolsunittests.cpp
@@ -25,7 +25,7 @@
#include "clangtoolsunittests.h"
-#include "clangtidyclazytool.h"
+#include "clangtool.h"
#include "clangtoolsdiagnostic.h"
#include "clangtoolssettings.h"
#include "clangtoolsutils.h"
@@ -87,7 +87,8 @@ static CppTools::ClangDiagnosticConfig configFor(const QString &tidyChecks,
config.setIsReadOnly(true);
config.setClangOptions(QStringList{QStringLiteral("-Wno-everything")});
config.setClangTidyMode(CppTools::ClangDiagnosticConfig::TidyMode::ChecksPrefixList);
- config.setClangTidyChecks("-*," + tidyChecks);
+ const QString theTidyChecks = tidyChecks.isEmpty() ? tidyChecks : "-*," + tidyChecks;
+ config.setClangTidyChecks(theTidyChecks);
config.setClazyChecks(clazyChecks);
return config;
}
@@ -108,14 +109,14 @@ void ClangToolsUnitTests::testProject()
CppTools::Tests::ProjectOpenerAndCloser projectManager;
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
QVERIFY(projectInfo.isValid());
- ClangTool *tool = ClangTidyClazyTool::instance();
+ ClangTool *tool = ClangTool::instance();
// Change configs
QSharedPointer cppToolsSettings = CppTools::codeModelSettings();
ClangToolsSettings *clangToolsSettings = ClangToolsSettings::instance();
const CppTools::ClangDiagnosticConfigs originalConfigs = cppToolsSettings
->clangCustomDiagnosticConfigs();
- const Core::Id originalId = clangToolsSettings->diagnosticConfigId();
+ const Core::Id originalId = clangToolsSettings->runSettings().diagnosticConfigId();
CppTools::ClangDiagnosticConfigs modifiedConfigs = originalConfigs;
modifiedConfigs.push_back(diagnosticConfig);
@@ -123,15 +124,19 @@ void ClangToolsUnitTests::testProject()
ExecuteOnDestruction executeOnDestruction([=]() {
// Restore configs
cppToolsSettings->setClangCustomDiagnosticConfigs(originalConfigs);
- clangToolsSettings->setDiagnosticConfigId(originalId);
+ RunSettings runSettings = clangToolsSettings->runSettings();
+ runSettings.setDiagnosticConfigId(originalId);
+ clangToolsSettings->setRunSettings(runSettings);
clangToolsSettings->writeSettings();
});
cppToolsSettings->setClangCustomDiagnosticConfigs(modifiedConfigs);
- clangToolsSettings->setDiagnosticConfigId(diagnosticConfig.id());
+ RunSettings runSettings = clangToolsSettings->runSettings();
+ runSettings.setDiagnosticConfigId(diagnosticConfig.id());
+ clangToolsSettings->setRunSettings(runSettings);
clangToolsSettings->writeSettings();
- tool->startTool(ClangTidyClazyTool::FileSelection::AllFiles);
+ tool->startTool(ClangTool::FileSelection::AllFiles);
QSignalSpy waiter(tool, SIGNAL(finished(bool)));
QVERIFY(waiter.wait(30000));
diff --git a/src/plugins/clangtools/runsettingswidget.cpp b/src/plugins/clangtools/runsettingswidget.cpp
new file mode 100644
index 00000000000..1a26d2e7d0b
--- /dev/null
+++ b/src/plugins/clangtools/runsettingswidget.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "runsettingswidget.h"
+
+#include "ui_runsettingswidget.h"
+
+#include "clangtoolssettings.h"
+#include "clangtoolsutils.h"
+
+#include
+
+namespace ClangTools {
+namespace Internal {
+
+RunSettingsWidget::RunSettingsWidget(QWidget *parent)
+ : QWidget(parent)
+ , m_ui(new Ui::RunSettingsWidget)
+{
+ m_ui->setupUi(this);
+
+ connect(m_ui->diagnosticWidget,
+ &CppTools::ClangDiagnosticConfigsSelectionWidget::currentConfigChanged,
+ [this](const Core::Id &) { emit changed(); });
+ // m_ui->buildBeforeAnalysis is handled in fromSettings()
+ connect(m_ui->parallelJobsSpinBox,
+ QOverload::of(&QSpinBox::valueChanged),
+ [this](int) { emit changed(); });
+}
+
+RunSettingsWidget::~RunSettingsWidget()
+{
+ delete m_ui;
+}
+
+void RunSettingsWidget::fromSettings(const RunSettings &s)
+{
+ m_ui->diagnosticWidget->refresh(s.diagnosticConfigId());
+
+ disconnect(m_ui->buildBeforeAnalysis, 0, 0, 0);
+ m_ui->buildBeforeAnalysis->setToolTip(hintAboutBuildBeforeAnalysis());
+ m_ui->buildBeforeAnalysis->setCheckState(s.buildBeforeAnalysis() ? Qt::Checked : Qt::Unchecked);
+ connect(m_ui->buildBeforeAnalysis, &QCheckBox::toggled, [this](bool checked) {
+ if (!checked)
+ showHintAboutBuildBeforeAnalysis();
+ emit changed();
+ });
+
+ m_ui->parallelJobsSpinBox->setValue(s.parallelJobs());
+ m_ui->parallelJobsSpinBox->setMinimum(1);
+ m_ui->parallelJobsSpinBox->setMaximum(QThread::idealThreadCount());
+}
+
+RunSettings RunSettingsWidget::toSettings() const
+{
+ RunSettings s;
+ s.setDiagnosticConfigId(m_ui->diagnosticWidget->currentConfigId());
+ s.setBuildBeforeAnalysis(m_ui->buildBeforeAnalysis->checkState() == Qt::CheckState::Checked);
+ s.setParallelJobs(m_ui->parallelJobsSpinBox->value());
+
+ return s;
+}
+
+} // namespace Internal
+} // namespace ClangTools
diff --git a/src/plugins/clangtools/runsettingswidget.h b/src/plugins/clangtools/runsettingswidget.h
new file mode 100644
index 00000000000..c49bc88f753
--- /dev/null
+++ b/src/plugins/clangtools/runsettingswidget.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include
+
+namespace ClangTools {
+namespace Internal {
+
+class RunSettings;
+
+namespace Ui {
+class RunSettingsWidget;
+}
+
+class RunSettingsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit RunSettingsWidget(QWidget *parent = nullptr);
+ ~RunSettingsWidget();
+
+ void fromSettings(const RunSettings &s);
+ RunSettings toSettings() const;
+
+signals:
+ void changed();
+
+private:
+ Ui::RunSettingsWidget *m_ui;
+};
+
+} // namespace Internal
+} // namespace ClangTools
diff --git a/src/plugins/clangtools/runsettingswidget.ui b/src/plugins/clangtools/runsettingswidget.ui
new file mode 100644
index 00000000000..e7ad362c846
--- /dev/null
+++ b/src/plugins/clangtools/runsettingswidget.ui
@@ -0,0 +1,93 @@
+
+
+ ClangTools::Internal::RunSettingsWidget
+
+
+
+ 0
+ 0
+ 383
+ 125
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Run Options
+
+
+
-
+
+
+ -
+
+
+ Build the project before analysis
+
+
+
+ -
+
+
-
+
+
+ Parallel jobs:
+
+
+
+ -
+
+
+ 1
+
+
+ 32
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CppTools::ClangDiagnosticConfigsSelectionWidget
+ QWidget
+ cpptools/clangdiagnosticconfigsselectionwidget.h
+
+
+
+
+
diff --git a/src/plugins/clangtools/settingswidget.cpp b/src/plugins/clangtools/settingswidget.cpp
index de5976a04fd..110135a7798 100644
--- a/src/plugins/clangtools/settingswidget.cpp
+++ b/src/plugins/clangtools/settingswidget.cpp
@@ -30,17 +30,6 @@
#include "clangtoolsconstants.h"
#include "clangtoolsutils.h"
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-
namespace ClangTools {
namespace Internal {
@@ -48,15 +37,13 @@ static void setupPathChooser(Utils::PathChooser *const chooser,
const QString &promptDiaglogTitle,
const QString &placeHolderText,
const QString &pathFromSettings,
- const QString &historyCompleterId,
- std::function savePath)
+ const QString &historyCompleterId)
{
chooser->setPromptDialogTitle(promptDiaglogTitle);
chooser->lineEdit()->setPlaceholderText(placeHolderText);
chooser->setPath(pathFromSettings);
chooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
chooser->setHistoryCompleter(historyCompleterId);
- QObject::connect(chooser, &Utils::PathChooser::rawPathChanged, savePath),
chooser->setValidationFunction([chooser](Utils::FancyLineEdit *edit, QString *errorMessage) {
const QString currentFilePath = chooser->fileName().toString();
Utils::PathChooser pc;
@@ -92,8 +79,7 @@ SettingsWidget::SettingsWidget(ClangToolsSettings *settings, QWidget *parent)
tr("Clang-Tidy Executable"),
placeHolderText,
path,
- "ClangTools.ClangTidyExecutable.History",
- [settings](const QString &path) { settings->setClangTidyExecutable(path); });
+ "ClangTools.ClangTidyExecutable.History");
if (qEnvironmentVariable("QTC_USE_CLAZY_STANDALONE_PATH").isEmpty()) {
m_ui->clazyStandalonePathChooser->setVisible(false);
@@ -107,47 +93,23 @@ SettingsWidget::SettingsWidget(ClangToolsSettings *settings, QWidget *parent)
tr("Clazy Executable"),
placeHolderText,
path,
- "ClangTools.ClazyStandaloneExecutable.History",
- [settings](const QString &path) {
- settings->setClazyStandaloneExecutable(path);
- });
+ "ClangTools.ClazyStandaloneExecutable.History");
}
//
// Group box "Run Options"
//
- m_ui->simultaneousProccessesSpinBox->setValue(settings->savedSimultaneousProcesses());
- m_ui->simultaneousProccessesSpinBox->setMinimum(1);
- m_ui->simultaneousProccessesSpinBox->setMaximum(QThread::idealThreadCount());
- connect(m_ui->simultaneousProccessesSpinBox,
- QOverload::of(&QSpinBox::valueChanged),
- [settings](int count) { settings->setSimultaneousProcesses(count); });
- QCheckBox *buildBeforeAnalysis = m_ui->buildBeforeAnalysis;
- buildBeforeAnalysis->setToolTip(hintAboutBuildBeforeAnalysis());
- buildBeforeAnalysis->setCheckState(settings->savedBuildBeforeAnalysis()
- ? Qt::Checked : Qt::Unchecked);
- connect(buildBeforeAnalysis, &QCheckBox::toggled, [settings](bool checked) {
- if (!checked)
- showHintAboutBuildBeforeAnalysis();
- settings->setBuildBeforeAnalysis(checked);
- });
+ m_ui->runSettingsWidget->fromSettings(m_settings->runSettings());
+}
- CppTools::ClangDiagnosticConfigsSelectionWidget *diagnosticWidget = m_ui->diagnosticWidget;
- diagnosticWidget->refresh(settings->savedDiagnosticConfigId());
+void SettingsWidget::apply()
+{
+ m_settings->setClangTidyExecutable(m_ui->clangTidyPathChooser->rawPath());
+ m_settings->setClazyStandaloneExecutable(m_ui->clazyStandalonePathChooser->rawPath());
+ m_settings->setRunSettings(m_ui->runSettingsWidget->toSettings());
- connect(diagnosticWidget,
- &CppTools::ClangDiagnosticConfigsSelectionWidget::currentConfigChanged,
- this, [this](const Core::Id ¤tConfigId) {
- m_settings->setDiagnosticConfigId(currentConfigId);
- });
-
- connect(CppTools::codeModelSettings().data(), &CppTools::CppCodeModelSettings::changed,
- this, [=]() {
- // Settings were applied so apply also the current selection if possible.
- diagnosticWidget->refresh(m_settings->diagnosticConfigId());
- m_settings->writeSettings();
- });
+ m_settings->writeSettings();
}
SettingsWidget::~SettingsWidget() = default;
diff --git a/src/plugins/clangtools/settingswidget.h b/src/plugins/clangtools/settingswidget.h
index 6eeaeb5d987..2002f32eec7 100644
--- a/src/plugins/clangtools/settingswidget.h
+++ b/src/plugins/clangtools/settingswidget.h
@@ -43,6 +43,9 @@ class SettingsWidget : public QWidget
public:
SettingsWidget(ClangToolsSettings *settings, QWidget *parent = nullptr);
~SettingsWidget() override;
+
+ void apply();
+
private:
std::unique_ptr m_ui;
ClangToolsSettings *m_settings;
diff --git a/src/plugins/clangtools/settingswidget.ui b/src/plugins/clangtools/settingswidget.ui
index c73148d0da2..6ef3d092971 100644
--- a/src/plugins/clangtools/settingswidget.ui
+++ b/src/plugins/clangtools/settingswidget.ui
@@ -44,57 +44,7 @@
-
-
-
- Run Options
-
-
-
-
-
-
- -
-
-
- Build the project before analysis
-
-
-
- -
-
-
-
-
-
- Simultaneous processes:
-
-
-
- -
-
-
- 1
-
-
- 32
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
+
-
@@ -112,17 +62,18 @@
-
- CppTools::ClangDiagnosticConfigsSelectionWidget
- QWidget
- cpptools/clangdiagnosticconfigsselectionwidget.h
-
Utils::PathChooser
QWidget
1
+
+ ClangTools::Internal::RunSettingsWidget
+ QWidget
+ clangtools/runsettingswidget.h
+ 1
+
diff --git a/src/plugins/coreplugin/windowsupport.cpp b/src/plugins/coreplugin/windowsupport.cpp
index 17bab61bccf..26117ba12fc 100644
--- a/src/plugins/coreplugin/windowsupport.cpp
+++ b/src/plugins/coreplugin/windowsupport.cpp
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
namespace Core {
namespace Internal {
@@ -111,6 +112,7 @@ bool WindowSupport::eventFilter(QObject *obj, QEvent *event)
m_minimizeAction->setEnabled(!minimized);
m_zoomAction->setEnabled(!minimized);
}
+ m_previousWindowState = static_cast(event)->oldState();
updateFullScreenAction();
} else if (event->type() == QEvent::WindowActivate) {
m_windowList->setActiveWindow(m_window);
@@ -126,7 +128,7 @@ bool WindowSupport::eventFilter(QObject *obj, QEvent *event)
void WindowSupport::toggleFullScreen()
{
if (m_window->isFullScreen()) {
- m_window->setWindowState(m_window->windowState() & ~Qt::WindowFullScreen);
+ m_window->setWindowState(m_previousWindowState & ~Qt::WindowFullScreen);
} else {
m_window->setWindowState(m_window->windowState() | Qt::WindowFullScreen);
}
diff --git a/src/plugins/coreplugin/windowsupport.h b/src/plugins/coreplugin/windowsupport.h
index 5531306fe0f..1e640f6edb3 100644
--- a/src/plugins/coreplugin/windowsupport.h
+++ b/src/plugins/coreplugin/windowsupport.h
@@ -80,6 +80,7 @@ private:
QAction *m_zoomAction;
QAction *m_closeAction;
QAction *m_toggleFullScreenAction;
+ Qt::WindowStates m_previousWindowState;
bool m_shutdown = false;
};
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
index 4120aaee218..dbb70ca07a5 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp
@@ -26,14 +26,25 @@
#include "setframevaluedialog.h"
#include "ui_setframevaluedialog.h"
+#include
+
namespace QmlDesigner {
-SetFrameValueDialog::SetFrameValueDialog(QWidget *parent)
+SetFrameValueDialog::SetFrameValueDialog(qreal frame, const QVariant &value,
+ const QString &propertyName, QWidget *parent)
: QDialog(parent)
, ui(new Ui::SetFrameValueDialog)
{
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
ui->setupUi(this);
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ setWindowTitle(tr("Edit Keyframe"));
+ setFixedSize(size());
+
+ ui->lineEditFrame->setValidator(new QIntValidator(0, 99999, this));
+
+ ui->lineEditFrame->setText(QString::number(frame));
+ ui->lineEditValue->setText(value.toString());
+ ui->labelValue->setText(propertyName);
}
SetFrameValueDialog::~SetFrameValueDialog()
@@ -41,15 +52,14 @@ SetFrameValueDialog::~SetFrameValueDialog()
delete ui;
}
-QLineEdit *SetFrameValueDialog::lineEdit() const
+qreal SetFrameValueDialog::frame() const
{
- return ui->lineEdit;
+ return ui->lineEditFrame->text().toDouble();
}
-void SetFrameValueDialog::setPropertName(const QString &name)
+QVariant SetFrameValueDialog::value() const
{
- setWindowTitle(tr("Change %1").arg(name));
- ui->label->setText(name);
+ return QVariant(ui->lineEditValue->text());
}
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
index e7ed226b674..799e3fadc52 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h
@@ -40,12 +40,12 @@ class SetFrameValueDialog : public QDialog
Q_OBJECT
public:
- explicit SetFrameValueDialog(QWidget *parent = nullptr);
+ explicit SetFrameValueDialog(qreal frame, const QVariant &value, const QString &propertyName,
+ QWidget *parent = nullptr);
~SetFrameValueDialog() override;
- QLineEdit *lineEdit() const;
-
- void setPropertName(const QString &name);
+ qreal frame() const;
+ QVariant value() const;
private:
Ui::SetFrameValueDialog *ui;
diff --git a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
index 2fa1241e4a2..1fe2468a6bf 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
@@ -7,7 +7,7 @@
0
0
184
- 79
+ 93
@@ -15,16 +15,13 @@
-
-
+
- Value
+ Frame
- -
-
-
- -
+
-
Qt::Horizontal
@@ -34,6 +31,19 @@
+ -
+
+
+ -
+
+
+ -
+
+
+ Value
+
+
+
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h b/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h
index c2a81373526..622dc366edb 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h
@@ -54,7 +54,8 @@ const char timelineInsertKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesigner
const char timelineDeleteKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Delete All Keyframes");
-const char timelineStatusBarFrameNumber[] = QT_TRANSLATE_NOOP("QmlDesignerTimeline", "Frame %1");
+const char statusBarPlayheadFrame[] = QT_TRANSLATE_NOOP("QmlDesignerTimeline", "Playhead frame %1");
+const char statusBarKeyframe[] = QT_TRANSLATE_NOOP("QmlDesignerTimeline", "Keyframe %1");
const char C_QMLTIMELINE[] = "QmlDesigner::Timeline";
const char C_SETTINGS[] = "QmlDesigner.Settings";
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
index 97ebb7e84d0..a5f61108122 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp
@@ -187,14 +187,14 @@ void TimelineGraphicsScene::setCurrentFrame(int frame)
if (timeline.isValid()) {
timeline.modelNode().setAuxiliaryData("currentFrame@NodeInstance", frame);
- m_currentFrameIndicator->setPosition(frame + timeline.startKeyframe());
+ m_currentFrameIndicator->setPosition(frame);
} else {
m_currentFrameIndicator->setPosition(0);
}
invalidateCurrentValues();
- emitStatusBarFrameMessageChanged(frame);
+ emitStatusBarPlayheadFrameChanged(frame);
}
void TimelineGraphicsScene::setStartFrame(int frame)
@@ -318,7 +318,7 @@ void TimelineGraphicsScene::commitCurrentFrame(qreal frame)
setCurrenFrame(timeline, qRound(frame));
invalidateCurrentValues();
}
- emitStatusBarFrameMessageChanged(int(frame));
+ emitStatusBarPlayheadFrameChanged(int(frame));
}
QList TimelineGraphicsScene::selectedKeyframes() const
@@ -700,10 +700,10 @@ void TimelineGraphicsScene::emitScrollOffsetChanged()
TimelineMovableAbstractItem::emitScrollOffsetChanged(item);
}
-void TimelineGraphicsScene::emitStatusBarFrameMessageChanged(int frame)
+void TimelineGraphicsScene::emitStatusBarPlayheadFrameChanged(int frame)
{
emit statusBarMessageChanged(
- QString(TimelineConstants::timelineStatusBarFrameNumber).arg(frame));
+ tr(TimelineConstants::statusBarPlayheadFrame).arg(frame));
}
bool TimelineGraphicsScene::event(QEvent *event)
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h
index b8f93595c44..d03a6a58242 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h
@@ -160,7 +160,7 @@ private:
ModelNode timelineModelNode() const;
void emitScrollOffsetChanged();
- void emitStatusBarFrameMessageChanged(int frame);
+ void emitStatusBarPlayheadFrameChanged(int frame);
QList itemsAt(const QPointF &pos);
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp
index 4db4567fd69..1d700cf063f 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp
@@ -46,6 +46,11 @@ void TimelineMovableAbstractItem::itemMoved(const QPointF & /*start*/, const QPo
setPositionInteractive(end);
}
+void TimelineMovableAbstractItem::itemDoubleClicked()
+{
+ // to be overridden by child classes if needed
+}
+
int TimelineMovableAbstractItem::scrollOffset() const
{
return timelineScene()->scrollOffset();
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h
index 0830facfbfb..cf71397225e 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h
@@ -57,6 +57,7 @@ public:
virtual void setPositionInteractive(const QPointF &point);
virtual void commitPosition(const QPointF &point);
virtual void itemMoved(const QPointF &start, const QPointF &end);
+ virtual void itemDoubleClicked();
int xPosScrollOffset(int x) const;
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp
index 0e68a63ff4c..71c76e5f676 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp
@@ -100,6 +100,9 @@ void TimelineMoveTool::mouseMoveEvent(TimelineMovableAbstractItem *item,
current->setPosition(sourceFrame + deltaFrame);
+ scene()->statusBarMessageChanged(tr(TimelineConstants::statusBarKeyframe)
+ .arg(sourceFrame + deltaFrame));
+
for (auto *keyframe : scene()->selectedKeyframes()) {
if (keyframe != current) {
qreal pos = std::round(current->mapFromSceneToFrame(keyframe->rect().center().x()));
@@ -125,29 +128,36 @@ void TimelineMoveTool::mouseReleaseEvent(TimelineMovableAbstractItem *item,
double start = current->mapFromFrameToScene(scene()->startFrame());
double end = current->mapFromFrameToScene(scene()->endFrame());
- if (mousePos < start) {
- scene()->setCurrentFrame(scene()->startFrame());
- scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(scene()->startFrame()));
- return;
- } else if (mousePos > end) {
- scene()->setCurrentFrame(scene()->endFrame());
- scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(scene()->endFrame()));
+ double limitFrame = -999999.;
+ if (mousePos < start)
+ limitFrame = scene()->startFrame();
+ else if (mousePos > end)
+ limitFrame = scene()->endFrame();
+
+ if (limitFrame > -999999.) {
+ scene()->setCurrentFrame(limitFrame);
+ scene()->statusBarMessageChanged(
+ tr(TimelineConstants::statusBarPlayheadFrame).arg(limitFrame));
return;
}
}
- scene()->timelineView()->executeInTransaction("TimelineMoveTool::mouseReleaseEvent", [this, current](){
+ scene()->timelineView()->executeInTransaction("TimelineMoveTool::mouseReleaseEvent",
+ [this, current]() {
current->commitPosition(mapToItem(current, current->rect().center()));
if (current->asTimelineKeyframeItem()) {
double frame = std::round(
current->mapFromSceneToFrame(current->rect().center().x()));
- scene()->statusBarMessageChanged(QObject::tr("Frame %1").arg(frame));
+ scene()->statusBarMessageChanged(
+ tr(TimelineConstants::statusBarKeyframe).arg(frame));
- for (auto keyframe : scene()->selectedKeyframes())
+ const auto selectedKeyframes = scene()->selectedKeyframes();
+ for (auto keyframe : selectedKeyframes) {
if (keyframe != current)
keyframe->commitPosition(mapToItem(current, keyframe->rect().center()));
+ }
}
});
}
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h
index 55b9a394174..20b9537af9a 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h
@@ -27,6 +27,7 @@
#include "timelineabstracttool.h"
+#include
#include
QT_FORWARD_DECLARE_CLASS(QGraphicsRectItem)
@@ -37,6 +38,8 @@ class TimelineMovableAbstractItem;
class TimelineMoveTool : public TimelineAbstractTool
{
+ Q_DECLARE_TR_FUNCTIONS(TimelineMoveTool)
+
public:
explicit TimelineMoveTool(TimelineGraphicsScene *scene, TimelineToolDelegate *delegate);
void mousePressEvent(TimelineMovableAbstractItem *item,
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
index beeca23183b..920a8b35ca9 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp
@@ -106,31 +106,40 @@ static void setEasingCurve(TimelineGraphicsScene *scene, const QList
EasingCurveDialog::runDialog(keys);
}
-static void editValue(const ModelNode &frame, const QString &propertyName)
+// display and handle the edit keyframe dialog
+static void editValue(const ModelNode &frameNode, const std::pair &timelineRange,
+ const QString &propertyName)
{
- const QVariant value = frame.variantProperty("value").value();
- auto dialog = new SetFrameValueDialog(Core::ICore::dialogParent());
-
- dialog->lineEdit()->setText(value.toString());
- dialog->setPropertName(propertyName);
+ const qreal frame = frameNode.variantProperty("frame").value().toReal();
+ const QVariant value = frameNode.variantProperty("value").value();
+ auto dialog = new SetFrameValueDialog(frame, value, propertyName,
+ Core::ICore::dialogParent());
QObject::connect(dialog, &SetFrameValueDialog::rejected, [dialog]() { dialog->deleteLater(); });
- QObject::connect(dialog, &SetFrameValueDialog::accepted, [dialog, frame, value]() {
+ QObject::connect(dialog, &SetFrameValueDialog::accepted, [dialog, frameNode, frame, value,
+ timelineRange]() {
dialog->deleteLater();
- int userType = value.userType();
- const QVariant result = dialog->lineEdit()->text();
- if (result.canConvert(userType)) {
- QVariant newValue = result;
- newValue.convert(userType);
- // canConvert gives true in case if the result is a double but the usertype was interger
- // try to fix that with a workaround to convert it to double if convertion resulted in isNull
- if (newValue.isNull()) {
- newValue = result;
- newValue.convert(QMetaType::Double);
+ qreal newFrame = qBound(timelineRange.first, dialog->frame(), timelineRange.second);
+ if (newFrame != frame)
+ frameNode.variantProperty("frame").setValue(newFrame);
+
+ int userType = value.userType();
+ QVariant newValue = dialog->value();
+
+ if (newValue.canConvert(userType)) {
+ QVariant newValueConverted = newValue;
+ bool converted = newValueConverted.convert(userType);
+
+ if (!converted) {
+ // convert() fails for int to double, so we try this combination
+ newValueConverted = newValue;
+ converted = newValueConverted.convert(QMetaType::Double);
}
- frame.variantProperty("value").setValue(result);
+
+ if (converted)
+ frameNode.variantProperty("value").setValue(newValueConverted);
}
});
@@ -431,9 +440,12 @@ void TimelinePropertyItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *even
setEasingCurve(timelineScene(), {currentFrameNode});
});
- QAction *editValueAction = mainMenu.addAction(tr("Edit Value for Keyframe..."));
+ QAction *editValueAction = mainMenu.addAction(tr("Edit Keyframe..."));
QObject::connect(editValueAction, &QAction::triggered, [this, currentFrameNode]() {
- editValue(currentFrameNode, propertyName());
+ std::pair timelineRange
+ = {timelineScene()->currentTimeline().startKeyframe(),
+ timelineScene()->currentTimeline().endKeyframe()};
+ editValue(currentFrameNode, timelineRange, propertyName());
});
const bool hasKeyframe = currentFrameNode.isValid();
@@ -541,6 +553,13 @@ void TimelineKeyframeItem::commitPosition(const QPointF &point)
enableUpdates();
}
+void TimelineKeyframeItem::itemDoubleClicked()
+{
+ std::pair timelineRange = {timelineScene()->currentTimeline().startKeyframe(),
+ timelineScene()->currentTimeline().endKeyframe()};
+ editValue(m_frame, timelineRange, propertyItem()->propertyName());
+}
+
TimelineKeyframeItem *TimelineKeyframeItem::asTimelineKeyframeItem()
{
return this;
@@ -630,9 +649,11 @@ void TimelineKeyframeItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *even
setEasingCurve(timelineScene(), keys);
});
- QAction *editValueAction = mainMenu.addAction(tr("Edit Value for Keyframe..."));
+ QAction *editValueAction = mainMenu.addAction(tr("Edit Keyframe..."));
QObject::connect(editValueAction, &QAction::triggered, [this]() {
- editValue(m_frame, propertyItem()->propertyName());
+ std::pair timelineRange = {timelineScene()->currentTimeline().startKeyframe(),
+ timelineScene()->currentTimeline().endKeyframe()};
+ editValue(m_frame, timelineRange, propertyItem()->propertyName());
});
mainMenu.exec(event->screenPos());
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h
index 2b8c00c59bc..4544b403029 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h
@@ -63,6 +63,8 @@ public:
void commitPosition(const QPointF &point) override;
+ void itemDoubleClicked() override;
+
TimelineKeyframeItem *asTimelineKeyframeItem() override;
protected:
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
index 987ac4935a6..c9ab3044976 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp
@@ -98,7 +98,6 @@ void TimelineSelectionTool::mouseReleaseEvent(TimelineMovableAbstractItem *item,
QGraphicsSceneMouseEvent *event)
{
Q_UNUSED(item)
- Q_UNUSED(event)
commitSelection(selectionMode(event));
@@ -108,9 +107,11 @@ void TimelineSelectionTool::mouseReleaseEvent(TimelineMovableAbstractItem *item,
void TimelineSelectionTool::mouseDoubleClickEvent(TimelineMovableAbstractItem *item,
QGraphicsSceneMouseEvent *event)
{
- Q_UNUSED(item)
Q_UNUSED(event)
+ if (item)
+ item->itemDoubleClicked();
+
reset();
}
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp
index 51c5a7d0889..d84a4619998 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp
@@ -92,8 +92,10 @@ void TimelineToolDelegate::mouseReleaseEvent(TimelineMovableAbstractItem *item,
void TimelineToolDelegate::mouseDoubleClickEvent(TimelineMovableAbstractItem *item,
QGraphicsSceneMouseEvent *event)
{
- if (m_currentTool)
+ if (hitCanvas(event)) {
+ m_currentTool = m_selectTool.get();
m_currentTool->mouseDoubleClickEvent(item, event);
+ }
reset();
}
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
index 522607f615b..303c761f3c9 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
+++ b/src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp
@@ -405,14 +405,18 @@ void TimelineWidget::contextHelp(const Core::IContext::HelpCallback &callback) c
void TimelineWidget::init()
{
QmlTimeline currentTimeline = m_timelineView->timelineForState(m_timelineView->currentState());
- if (currentTimeline.isValid())
+ if (currentTimeline.isValid()) {
setTimelineId(currentTimeline.modelNode().id());
- else
+ m_statusBar->setText(tr(TimelineConstants::statusBarPlayheadFrame)
+ .arg(getcurrentFrame(currentTimeline)));
+ } else {
setTimelineId({});
+ m_statusBar->clear();
+ }
- invalidateTimelineDuration(graphicsScene()->currentTimeline());
+ invalidateTimelineDuration(m_graphicsScene->currentTimeline());
- graphicsScene()->setWidth(m_graphicsView->viewport()->width());
+ m_graphicsScene->setWidth(m_graphicsView->viewport()->width());
// setScaleFactor uses QSignalBlocker.
m_toolbar->setScaleFactor(0);
@@ -442,7 +446,14 @@ void TimelineWidget::invalidateTimelineDuration(const QmlTimeline &timeline)
QmlTimeline currentTimeline = graphicsScene()->currentTimeline();
if (currentTimeline.isValid() && currentTimeline == timeline) {
graphicsScene()->setTimeline(timeline);
- graphicsScene()->setCurrenFrame(timeline, getcurrentFrame(timeline));
+
+ qreal playHeadFrame = getcurrentFrame(timeline);
+ if (playHeadFrame < timeline.startKeyframe())
+ playHeadFrame = timeline.startKeyframe();
+ else if (playHeadFrame > timeline.endKeyframe())
+ playHeadFrame = timeline.endKeyframe();
+
+ graphicsScene()->setCurrentFrame(playHeadFrame);
}
}
}