summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2019-09-27 14:22:41 +0200
committerEike Ziller <eike.ziller@qt.io>2019-09-27 14:22:41 +0200
commit68d08c162a8d191e7777aefc84f4401b5fb70aeb (patch)
tree3bfd7a29374b96a4e0a815c39506b9063996c10a
parent642be639919dbb92d9248dfd635ecbed9a0bb726 (diff)
parentd4c0f9e5103056cb9e7d6a4affbd6000b39e98e5 (diff)
downloadqt-creator-68d08c162a8d191e7777aefc84f4401b5fb70aeb.tar.gz
Merge remote-tracking branch 'origin/4.11'
Change-Id: I3fd1723e8c097bf6df8933c122fcc006ad0af9e7
-rw-r--r--share/qtcreator/translations/qtcreator_ru.ts165
-rw-r--r--src/libs/utils/touchbar/touchbar_mac.mm4
-rw-r--r--src/plugins/clangtools/CMakeLists.txt2
-rw-r--r--src/plugins/clangtools/clangselectablefilesdialog.cpp54
-rw-r--r--src/plugins/clangtools/clangselectablefilesdialog.ui67
-rw-r--r--src/plugins/clangtools/clangtidyclazytool.cpp569
-rw-r--r--src/plugins/clangtools/clangtidyclazytool.h85
-rw-r--r--src/plugins/clangtools/clangtool.cpp491
-rw-r--r--src/plugins/clangtools/clangtool.h52
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.cpp35
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.h13
-rw-r--r--src/plugins/clangtools/clangtools.pro5
-rw-r--r--src/plugins/clangtools/clangtools.qbs5
-rw-r--r--src/plugins/clangtools/clangtoolslogfilereader.cpp2
-rw-r--r--src/plugins/clangtools/clangtoolsplugin.cpp24
-rw-r--r--src/plugins/clangtools/clangtoolspreconfiguredsessiontests.cpp8
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettings.cpp87
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettings.h16
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp46
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettingswidget.h2
-rw-r--r--src/plugins/clangtools/clangtoolsprojectsettingswidget.ui134
-rw-r--r--src/plugins/clangtools/clangtoolssettings.cpp182
-rw-r--r--src/plugins/clangtools/clangtoolssettings.h66
-rw-r--r--src/plugins/clangtools/clangtoolsunittests.cpp19
-rw-r--r--src/plugins/clangtools/runsettingswidget.cpp87
-rw-r--r--src/plugins/clangtools/runsettingswidget.h58
-rw-r--r--src/plugins/clangtools/runsettingswidget.ui93
-rw-r--r--src/plugins/clangtools/settingswidget.cpp60
-rw-r--r--src/plugins/clangtools/settingswidget.h3
-rw-r--r--src/plugins/clangtools/settingswidget.ui61
-rw-r--r--src/plugins/coreplugin/windowsupport.cpp4
-rw-r--r--src/plugins/coreplugin/windowsupport.h1
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.cpp24
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.h8
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui24
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h3
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.cpp10
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinegraphicsscene.h2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp5
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.h1
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.cpp30
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinemovetool.h3
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.cpp65
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinepropertyitem.h2
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelineselectiontool.cpp5
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinetooldelegate.cpp4
-rw-r--r--src/plugins/qmldesigner/components/timelineeditor/timelinewidget.cpp21
47 files changed, 1423 insertions, 1284 deletions
diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts
index 5bffaae635..16a28c2f65 100644
--- a/share/qtcreator/translations/qtcreator_ru.ts
+++ b/share/qtcreator/translations/qtcreator_ru.ts
@@ -131,11 +131,70 @@
</message>
</context>
<context>
+ <name>AnchorButtons</name>
+ <message>
+ <source>Anchor item to the top.</source>
+ <translation>Привязка элемента к верхнему краю.</translation>
+ </message>
+ <message>
+ <source>Anchor item to the bottom.</source>
+ <translation>Привязка элемента к нижнему краю.</translation>
+ </message>
+ <message>
+ <source>Anchor item to the left.</source>
+ <translation>Привязка элемента к левому краю.</translation>
+ </message>
+ <message>
+ <source>Anchor item to the right.</source>
+ <translation>Привязка элемента к правому краю.</translation>
+ </message>
+ <message>
+ <source>Fill parent item.</source>
+ <translation>Заполнить родительский элемент.</translation>
+ </message>
+ <message>
+ <source>Anchor item vertically.</source>
+ <translation>Вертикальная привязка элемента.</translation>
+ </message>
+ <message>
+ <source>Anchor item horizontally.</source>
+ <translation>Горизонтальная привязка элемента.</translation>
+ </message>
+</context>
+<context>
<name>AnchorRow</name>
<message>
<source>Target</source>
<translation>Цель</translation>
</message>
+ <message>
+ <source>Margin</source>
+ <translation>Внешний отступ</translation>
+ </message>
+ <message>
+ <source>Anchor to the top of the target.</source>
+ <translation>Привязка к верхнему краю цели.</translation>
+ </message>
+ <message>
+ <source>Anchor to the left of the target.</source>
+ <translation>Привязка к левому краю цели.</translation>
+ </message>
+ <message>
+ <source>Anchor to the vertical center of the target.</source>
+ <translation>Привязка к вертикальному центру цели.</translation>
+ </message>
+ <message>
+ <source>Anchor to the horizontal center of the target.</source>
+ <translation>Привязка к горизонтальному центру цели.</translation>
+ </message>
+ <message>
+ <source>Anchor to the bottom of the target.</source>
+ <translation>Привязка к нижнему краю цели.</translation>
+ </message>
+ <message>
+ <source>Anchor to the right of the target.</source>
+ <translation>Привязка к правому краю цели.</translation>
+ </message>
</context>
<context>
<name>Android::AndroidBuildApkStep</name>
@@ -1903,7 +1962,7 @@ Install an SDK of at least API version %1.</source>
</message>
<message>
<source>%1 tests passed.</source>
- <translation>%1 тестов прошли успешно.</translation>
+ <translation>%1 тестов прошло успешно.</translation>
</message>
<message>
<source>No errors detected.</source>
@@ -3241,7 +3300,7 @@ Warning: this is an experimental feature and might lead to failing to execute th
</message>
<message>
<source>The kit has a Qt version, but no C++ compiler.</source>
- <translation>У комплекта задан профил Qt, но нет компилятора C++.</translation>
+ <translation>У комплекта задан профиль Qt, но нет компилятора C++.</translation>
</message>
<message>
<source>Name:</source>
@@ -4476,7 +4535,7 @@ For example, &quot;Revision: 15&quot; will leave the branch at revision 15.</sou
</message>
<message>
<source>A seed of 0 means no randomization. A value of 1 uses the current time any other value is used as random seed generator.</source>
- <translation>0 отключает случайный порядок. Значение 1 использует текущее время, любой другое используется для генерации случайной последовательности.</translation>
+ <translation>0 отключает случайный порядок. Значение 1 использует текущее время, любое другое используется для генерации случайной последовательности.</translation>
</message>
<message>
<source>Catch or ignore system errors.</source>
@@ -7117,6 +7176,10 @@ p, li { white-space: pre-wrap; }
<translation>Недавний</translation>
</message>
<message>
+ <source>Open Color Dialog</source>
+ <translation>Открыть выбор цвета</translation>
+ </message>
+ <message>
<source>Defines the start angle for the conical gradient. The value is in degrees (0-360).</source>
<translation>Определяет начальный угол для конического градиента. Значение в градусах от 0 до 360.</translation>
</message>
@@ -9120,11 +9183,11 @@ Do you want to kill it?</source>
</message>
<message>
<source>Cycle Mode Selector Styles</source>
- <translation type="unfinished">Зациклить стили режима выбора</translation>
+ <translation>Зациклить стили режима выбора</translation>
</message>
<message>
<source>Mode Selector Style</source>
- <translation type="unfinished">Стиль режима выбора</translation>
+ <translation>Стиль режима выбора</translation>
</message>
<message>
<source>Icons and Text</source>
@@ -16270,7 +16333,7 @@ You can choose another communication channel here, such as a serial line or cust
</message>
<message>
<source>Creation Time in ms</source>
- <translation>Время создания в мс</translation>
+ <translation>Время создания, мс</translation>
</message>
<message>
<source>&lt;empty&gt;</source>
@@ -17359,7 +17422,7 @@ Rebuilding the project might help.</source>
</message>
<message>
<source>Drag Margin</source>
- <translation>Поле перетаскивания</translation>
+ <translation>Зона перетаскивания</translation>
</message>
<message>
<source>Defines the distance from the screen edge within which drag actions will open the drawer.</source>
@@ -18418,6 +18481,10 @@ will also disable the following plugins:
<translation>Определяет, будет ли Flickable создавать ощущение, что края у вида мягкие, а не жесткие физические границы.</translation>
</message>
<message>
+ <source>Describes whether the user can interact with the Flickable. A user cannot drag or flick a Flickable that is not interactive.</source>
+ <translation>Определяет, может ли пользователь влиять на Flickable. Пользователь не может перетягивать или сдвигать Flickable, если он не интерактивен.</translation>
+ </message>
+ <message>
<source>Press delay</source>
<translation>Задержка нажатия</translation>
</message>
@@ -18443,7 +18510,7 @@ will also disable the following plugins:
</message>
<message>
<source>Margins</source>
- <translation>Отступы</translation>
+ <translation>Внешние отступы</translation>
</message>
<message>
<source>Flick direction</source>
@@ -20499,7 +20566,7 @@ Commit now?</source>
</message>
<message>
<source>DCommit</source>
- <translation type="unfinished">Дельта фиксация (dcommit)</translation>
+ <translation>Дельта фиксация (dcommit)</translation>
</message>
<message>
<source>Manage Remotes...</source>
@@ -23443,7 +23510,7 @@ Error: %5</translation>
</message>
<message>
<source>Margins</source>
- <translation>Отступы</translation>
+ <translation>Внешние отступы</translation>
</message>
<message>
<source>Row span</source>
@@ -23954,7 +24021,7 @@ Error: %5</translation>
<name>MarginSection</name>
<message>
<source>Margin</source>
- <translation>Поле</translation>
+ <translation>Внешний отступ</translation>
</message>
<message>
<source>Vertical</source>
@@ -23998,7 +24065,7 @@ Error: %5</translation>
</message>
<message>
<source>Margins</source>
- <translation>Отступы</translation>
+ <translation>Внешние отступы</translation>
</message>
<message>
<source>The margins around the item.</source>
@@ -25088,7 +25155,7 @@ Error: %5</translation>
</message>
<message>
<source>Drag margin</source>
- <translation>Перетаскиваемый край</translation>
+ <translation>Зона перетаскивания</translation>
</message>
<message>
<source>Flick deceleration</source>
@@ -25795,12 +25862,12 @@ Error: %5</translation>
</message>
<message>
<source>Self Samples</source>
- <translation type="unfinished">Собственных семплов</translation>
+ <translation>Собственных семплов</translation>
</message>
<message>
<source>Self in Percent</source>
<translatorcomment>х.з. как переводить</translatorcomment>
- <translation type="unfinished">Собственное в процентах</translation>
+ <translation>Собственное в процентах</translation>
</message>
</context>
<context>
@@ -26741,7 +26808,7 @@ Error: %5</translation>
</message>
<message>
<source>Build/Deployment canceled</source>
- <translation>Сборка/разворачивание отменено</translation>
+ <translation>Сборка/развёртывание отменено</translation>
</message>
<message>
<source>When executing step &quot;%1&quot;</source>
@@ -26754,7 +26821,7 @@ Error: %5</translation>
<message>
<source>Deployment</source>
<comment>Category for deployment issues listed under &apos;Issues&apos;</comment>
- <translation>Разворачивание</translation>
+ <translation>Развёртывание</translation>
</message>
<message>
<source>Autotests</source>
@@ -26763,11 +26830,11 @@ Error: %5</translation>
</message>
<message>
<source>Canceled build/deployment.</source>
- <translation>Сборка/разворачивание было отменено.</translation>
+ <translation>Сборка/развёртывание было отменено.</translation>
</message>
<message>
<source>Error while building/deploying project %1 (kit: %2)</source>
- <translation>Ошибка при сборке/разворачивании проекта %1 (комплект: %2)</translation>
+ <translation>Ошибка при сборке/развёртывании проекта %1 (комплект: %2)</translation>
</message>
<message>
<source>The kit %1 has configuration issues which might be the root cause for this problem.</source>
@@ -27022,21 +27089,21 @@ Error: %5</translation>
<message>
<source>Deploy</source>
<extracomment>Display name of the deploy build step list. Used as part of the labels in the project window.</extracomment>
- <translation>Разваорачивание</translation>
+ <translation>Развёртывание</translation>
</message>
<message>
<source>Deploy locally</source>
<extracomment>Default DeployConfiguration display name</extracomment>
- <translation>Локальное разворачивание</translation>
+ <translation>Локальное развёртывание</translation>
</message>
<message>
<source>Deploy Configuration</source>
<extracomment>Display name of the default deploy configuration</extracomment>
- <translation>Конфигурация разворачивания</translation>
+ <translation>Конфигурация развёртывания</translation>
</message>
<message>
<source>Deploy Settings</source>
- <translation>Настройки разворачивания</translation>
+ <translation>Настройки развёртывания</translation>
</message>
</context>
<context>
@@ -27054,7 +27121,7 @@ Error: %5</translation>
<name>ProjectExplorer::DeploymentDataView</name>
<message>
<source>Files to deploy:</source>
- <translation>Разворачиваемые файлы:</translation>
+ <translation>Файлы для развёртывания:</translation>
</message>
</context>
<context>
@@ -27360,11 +27427,11 @@ Error: %5</translation>
</message>
<message>
<source>Append Path...</source>
- <translation type="unfinished">Добавить после пути...</translation>
+ <translation>Добавить после пути...</translation>
</message>
<message>
<source>Prepend Path...</source>
- <translation type="unfinished">Добавить перед путём...</translation>
+ <translation>Добавить перед путём...</translation>
</message>
<message>
<source>&amp;Batch Edit...</source>
@@ -27987,7 +28054,7 @@ Excluding: %2
</message>
<message>
<source>Synchronize active kit, build, and deploy configuration between projects.</source>
- <translation>Сихронизировать у проектов текущий комплект и конфигурации сборки и разворачивания.</translation>
+ <translation>Сихронизировать у проектов текущий комплект и конфигурации сборки и развёртывания.</translation>
</message>
</context>
<context>
@@ -28492,7 +28559,7 @@ What should Qt Creator do now?</source>
</message>
<message>
<source>Deploy</source>
- <translation>Разворачивание</translation>
+ <translation>Развёртывание</translation>
</message>
<message>
<source>Run</source>
@@ -28520,7 +28587,7 @@ What should Qt Creator do now?</source>
</message>
<message>
<source>&lt;b&gt;Deploy:&lt;/b&gt; %1</source>
- <translation>&lt;b&gt;Разворачивание:&lt;/b&gt; %1</translation>
+ <translation>&lt;b&gt;Развёртывание:&lt;/b&gt; %1</translation>
</message>
<message>
<source>&lt;b&gt;Run:&lt;/b&gt; %1</source>
@@ -28544,7 +28611,7 @@ What should Qt Creator do now?</source>
</message>
<message>
<source>Deploy: &lt;b&gt;%1&lt;/b&gt;&lt;br/&gt;</source>
- <translation>Разворачивание: &lt;b&gt;%1&lt;/b&gt;&lt;br/&gt;</translation>
+ <translation>Развёртывание: &lt;b&gt;%1&lt;/b&gt;&lt;br/&gt;</translation>
</message>
<message>
<source>Run: &lt;b&gt;%1&lt;/b&gt;&lt;br/&gt;</source>
@@ -28687,11 +28754,11 @@ What should Qt Creator do now?</source>
</message>
<message>
<source>Always build project before deploying it</source>
- <translation>Всегда собирать проект перед разворачиванием</translation>
+ <translation>Всегда собирать проект перед развёртыванием</translation>
</message>
<message>
<source>Always deploy project before running it</source>
- <translation>Всегда разворачивать проект перед запуском</translation>
+ <translation>Всегда развёртывать проект перед запуском</translation>
</message>
<message>
<source>Always ask before stopping applications</source>
@@ -29053,7 +29120,7 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>Deployment</source>
- <translation>Разворачивание</translation>
+ <translation>Развёртывание</translation>
</message>
<message>
<source>Method:</source>
@@ -29082,7 +29149,7 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>Cancel Build &amp;&amp; Remove Deploy Configuration</source>
- <translation>Отменить сборку и удалить конфигурацию разворачивания</translation>
+ <translation>Отменить сборку и удалить конфигурацию развёртывания</translation>
</message>
<message>
<source>Do Not Remove</source>
@@ -29090,27 +29157,27 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>Remove Deploy Configuration %1?</source>
- <translation>Удаление конфигурации разворачивания %1</translation>
+ <translation>Удаление конфигурации развёртывания %1</translation>
</message>
<message>
<source>The deploy configuration &lt;b&gt;%1&lt;/b&gt; is currently being built.</source>
- <translation>В данный момент идёт сборка с использованием конфигурации разворачивания &lt;b&gt;%1&lt;/b&gt;.</translation>
+ <translation>В данный момент идёт сборка с использованием конфигурации развёртывания &lt;b&gt;%1&lt;/b&gt;.</translation>
</message>
<message>
<source>Do you want to cancel the build process and remove the Deploy Configuration anyway?</source>
- <translation>Остановить процесс сборки и удалить конфигурацию разворачивания?</translation>
+ <translation>Остановить процесс сборки и удалить конфигурацию развёртывания?</translation>
</message>
<message>
<source>Remove Deploy Configuration?</source>
- <translation>Удаление конфигурации разворачивания</translation>
+ <translation>Удаление конфигурации развёртывания</translation>
</message>
<message>
<source>Do you really want to delete deploy configuration &lt;b&gt;%1&lt;/b&gt;?</source>
- <translation>Желаете удалить конфигурацию разворачивания &lt;b&gt;%1&lt;/b&gt;?</translation>
+ <translation>Желаете удалить конфигурацию развёртывания &lt;b&gt;%1&lt;/b&gt;?</translation>
</message>
<message>
<source>New name for deploy configuration &lt;b&gt;%1&lt;/b&gt;:</source>
- <translation>Новое название конфигурации разворачивания &lt;b&gt;%1&lt;/b&gt;:</translation>
+ <translation>Новое название конфигурации развёртывания &lt;b&gt;%1&lt;/b&gt;:</translation>
</message>
</context>
<context>
@@ -30027,7 +30094,7 @@ to project &quot;%2&quot;.</source>
</message>
<message>
<source>QML File (Qt Quick 2)</source>
- <translation>Файл QML (Qt Quck 2)</translation>
+ <translation>Файл QML (Qt Quick 2)</translation>
</message>
<message>
<source>Creates a scratch buffer using a temporary file.</source>
@@ -31178,7 +31245,7 @@ Please close all running instances of your application before starting a build.<
</message>
<message>
<source>Deploy configurations:</source>
- <translation>Конфигурации разворачивания:</translation>
+ <translation>Конфигурации развёртывания:</translation>
</message>
<message>
<source>Run configurations:</source>
@@ -31581,7 +31648,7 @@ Rename %2 to %3 anyway?</source>
</message>
<message>
<source>Run Without Deployment</source>
- <translation>Запустить без разворачивания</translation>
+ <translation>Запустить без развёртывания</translation>
</message>
<message>
<source>New Subproject...</source>
@@ -33828,7 +33895,7 @@ Neither the path to the library nor the path to its includes is added to the .pr
</message>
<message>
<source>Qmake has subtle bugs that can be triggered if source and build directory are not at the same level.</source>
- <translation>Qmake содержит ошибку, возникающую при нахождении каталогов сборки и исходников на разных уровнях.</translation>
+ <translation>Qmake содержит ошибку, которая может проявляться, если каталоги сборки и исходников находятся на разных уровнях.</translation>
</message>
<message>
<source>Run qmake on every build</source>
@@ -38341,7 +38408,7 @@ Saving failed.</source>
<name>Qnx::Internal::QnxDeployQtLibrariesDialog</name>
<message>
<source>Qt library to deploy:</source>
- <translation>Разворачиваемая Qt:</translation>
+ <translation>Библиотека Qt для развёртывания:</translation>
</message>
<message>
<source>Deploy</source>
@@ -38766,6 +38833,10 @@ For more details, see /etc/sysctl.d/10-ptrace.conf
<translation>Тип</translation>
</message>
<message>
+ <source>Change the type of this item.</source>
+ <translation>Меняет тип этого элемента.</translation>
+ </message>
+ <message>
<source>id</source>
<translation>идентификатор</translation>
</message>
@@ -42948,7 +43019,7 @@ Specifies how backspace interacts with indentation.
</message>
<message>
<source>Timeout in ms:</source>
- <translation>Таймаут в мс:</translation>
+ <translation>Таймаут, мс:</translation>
</message>
<message>
<source>Inserts the common prefix of available completion items.</source>
@@ -47925,7 +47996,7 @@ What do you want to do?</source>
</message>
<message>
<source>Multi-paradigm language for creating highly dynamic applications.</source>
- <translation>Многопарадигмый язый для создания высокодинамичных приложений.</translation>
+ <translation>Мультипарадигменный язык для создания высокодинамичных приложений.</translation>
</message>
<message>
<source>Run your concepts and prototypes on your final hardware.</source>
diff --git a/src/libs/utils/touchbar/touchbar_mac.mm b/src/libs/utils/touchbar/touchbar_mac.mm
index ee5a45bf72..dfaf670087 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 93195bdfb9..f5f2c2a84c 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 c9fce5552f..6541ca46bc 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<int>::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 &currentConfigId) {
- 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<FilePath> checkedDirs;
QSet<FilePath> checkedFiles;
m_filesModel->minimalSelection(checkedDirs, checkedFiles);
diff --git a/src/plugins/clangtools/clangselectablefilesdialog.ui b/src/plugins/clangtools/clangselectablefilesdialog.ui
index 267b36364a..834f3fc189 100644
--- a/src/plugins/clangtools/clangselectablefilesdialog.ui
+++ b/src/plugins/clangtools/clangselectablefilesdialog.ui
@@ -11,66 +11,14 @@
</rect>
</property>
<property name="windowTitle">
- <string>Analyzer Configuration</string>
+ <string>Files to Analyze</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QGroupBox" name="groupBox_3">
- <property name="title">
- <string>General</string>
+ <widget class="QTreeView" name="filesView">
+ <property name="headerHidden">
+ <bool>true</bool>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QComboBox" name="globalOrCustom">
- <item>
- <property name="text">
- <string>Global Settings</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Custom Settings</string>
- </property>
- </item>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <widget class="CppTools::ClangDiagnosticConfigsSelectionWidget" name="diagnosticWidget" native="true"/>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="title">
- <string>Files to Analyze</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QTreeView" name="filesView">
- <property name="headerHidden">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
</widget>
</item>
<item>
@@ -85,13 +33,6 @@
</item>
</layout>
</widget>
- <customwidgets>
- <customwidget>
- <class>CppTools::ClangDiagnosticConfigsSelectionWidget</class>
- <extends>QWidget</extends>
- <header>cpptools/clangdiagnosticconfigsselectionwidget.h</header>
- </customwidget>
- </customwidgets>
<resources/>
<connections>
<connection>
diff --git a/src/plugins/clangtools/clangtidyclazytool.cpp b/src/plugins/clangtools/clangtidyclazytool.cpp
deleted file mode 100644
index 85be64da49..0000000000
--- 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 <coreplugin/actionmanager/actioncontainer.h>
-#include <coreplugin/actionmanager/actionmanager.h>
-#include <coreplugin/icore.h>
-#include <coreplugin/messagebox.h>
-
-#include <cpptools/clangdiagnosticconfigsmodel.h>
-#include <cpptools/cppcodemodelsettings.h>
-#include <cpptools/cppmodelmanager.h>
-#include <cpptools/cpptoolsreuse.h>
-
-#include <debugger/analyzer/analyzermanager.h>
-
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/projectexplorericons.h>
-#include <projectexplorer/target.h>
-#include <projectexplorer/session.h>
-
-#include <utils/fancylineedit.h>
-#include <utils/utilsicons.h>
-
-#include <QAction>
-#include <QFileDialog>
-#include <QToolButton>
-
-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<DiagnosticItem *> diagnosticItems;
- bool hasScheduledFixits = false;
- };
-
- ApplyFixIts(const QVector<DiagnosticItem *> &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<DiagnosticItem *> itemsScheduledOrSchedulable;
- QVector<DiagnosticItem *> itemsScheduled;
- QVector<DiagnosticItem *> 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<DiagnosticItem *> itemsApplied;
- QVector<DiagnosticItem *> itemsFailedToApply;
- QVector<DiagnosticItem *> 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<QString, RefactoringFileInfo> 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<QAbstractItemModel *>({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<DiagnosticView *>(m_diagnosticView.data())->setSelectedFixItsCount(c);
- });
- connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
- QVector<DiagnosticItem *> 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),
- {},
- &currentError);
-
- 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<Utils::FilePath> &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 be96438117..0000000000
--- 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 <debugger/debuggermainwindow.h>
-
-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<Utils::FilePath> &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 a2ffb83c7b..da9e022b03 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 <coreplugin/actionmanager/actioncontainer.h>
@@ -36,6 +42,7 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
+#include <coreplugin/messagebox.h>
#include <cpptools/cppmodelmanager.h>
@@ -44,19 +51,22 @@
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorericons.h>
-#include <projectexplorer/target.h>
#include <projectexplorer/session.h>
+#include <projectexplorer/target.h>
#include <utils/algorithm.h>
+#include <utils/fancylineedit.h>
#include <utils/fancymainwindow.h>
#include <utils/utilsicons.h>
#include <QAction>
+#include <QFileDialog>
#include <QLabel>
#include <QSortFilterProxyModel>
#include <QToolButton>
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<DiagnosticItem *> diagnosticItems;
+ bool hasScheduledFixits = false;
+ };
+
+ ApplyFixIts(const QVector<DiagnosticItem *> &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<DiagnosticItem *> itemsScheduledOrSchedulable;
+ QVector<DiagnosticItem *> itemsScheduled;
+ QVector<DiagnosticItem *> 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<DiagnosticItem *> itemsApplied;
+ QVector<DiagnosticItem *> itemsFailedToApply;
+ QVector<DiagnosticItem *> 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<QString, RefactoringFileInfo> m_refactoringFileInfos;
+};
+
static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &projectParts)
{
FileInfos fileInfos;
@@ -93,9 +239,24 @@ static FileInfos sortedFileInfos(const QVector<CppTools::ProjectPart::Ptr> &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<QAbstractItemModel *>({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<DiagnosticView *>(m_diagnosticView.data())->setSelectedFixItsCount(c);
+ });
+ connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
+ QVector<DiagnosticItem *> 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<FilePath> &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),
+ {},
+ &currentError);
+
+ 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<Diagnostic> 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 c0b1565260..b61ed1ac44 100644
--- a/src/plugins/clangtools/clangtool.h
+++ b/src/plugins/clangtools/clangtool.h
@@ -29,38 +29,56 @@
#include "clangtoolsdiagnostic.h"
#include "clangtoolslogfilereader.h"
+#include <debugger/debuggermainwindow.h>
+
#include <projectexplorer/runconfiguration.h>
#include <cpptools/projectinfo.h>
-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<Utils::FilePath> &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<Debugger::DetailedErrorView> 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 dc22e7a39b..2af11aa7ef 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 <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
+#include <cpptools/clangdiagnosticconfigsmodel.h>
#include <cpptools/compileroptionsbuilder.h>
+#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppprojectfile.h>
#include <cpptools/cpptoolsreuse.h>
@@ -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 842350a7f4..bfada9e502 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 <cpptools/clangdiagnosticconfig.h>
#include <cpptools/projectinfo.h>
@@ -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:
- ProjectBuilder *m_projectBuilder = nullptr;
- Utils::Environment m_environment;
- Utils::TemporaryDirectory m_temporaryDir;
-
private:
+ RunSettings m_runSettings;
CppTools::ClangDiagnosticConfig m_diagnosticConfig;
FileInfos m_fileInfos;
+ ProjectBuilder *m_projectBuilder = nullptr;
+ Utils::Environment m_environment;
+ Utils::TemporaryDirectory m_temporaryDir;
+
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 a089f1edb7..6173e2eec1 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 32146f87c0..daca2934c1 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 59ea741c25..1fe490a6bf 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 fed9cb2150..12031dc589 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<QWidget> m_widget;
+ QPointer<SettingsWidget> 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 5d711a8aef..2ed19354f2 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 <coreplugin/icore.h>
@@ -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<QVariant> 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<Project *> validProjects(const QList<Project *> projectsOfSession)
diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.cpp b/src/plugins/clangtools/clangtoolsprojectsettings.cpp
index 6c2597789d..005897b49c 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
+ }
+ }
- auto toFileName = [](const QString &s) { return Utils::FilePath::fromString(s); };
+ // Read map
+ m_useGlobalSettings = map.value(SETTINGS_KEY_USE_GLOBAL_SETTINGS).toBool();
- const QStringList dirs = m_project->namedSettings(SETTINGS_KEY_SELECTED_DIRS).toStringList();
+ auto toFileName = [](const QString &s) { return Utils::FilePath::fromString(s); };
+ const QStringList dirs = map.value(SETTINGS_KEY_SELECTED_DIRS).toStringList();
m_selectedDirs = Utils::transform<QSet>(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<QSet>(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<QList>(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<QList>(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;
-}
-
-void ClangToolsProjectSettings::setUseGlobalSettings(bool useGlobalSettings)
-{
- m_useGlobalSettings = useGlobalSettings;
-}
+ m_runSettings.toMap(map, SETTINGS_PREFIX);
-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 0a6aa477d3..aaf045f056 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettings.h
+++ b/src/plugins/clangtools/clangtoolsprojectsettings.h
@@ -25,7 +25,7 @@
#pragma once
-#include <QObject>
+#include "clangtoolssettings.h"
#include <coreplugin/id.h>
#include <projectexplorer/project.h>
@@ -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<Utils::FilePath> selectedDirs() const { return m_selectedDirs; }
void setSelectedDirs(const QSet<Utils::FilePath> &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<Utils::FilePath> m_selectedDirs;
QSet<Utils::FilePath> m_selectedFiles;
+
SuppressedDiagnosticsList m_suppressedDiagnostics;
};
diff --git a/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp b/src/plugins/clangtools/clangtoolsprojectsettingswidget.cpp
index 3e380aa9af..c5b7c53a68 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 <coreplugin/icore.h>
+
#include <utils/qtcassert.h>
#include <QAbstractTableModel>
@@ -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<int>::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 f9153f75a6..680431cc6e 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 c120d3bb95..b8263a450a 100644
--- a/src/plugins/clangtools/clangtoolsprojectsettingswidget.ui
+++ b/src/plugins/clangtools/clangtoolsprojectsettingswidget.ui
@@ -6,20 +6,41 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>300</height>
+ <width>615</width>
+ <height>399</height>
</rect>
</property>
<property name="windowTitle">
<string/>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QLabel" name="label">
+ <widget class="QComboBox" name="globalCustomComboBox">
+ <item>
+ <property name="text">
+ <string>Use Global Settings</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Use Customized Settings</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="restoreGlobal">
<property name="text">
- <string>Suppressed diagnostics:</string>
+ <string>Restore Global Settings</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="gotoGlobalSettingsLabel">
+ <property name="text">
+ <string>&lt;a href=&quot;target&quot;&gt;Show Global Settings&lt;/a&gt;</string>
</property>
</widget>
</item>
@@ -36,52 +57,79 @@
</property>
</spacer>
</item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
- <widget class="QTreeView" name="diagnosticsView">
- <property name="selectionMode">
- <enum>QAbstractItemView::SingleSelection</enum>
+ <widget class="QLabel" name="gotoAnalyzerModeLabel">
+ <property name="text">
+ <string>&lt;a href=&quot;target&quot;&gt;Go to Analyzer&lt;/a&gt;</string>
</property>
</widget>
</item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QPushButton" name="removeSelectedButton">
- <property name="text">
- <string>Remove Selected</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="removeAllButton">
- <property name="text">
- <string>Remove All</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
</layout>
</item>
+ <item>
+ <widget class="ClangTools::Internal::RunSettingsWidget" name="runSettingsWidget" native="true"/>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Suppressed diagnostics</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QTreeView" name="diagnosticsView">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="removeSelectedButton">
+ <property name="text">
+ <string>Remove Selected</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeAllButton">
+ <property name="text">
+ <string>Remove All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>ClangTools::Internal::RunSettingsWidget</class>
+ <extends>QWidget</extends>
+ <header>clangtools/runsettingswidget.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
<resources/>
<connections/>
</ui>
diff --git a/src/plugins/clangtools/clangtoolssettings.cpp b/src/plugins/clangtools/clangtoolssettings.cpp
index 86f152f660..07b9592a8e 100644
--- a/src/plugins/clangtools/clangtoolssettings.cpp
+++ b/src/plugins/clangtools/clangtoolssettings.cpp
@@ -29,160 +29,112 @@
#include <coreplugin/icore.h>
-#include <utils/hostosinfo.h>
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
#include <QThread>
-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";
-namespace ClangTools {
-namespace Internal {
+static const char parallelJobsKey[] = "ParallelJobs";
+static const char buildBeforeAnalysisKey[] = "BuildBeforeAnalysis";
-ClangToolsSettings::ClangToolsSettings()
-{
- readSettings();
-}
+static const char oldDiagnosticConfigIdKey[] = "diagnosticConfigId";
-ClangToolsSettings *ClangToolsSettings::instance()
-{
- static ClangToolsSettings instance;
- return &instance;
-}
+namespace ClangTools {
+namespace Internal {
-int ClangToolsSettings::savedSimultaneousProcesses() const
+RunSettings::RunSettings()
+ : m_parallelJobs(qMax(0, QThread::idealThreadCount() / 2))
{
- return m_savedSimultaneousProcesses;
}
-int ClangToolsSettings::simultaneousProcesses() const
+void RunSettings::fromMap(const QVariantMap &map, const QString &prefix)
{
- return m_simultaneousProcesses;
+ m_diagnosticConfigId = Core::Id::fromSetting(map.value(prefix + diagnosticConfigIdKey));
+ m_parallelJobs = map.value(prefix + parallelJobsKey).toInt();
+ m_buildBeforeAnalysis = map.value(prefix + buildBeforeAnalysisKey).toBool();
}
-void ClangToolsSettings::setSimultaneousProcesses(int processes)
+void RunSettings::toMap(QVariantMap &map, const QString &prefix) const
{
- m_simultaneousProcesses = processes;
+ map.insert(prefix + diagnosticConfigIdKey, m_diagnosticConfigId.toSetting());
+ map.insert(prefix + parallelJobsKey, m_parallelJobs);
+ map.insert(prefix + buildBeforeAnalysisKey, m_buildBeforeAnalysis);
}
-bool ClangToolsSettings::savedBuildBeforeAnalysis() const
+ClangToolsSettings::ClangToolsSettings()
{
- return m_savedBuildBeforeAnalysis;
+ readSettings();
}
-bool ClangToolsSettings::buildBeforeAnalysis() const
+ClangToolsSettings *ClangToolsSettings::instance()
{
- return m_buildBeforeAnalysis;
+ static ClangToolsSettings instance;
+ return &instance;
}
-void ClangToolsSettings::setBuildBeforeAnalysis(bool build)
+static QVariantMap convertToMapFromVersionBefore410(QSettings *s)
{
- m_buildBeforeAnalysis = build;
-}
+ const char oldParallelJobsKey[] = "simultaneousProcesses";
+ const char oldBuildBeforeAnalysisKey[] = "buildBeforeAnalysis";
-Core::Id ClangToolsSettings::savedDiagnosticConfigId() const
-{
- return m_savedDiagnosticConfigId;
-}
+ QVariantMap map;
+ map.insert(diagnosticConfigIdKey, s->value(oldDiagnosticConfigIdKey));
+ map.insert(parallelJobsKey, s->value(oldParallelJobsKey));
+ map.insert(buildBeforeAnalysisKey, s->value(oldBuildBeforeAnalysisKey));
-Core::Id ClangToolsSettings::diagnosticConfigId() const
-{
- return m_diagnosticConfigId;
-}
+ s->remove(oldDiagnosticConfigIdKey);
+ s->remove(oldParallelJobsKey);
+ s->remove(oldBuildBeforeAnalysisKey);
-void ClangToolsSettings::setDiagnosticConfigId(Core::Id id)
-{
- m_diagnosticConfigId = id;
+ return map;
}
-void ClangToolsSettings::updateSavedBuildBeforeAnalysiIfRequired()
-{
- if (m_savedBuildBeforeAnalysis == m_buildBeforeAnalysis)
- return;
- m_savedBuildBeforeAnalysis = m_buildBeforeAnalysis;
- emit buildBeforeAnalysisChanged(m_savedBuildBeforeAnalysis);
-}
-
-QString ClangToolsSettings::savedClazyStandaloneExecutable() const
+void ClangToolsSettings::readSettings()
{
- return m_savedClazyStandaloneExecutable;
-}
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(Constants::SETTINGS_ID);
+ m_clangTidyExecutable = s->value(clangTidyExecutableKey).toString();
+ m_clazyStandaloneExecutable = s->value(clazyStandaloneExecutableKey).toString();
-QString ClangToolsSettings::savedClangTidyExecutable() const
-{
- return m_savedClangTidyExecutable;
-}
+ bool write = false;
-QString ClangToolsSettings::clazyStandaloneExecutable() const
-{
- return m_clazyStandaloneExecutable;
-}
+ 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()));
+ }
-void ClangToolsSettings::setClazyStandaloneExecutable(const QString &path)
-{
- m_clazyStandaloneExecutable = path;
-}
+ // Run settings
+ m_runSettings.fromMap(map);
-QString ClangToolsSettings::clangTidyExecutable() const
-{
- return m_clangTidyExecutable;
-}
+ s->endGroup();
-void ClangToolsSettings::setClangTidyExecutable(const QString &path)
-{
- m_clangTidyExecutable = path;
+ if (write)
+ writeSettings();
}
-void ClangToolsSettings::readSettings()
+void ClangToolsSettings::writeSettings()
{
- QSettings *settings = Core::ICore::settings();
- settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
-
- const int defaultSimultaneousProcesses = qMax(0, QThread::idealThreadCount() / 2);
- m_savedSimultaneousProcesses = m_simultaneousProcesses
- = settings->value(QString(simultaneousProcessesKey),
- defaultSimultaneousProcesses).toInt();
-
- m_buildBeforeAnalysis = settings->value(QString(buildBeforeAnalysisKey), true).toBool();
+ QSettings *s = Core::ICore::settings();
+ s->beginGroup(Constants::SETTINGS_ID);
- m_savedClangTidyExecutable = m_clangTidyExecutable
- = settings->value(QLatin1String(clangTidyExecutableKey)).toString();
- m_savedClazyStandaloneExecutable = m_clazyStandaloneExecutable
- = settings->value(QLatin1String(clazyStandaloneExecutableKey)).toString();
+ s->setValue(clangTidyExecutableKey, m_clangTidyExecutable);
+ s->setValue(clazyStandaloneExecutableKey, m_clazyStandaloneExecutable);
- m_diagnosticConfigId = Core::Id::fromSetting(settings->value(QString(diagnosticConfigIdKey)));
- if (!m_diagnosticConfigId.isValid())
- m_diagnosticConfigId = "Builtin.TidyAndClazy";
+ QVariantMap map;
+ m_runSettings.toMap(map);
+ for (QVariantMap::ConstIterator it = map.constBegin(); it != map.constEnd(); ++it)
+ s->setValue(it.key(), it.value());
- m_savedDiagnosticConfigId = m_diagnosticConfigId;
-
- updateSavedBuildBeforeAnalysiIfRequired();
-
- settings->endGroup();
-}
-
-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());
-
- m_savedSimultaneousProcesses = m_simultaneousProcesses;
- m_savedDiagnosticConfigId = m_diagnosticConfigId;
- m_savedClangTidyExecutable = m_clangTidyExecutable;
- m_savedClazyStandaloneExecutable = m_clazyStandaloneExecutable;
- updateSavedBuildBeforeAnalysiIfRequired();
-
- settings->endGroup();
+ s->endGroup();
}
} // namespace Internal
diff --git a/src/plugins/clangtools/clangtoolssettings.h b/src/plugins/clangtools/clangtoolssettings.h
index 402845d20f..893dbd23f9 100644
--- a/src/plugins/clangtools/clangtoolssettings.h
+++ b/src/plugins/clangtools/clangtoolssettings.h
@@ -27,61 +27,61 @@
#include <coreplugin/id.h>
-#include <QObject>
#include <QString>
namespace ClangTools {
namespace Internal {
-// TODO: Remove need for "saved* members
-class ClangToolsSettings : public QObject
+const char diagnosticConfigIdKey[] = "DiagnosticConfigId";
+
+class RunSettings
{
- Q_OBJECT
public:
- static ClangToolsSettings *instance();
+ RunSettings();
- void writeSettings();
+ void fromMap(const QVariantMap &map, const QString &prefix = QString());
+ void toMap(QVariantMap &map, const QString &prefix = QString()) const;
- int savedSimultaneousProcesses() const;
- bool savedBuildBeforeAnalysis() const;
- Core::Id savedDiagnosticConfigId() const;
- QString savedClangTidyExecutable() const;
- QString savedClazyStandaloneExecutable() const;
+ Core::Id diagnosticConfigId() const { return m_diagnosticConfigId; }
+ void setDiagnosticConfigId(const Core::Id &id) { m_diagnosticConfigId = id; }
- int simultaneousProcesses() const;
- void setSimultaneousProcesses(int processes);
+ bool buildBeforeAnalysis() const { return m_buildBeforeAnalysis; }
+ void setBuildBeforeAnalysis(bool yesno) { m_buildBeforeAnalysis = yesno; }
- bool buildBeforeAnalysis() const;
- void setBuildBeforeAnalysis(bool build);
+ 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;
+};
- Core::Id diagnosticConfigId() const;
- void setDiagnosticConfigId(Core::Id id);
+class ClangToolsSettings
+{
+public:
+ static ClangToolsSettings *instance();
+ void writeSettings();
- QString clangTidyExecutable() const;
- void setClangTidyExecutable(const QString &path);
+ QString clangTidyExecutable() const { return m_clangTidyExecutable; }
+ void setClangTidyExecutable(const QString &path) { m_clangTidyExecutable = path; }
- QString clazyStandaloneExecutable() const;
- void setClazyStandaloneExecutable(const QString &path);
+ QString clazyStandaloneExecutable() const { return m_clazyStandaloneExecutable; }
+ void setClazyStandaloneExecutable(const QString &path) { m_clazyStandaloneExecutable = 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 b8546c58bd..79b7bfcc94 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<CppTools::CppCodeModelSettings> 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 0000000000..1a26d2e7d0
--- /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 <QThread>
+
+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<int>::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 0000000000..c49bc88f75
--- /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 <QWidget>
+
+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 0000000000..e7ad362c84
--- /dev/null
+++ b/src/plugins/clangtools/runsettingswidget.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClangTools::Internal::RunSettingsWidget</class>
+ <widget class="QWidget" name="ClangTools::Internal::RunSettingsWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>383</width>
+ <height>125</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Run Options</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="CppTools::ClangDiagnosticConfigsSelectionWidget" name="diagnosticWidget" native="true"/>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="buildBeforeAnalysis">
+ <property name="text">
+ <string>Build the project before analysis</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="processesLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Parallel jobs:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="parallelJobsSpinBox">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>32</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>CppTools::ClangDiagnosticConfigsSelectionWidget</class>
+ <extends>QWidget</extends>
+ <header>cpptools/clangdiagnosticconfigsselectionwidget.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/plugins/clangtools/settingswidget.cpp b/src/plugins/clangtools/settingswidget.cpp
index de5976a04f..110135a779 100644
--- a/src/plugins/clangtools/settingswidget.cpp
+++ b/src/plugins/clangtools/settingswidget.cpp
@@ -30,17 +30,6 @@
#include "clangtoolsconstants.h"
#include "clangtoolsutils.h"
-#include <coreplugin/icore.h>
-
-#include <cpptools/clangdiagnosticconfigswidget.h>
-#include <cpptools/cppcodemodelsettings.h>
-#include <cpptools/cpptoolsreuse.h>
-
-#include <QDir>
-#include <QThread>
-
-#include <memory>
-
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<void(const QString &path)> 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<int>::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);
- });
- CppTools::ClangDiagnosticConfigsSelectionWidget *diagnosticWidget = m_ui->diagnosticWidget;
- diagnosticWidget->refresh(settings->savedDiagnosticConfigId());
+ m_ui->runSettingsWidget->fromSettings(m_settings->runSettings());
+}
- connect(diagnosticWidget,
- &CppTools::ClangDiagnosticConfigsSelectionWidget::currentConfigChanged,
- this, [this](const Core::Id &currentConfigId) {
- m_settings->setDiagnosticConfigId(currentConfigId);
- });
+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(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 6eeaeb5d98..2002f32eec 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<Ui::SettingsWidget> m_ui;
ClangToolsSettings *m_settings;
diff --git a/src/plugins/clangtools/settingswidget.ui b/src/plugins/clangtools/settingswidget.ui
index c73148d0da..6ef3d09297 100644
--- a/src/plugins/clangtools/settingswidget.ui
+++ b/src/plugins/clangtools/settingswidget.ui
@@ -44,57 +44,7 @@
</widget>
</item>
<item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>Run Options</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="CppTools::ClangDiagnosticConfigsSelectionWidget" name="diagnosticWidget" native="true"/>
- </item>
- <item>
- <widget class="QCheckBox" name="buildBeforeAnalysis">
- <property name="text">
- <string>Build the project before analysis</string>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="processesLayout">
- <item>
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Simultaneous processes:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QSpinBox" name="simultaneousProccessesSpinBox">
- <property name="minimum">
- <number>1</number>
- </property>
- <property name="maximum">
- <number>32</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
+ <widget class="ClangTools::Internal::RunSettingsWidget" name="runSettingsWidget" native="true"/>
</item>
<item>
<spacer name="verticalSpacer">
@@ -113,14 +63,15 @@
</widget>
<customwidgets>
<customwidget>
- <class>CppTools::ClangDiagnosticConfigsSelectionWidget</class>
+ <class>Utils::PathChooser</class>
<extends>QWidget</extends>
- <header>cpptools/clangdiagnosticconfigsselectionwidget.h</header>
+ <header location="global">utils/pathchooser.h</header>
+ <container>1</container>
</customwidget>
<customwidget>
- <class>Utils::PathChooser</class>
+ <class>ClangTools::Internal::RunSettingsWidget</class>
<extends>QWidget</extends>
- <header location="global">utils/pathchooser.h</header>
+ <header>clangtools/runsettingswidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
diff --git a/src/plugins/coreplugin/windowsupport.cpp b/src/plugins/coreplugin/windowsupport.cpp
index 17bab61bcc..26117ba12f 100644
--- a/src/plugins/coreplugin/windowsupport.cpp
+++ b/src/plugins/coreplugin/windowsupport.cpp
@@ -40,6 +40,7 @@
#include <QEvent>
#include <QMenu>
#include <QWidget>
+#include <QWindowStateChangeEvent>
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<QWindowStateChangeEvent *>(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 5531306fe0..1e640f6edb 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 4120aaee21..dbb70ca07a 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 <QIntValidator>
+
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 e7ed226b67..799e3fadc5 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 2fa1241e4a..1fe2468a6b 100644
--- a/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
+++ b/src/plugins/qmldesigner/components/timelineeditor/setframevaluedialog.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>184</width>
- <height>79</height>
+ <height>93</height>
</rect>
</property>
<property name="windowTitle">
@@ -15,16 +15,13 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="labelFrame">
<property name="text">
- <string>Value</string>
+ <string>Frame</string>
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="lineEdit"/>
- </item>
- <item row="1" column="0" colspan="2">
+ <item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -34,6 +31,19 @@
</property>
</widget>
</item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="lineEditFrame"/>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="lineEditValue"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="labelValue">
+ <property name="text">
+ <string>Value</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<resources/>
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h b/src/plugins/qmldesigner/components/timelineeditor/timelineconstants.h
index c2a8137352..622dc366ed 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 97ebb7e84d..a5f6110812 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<TimelineKeyframeItem *> 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 b8f93595c4..d03a6a5824 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<QGraphicsItem *> itemsAt(const QPointF &pos);
diff --git a/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp b/src/plugins/qmldesigner/components/timelineeditor/timelinemovableabstractitem.cpp
index 4db4567fd6..1d700cf063 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 0830facfbf..cf71397225 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 0e68a63ff4..71c76e5f67 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 55b9a39417..20b9537af9 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 <QCoreApplication>
#include <QPointF>
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 beeca23183..920a8b35ca 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<ModelNode>
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<qreal, qreal> &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();
+
+ qreal newFrame = qBound(timelineRange.first, dialog->frame(), timelineRange.second);
+ if (newFrame != frame)
+ frameNode.variantProperty("frame").setValue(newFrame);
+
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);
+ 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<qreal, qreal> 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<qreal, qreal> 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<qreal, qreal> 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 2b8c00c59b..4544b40302 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 987ac4935a..c9ab304497 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 51c5a7d088..d84a461999 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 522607f615..303c761f3c 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);
}
}
}