Merge remote-tracking branch 'origin/6.0'

Change-Id: If6c5ca7bc4b404959ca3250777d6fb818297798d
This commit is contained in:
Eike Ziller
2021-10-04 09:38:28 +02:00
85 changed files with 1708 additions and 1162 deletions

View File

@@ -34,7 +34,13 @@ if (WIN32 AND TARGET clangTooling)
llvm::cl::OptionCategory CheckToolCategory("check tool options");
int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, CheckToolCategory);
class Parser : public CommonOptionsParser {
public:
Parser(int &argc, const char **argv, llvm::cl::OptionCategory &Category) :
CommonOptionsParser(argc, argv, Category) {}
};
Parser OptionsParser(argc, argv, CheckToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
return 0;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -44,38 +44,75 @@
\uicontrol {Qt Quick 3D} module to your project as instructed in
\l {Adding and Removing Modules}.
\note If you select \uicontrol {Qt 5} as the \uicontrol {Target Qt Version}
when \l {Creating Projects}{creating your project}, the available light
components and their properties will be slightly different. The properties
may also be situated differently in the \uicontrol Properties view.
By default, all imported scenes are created with one directional light.
You can use the following components to add lights:
\list
\table
\header
\li Icon
\li Name
\li Qt 5 Only
\li More Information
\row
\li \inlineimage spot.png
\li Directional Light
\li
\li \l{DirectionalLight}{Light Directional}
\row
\li \inlineimage point.png
\li Point Light
\li
\li \l{PointLight}{Light Point}
\row
\li \inlineimage spot.png
\li Spot Light
\li
\li \l{SpotLight}{Light Spot}
\row
\li \inlineimage area.png
\li Area Light
\li \inlineimage ok.png
\li \l{AreaLight}{Light Area}
\endlist
\endtable
\note Each additional light negatively effects the rendering performance
of your scene. Keep scenes as simple as possible and use lights sparingly.
Use a \l{SceneEnvironment}{Scene Environment} component to apply image-based
lighting that can produce soft and subtle lighting.
You can edit light properties in the \uicontrol Properties view. The
\uicontrol Scope property specifies which node, with it's children,
is illuminated by a light.
To edit light properties, select a light component in \uicontrol Navigator,
or \uicontrol {3D Editor}, and then adjust its properties in the
\uicontrol Properties view or by dragging the yellow light gizmo handles in
\uicontrol {3D Editor}.
Set the \uicontrol {Color} property to specify the color applied to models
To specify an overall multiplier for a light component's effects, adjust the
\uicontrol Brightness property. The \uicontrol Scope property specifies which
component, with its children, is illuminated by the light. Set the
\l{Picking Colors}{Color} property to specify the color applied to models
illuminated by a light. Set the \uicontrol {Ambient color} property to
specify the ambient color applied to materials before being illuminated by
the light.
You can animate light properties in the \uicontrol Timeline view.
You can animate light properties in the \l Timeline view.
\section1 Directional Light
A directional light emits light in one direction from a unidentifiable
A directional light emits light in one direction from an unidentifiable
source located infinitely far away. This is similar to sunlight.
\image studio-3d-directional-light.png "Models lit by a dirctional light"
Use the \uicontrol Brightness handle of the light gizmo (1) to adjust the
\uicontrol Brightness property of any of the light components.
\image studio-3d-directional-light.png "Models lit by a directional light."
If the \uicontrol {Casts shadow} property is enabled, shadows are positioned
parallel to the light direction. A directional light has infinite range and
@@ -96,20 +133,17 @@
\section1 Point Light
A point light can be described as a sphere, emitting light with equal
A point light can be described as a sphere that emits light with equal
strength in all directions from the center of the light. This is similar
to the way a light bulb emits light.
\image studio-3d-point-light.png "Models lit by a point light"
\image studio-3d-point-light.png "Models lit by a point light."
Lighting is applied outwards from the center of a point light, becoming
increasingly dim away from the center. Moving a point light changes the
position from where the light is emitted. Rotating or scaling a point
light does not have any effect.
To specify an overall multiplier for a point light's effects, set the
\uicontrol Brightness property.
To control the fade-off and range of a point light, set the
\uicontrol {Constant fade}, \uicontrol {Linear fade}, and
\uicontrol {Quadratic fade} properties. Constant fade is the constant
@@ -125,7 +159,8 @@
dims on surfaces that are far away from the light. The value 1.0 means that
the point light fade exactly follows the inverse square law. For example,
when the distance to a component doubles, the light intensity decreases to
one fourth.
one fourth. Adjust the \uicontrol {Quadratic fade} in the Properties view,
or by using the light gizmo handle (2).
Aside from fade, a point light has the same properties as a directional
light.
@@ -136,7 +171,13 @@
The light intensity diminishes when approaching the value of the
\uicontrol {Cone angle} property. The angle at which the light
intensity starts to diminish is defined by the
\uicontrol {Inner cone angle} property. Both angles are defined in degrees.
\uicontrol {Inner cone angle} property. Both angles are defined in degrees
in the \uicontrol Properties view. Use the Properties view or the light gizmo
handles to adjust the \uicontrol {Cone angle} (3),
\uicontrol {Inner cone angle} (4), and \uicontrol {Quadratic fade} (5)
properties.
\image studio-3d-spot-light.png "A model lit by a spot light."
Inside the inner cone angle, the spot light behaves similarly to the point
light. There the light intensity diminishes according to inverse-square-law.
@@ -144,15 +185,17 @@
\uicontrol {Constant fade}, \uicontrol {Linear fade}, and
\uicontrol {Quadratic fade} properties.
\image studio-3d-spot-light.png
\section1 Area Light
\note The \uicontrol {Area Light} component is only available in Qt 5.
An area light is similar to the directional light. However, instead of
emitting an equally bright light across the whole scene, the area light
emits directional light from a rectangle shaped component. You can set the
\uicontrol Width and \uicontrol Height properties to determine the size
of the area light.
emits directional light from a rectangle shaped component. Use the light
gizmo or the \uicontrol Properties view to set the \uicontrol Width (6)
and \uicontrol Height (7) properties to determine the size of the area light.
\image studio-3d-area-light.png "A model lit by two area lights."
Aside from the size, an area light has the same properties as a directional
light.
@@ -160,8 +203,6 @@
The image below shows an example on how to light a component with different
colors using two different area lights.
\image studio-3d-area-light.png
You can rotate, scale, and move area lights.
\section1 Shadows

View File

@@ -41,7 +41,7 @@ Item {
anchors.topMargin: 1
anchors.fill: parent
color: StudioTheme.Values.themePanelBackground
color: mouseRegion.containsMouse ? StudioTheme.Values.themeControlBackgroundHover : StudioTheme.Values.themePanelBackground
Image {
id: itemIcon // to be set by model

View File

@@ -73,7 +73,7 @@ itemLibraryModel [
]
*/
ScrollView {
Item {
id: itemsView
property string importToRemove: ""
@@ -81,6 +81,11 @@ ScrollView {
property var currentItem: null
property var currentCategory: null
property var currentImport: null
property bool isHorizontalView: false
// horizontal component lib variables
property var selectedCategory: null
property var selectedCategoryImport: null
// called from C++ to close context menu on focus out
function closeContextMenu()
@@ -91,15 +96,21 @@ ScrollView {
function showImportCategories()
{
currentImport.importCatVisibleState = true
if (itemLibraryModel.isAllCategoriesHidden()) {
itemsView.currentImport.importCatVisibleState = true
if (!itemLibraryModel.getIsAnyCategoryHidden())
itemLibraryModel.isAnyCategoryHidden = false
itemsView.selectedCategory = itemLibraryModel.selectImportFirstVisibleCategory()
}
itemsView.currentImport.importCatVisibleState = true
if (!itemLibraryModel.getIsAnyCategoryHidden())
itemLibraryModel.isAnyCategoryHidden = false
}
onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - height, 0)
if (contentY > maxPosition)
contentY = maxPosition
onWidthChanged: {
itemsView.isHorizontalView = itemsView.width > widthLimit
}
Item {
@@ -112,66 +123,68 @@ ScrollView {
property int cellVerticalMargin: 4
// the following depend on the actual shape of the item delegate
property int cellWidth: textWidth + 2 * cellHorizontalMargin
property int cellHeight: itemLibraryIconHeight + textHeight +
2 * cellVerticalMargin + cellVerticalSpacing
property int cellWidth: styleConstants.textWidth + 2 * styleConstants.cellHorizontalMargin
property int cellHeight: itemLibraryIconHeight + styleConstants.textHeight +
2 * styleConstants.cellVerticalMargin + styleConstants.cellVerticalSpacing
StudioControls.Menu {
id: moduleContextMenu
StudioControls.MenuItem {
text: qsTr("Remove Module")
visible: currentCategory === null
visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0
enabled: importToRemove !== ""
enabled: itemsView.importToRemove !== ""
onTriggered: {
showImportCategories()
rootView.removeImport(importToRemove)
rootView.removeImport(itemsView.importToRemove)
}
}
StudioControls.MenuSeparator {
visible: currentCategory === null
visible: itemsView.currentCategory === null
height: StudioTheme.Values.border
}
StudioControls.MenuItem {
text: qsTr("Expand All")
visible: currentCategory === null
visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.expandAll()
}
StudioControls.MenuItem {
text: qsTr("Collapse All")
visible: currentCategory === null
visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.collapseAll()
}
StudioControls.MenuSeparator {
visible: currentCategory === null
visible: itemsView.currentCategory === null
height: StudioTheme.Values.border
}
StudioControls.MenuItem {
text: qsTr("Hide Category")
visible: currentCategory
visible: itemsView.currentCategory
height: visible ? implicitHeight : 0
onTriggered: {
itemLibraryModel.isAnyCategoryHidden = true
currentCategory.categoryVisible = false
itemsView.currentCategory.categoryVisible = false
itemsView.currentCategory.categorySelected = false
itemsView.selectedCategory = itemLibraryModel.selectImportFirstVisibleCategory()
}
}
StudioControls.MenuSeparator {
visible: currentCategory
visible: itemsView.currentCategory
height: StudioTheme.Values.border
}
StudioControls.MenuItem {
text: qsTr("Show Module Hidden Categories")
enabled: currentImport && !currentImport.importCatVisibleState
enabled: itemsView.currentImport && !itemsView.currentImport.importCatVisibleState
onTriggered: showImportCategories()
}
@@ -179,6 +192,12 @@ ScrollView {
text: qsTr("Show All Hidden Categories")
enabled: itemLibraryModel.isAnyCategoryHidden
onTriggered: {
if (itemLibraryModel.isAllCategoriesHidden()) {
itemLibraryModel.showHiddenCategories()
itemsView.selectedCategory = itemLibraryModel.selectImportFirstVisibleCategory()
itemLibraryModel.isAnyCategoryHidden = false
}
itemLibraryModel.isAnyCategoryHidden = false
itemLibraryModel.showHiddenCategories()
}
@@ -192,20 +211,39 @@ ScrollView {
StudioControls.MenuItem {
id: importMenuItem
text: qsTr("Add Module: ") + importToAdd
enabled: importToAdd !== ""
onTriggered: rootView.addImportForItem(importToAdd)
text: qsTr("Add Module: ") + itemsView.importToAdd
enabled: itemsView.importToAdd !== ""
onTriggered: rootView.addImportForItem(itemsView.importToAdd)
}
}
}
Loader {
anchors.fill: parent
sourceComponent: itemsView.isHorizontalView ? horizontalView : verticalView
}
Component {
id: verticalView
ScrollView {
id: verticalScrollView
width: itemsView.width
height: itemsView.height
onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - verticalScrollView.height, 0)
if (contentY > maxPosition)
contentY = maxPosition
}
Column {
spacing: 2
Repeater {
model: itemLibraryModel // to be set in Qml context
delegate: Section {
width: itemsView.width -
(itemsView.verticalScrollBarVisible ? itemsView.verticalThickness : 0)
(verticalScrollView.verticalScrollBarVisible
? verticalScrollView.verticalThickness : 0)
caption: importName
visible: importVisible
sectionHeight: 30
@@ -218,15 +256,14 @@ ScrollView {
expanded: importExpanded
expandOnClick: false
useDefaulContextMenu: false
onToggleExpand: {
if (categoryModel.rowCount() > 0)
importExpanded = !importExpanded
}
onShowContextMenu: {
importToRemove = importRemovable ? importUrl : ""
currentImport = model
currentCategory = null
itemsView.importToRemove = importRemovable ? importUrl : ""
itemsView.currentImport = model
itemsView.currentCategory = null
if (!rootView.isSearchActive())
moduleContextMenu.popup()
}
@@ -238,22 +275,24 @@ ScrollView {
model: categoryModel
delegate: Section {
width: itemsView.width -
(itemsView.verticalScrollBarVisible ? itemsView.verticalThickness : 0)
(verticalScrollView.verticalScrollBarVisible
? verticalScrollView.verticalThickness : 0)
sectionBackgroundColor: "transparent"
showTopSeparator: index > 0
hideHeader: categoryModel.rowCount() <= 1
leftPadding: 0
rightPadding: 0
addTopPadding: categoryModel.rowCount() > 1
addBottomPadding: index != categoryModel.rowCount() - 1
addBottomPadding: index !== categoryModel.rowCount() - 1
caption: categoryName + " (" + itemModel.rowCount() + ")"
visible: categoryVisible
expanded: categoryExpanded
expandOnClick: false
onToggleExpand: categoryExpanded = !categoryExpanded
useDefaulContextMenu: false
onShowContextMenu: {
currentCategory = model
currentImport = parent.currentImportModel
itemsView.currentCategory = model
itemsView.currentImport = parent.currentImportModel
if (!rootView.isSearchActive())
moduleContextMenu.popup()
}
@@ -267,6 +306,7 @@ ScrollView {
leftPadding: 6
rightPadding: 6
columns: itemGrid.actualWidth / styleConstants.cellWidth
rowSpacing: 7
Repeater {
model: itemModel
@@ -278,7 +318,7 @@ ScrollView {
height: styleConstants.cellHeight
onShowContextMenu: {
if (!itemUsable) {
importToAdd = itemRequiredImport
itemsView.importToAdd = itemRequiredImport
itemContextMenu.popup()
}
}
@@ -292,3 +332,164 @@ ScrollView {
}
}
}
}
Component {
id: horizontalView
Row {
padding: 5
ScrollView {
id: horizontalScrollView
width: 270
height: itemsView.height
onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - horizontalScrollView.height, 0)
if (contentY > maxPosition)
contentY = maxPosition
}
Column {
width: parent.width
spacing: 2
Repeater {
model: itemLibraryModel // to be set in Qml context
delegate: Section {
width: 265 -
(horizontalScrollView.verticalScrollBarVisible
? horizontalScrollView.verticalThickness : 0)
caption: importName
visible: importVisible
sectionHeight: 30
sectionFontSize: 15
showArrow: categoryModel.rowCount() > 0
labelColor: importUnimported ? StudioTheme.Values.themeUnimportedModuleColor
: StudioTheme.Values.themeTextColor
leftPadding: 0
rightPadding: 0
expanded: importExpanded
expandOnClick: false
useDefaulContextMenu: false
onToggleExpand: {
if (categoryModel.rowCount() > 0)
importExpanded = !importExpanded
}
onShowContextMenu: {
itemsView.importToRemove = importRemovable ? importUrl : ""
itemsView.currentImport = model
itemsView.currentCategory = null
if (!rootView.isSearchActive())
moduleContextMenu.popup()
}
Column {
spacing: 2
property var currentImportModel: model // allows accessing the import model from inside the category section
Repeater {
model: categoryModel
delegate: Rectangle {
width: 265 -
(horizontalScrollView.verticalScrollBarVisible
? horizontalScrollView.verticalThickness : 0)
height: 25
visible: categoryVisible
border.width: StudioTheme.Values.border
border.color: StudioTheme.Values.themeControlOutline
color: categorySelected
? StudioTheme.Values.themeControlBackgroundHover
: categoryMouseArea.containsMouse ? Qt.darker(StudioTheme.Values.themeControlBackgroundHover, 1.5)
: StudioTheme.Values.themeControlBackground
Text {
anchors.fill: parent
text: categoryName
color: StudioTheme.Values.themeTextColor
font.pixelSize: 13
font.capitalization: Font.AllUppercase
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
MouseArea {
id: categoryMouseArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: (mouse) => {
itemLibraryModel.selectImportCategory(parent.parent.currentImportModel.importUrl, model.index)
itemsView.selectedCategory = model
itemsView.selectedCategoryImport = parent.parent.currentImportModel
if (mouse.button === Qt.RightButton && !rootView.isSearchActive() && categoryModel.rowCount() !== 1) {
itemsView.currentCategory = model
itemsView.currentImport = parent.parent.currentImportModel
moduleContextMenu.popup()
}
}
Component.onCompleted: {
if (categorySelected)
categorySelected = !categorySelected
itemsView.selectedCategory = itemLibraryModel.selectImportFirstVisibleCategory()
if (itemsView.selectedCategory === categorySelected)
itemsView.selectedCategoryImport = itemsView.selectedCategory.parent.currentImportModel
}
}
}
}
}
}
}
}
}
Rectangle { // separator between import/category column and item grid
id: separatingLine
height: itemsView.height - 10
width: 1
color: StudioTheme.Values.themeControlOutline
}
ScrollView {
id: itemScrollView
width: itemsView.width - 275
height: itemsView.height
onContentHeightChanged: {
var maxPosition = Math.max(contentHeight - itemScrollView.height, 0)
if (contentY > maxPosition)
contentY = maxPosition
}
Grid {
id: hItemGrid
property real actualWidth: itemsView.width - 294
property int flexibleWidth: (hItemGrid.actualWidth / hItemGrid.columns) - styleConstants.cellWidth
leftPadding: 9
rightPadding: 9
bottomPadding: 15
columns: hItemGrid.actualWidth / styleConstants.cellWidth
rowSpacing: 7
Repeater {
model: itemsView.selectedCategory ? itemsView.selectedCategory.itemModel : null
delegate: ItemDelegate {
visible: itemVisible
textColor: itemsView.selectedCategoryImport && itemsView.selectedCategoryImport.importUnimported
? StudioTheme.Values.themeUnimportedModuleColor : StudioTheme.Values.themeTextColor
width: styleConstants.cellWidth + hItemGrid.flexibleWidth
height: styleConstants.cellHeight
onShowContextMenu: {
if (!itemUsable) {
itemsView.importToAdd = itemRequiredImport
itemContextMenu.popup()
}
}
}
}
}
}
}
}
}

View File

@@ -336,6 +336,12 @@ public:
Utils::optional<QList<MarkupKind>> documentationFormat() const;
void setDocumentationFormat(const QList<MarkupKind> &documentationFormat);
void clearDocumentationFormat() { remove(documentationFormatKey); }
Utils::optional<bool> activeParameterSupport() const
{ return optionalValue<bool>(activeParameterSupportKey); }
void setActiveParameterSupport(bool activeParameterSupport)
{ insert(activeParameterSupportKey, activeParameterSupport); }
void clearActiveParameterSupport() { remove(activeParameterSupportKey); }
};
// The client supports the following `SignatureInformation` specific properties.

View File

@@ -29,6 +29,7 @@ namespace LanguageServerProtocol {
constexpr char actionsKey[] = "actions";
constexpr char activeParameterKey[] = "activeParameter";
constexpr char activeParameterSupportKey[] = "activeParameterSupport";
constexpr char activeSignatureKey[] = "activeSignature";
constexpr char addedKey[] = "added";
constexpr char additionalTextEditsKey[] = "additionalTextEdits";

View File

@@ -145,6 +145,10 @@ public:
void setParameters(const QList<ParameterInformation> &parameters)
{ insertArray(parametersKey, parameters); }
void clearParameters() { remove(parametersKey); }
Utils::optional<int> activeParameter() const { return optionalValue<int>(activeParameterKey); }
void setActiveParameter(int activeParameter) { insert(activeParameterKey, activeParameter); }
void clearActiveParameter() { remove(activeParameterKey); }
};
/**

View File

@@ -1181,7 +1181,7 @@ void StringAspect::setVolatileValue(const QVariant &val)
switch (d->m_displayStyle) {
case PathChooserDisplay:
if (d->m_pathChooserDisplay)
d->m_pathChooserDisplay->setPath(val.toString());
d->m_pathChooserDisplay->setFilePath(FilePath::fromVariant(val));
break;
case LineEditDisplay:
if (d->m_lineEditDisplay)

View File

@@ -647,8 +647,10 @@ void ProcessArgs::addArgs(QString *args, const QStringList &inArgs)
bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, ProcessArgs *outArgs,
const Environment *env, const FilePath *pwd)
{
const FilePath executable = cmdLine.executable();
FilePath executable = cmdLine.executable();
const QString arguments = cmdLine.arguments();
if (env && executable.isRelativePath())
executable = env->searchInPath(executable.toString());
ProcessArgs::SplitError err;
*outArgs = ProcessArgs::prepareArgs(arguments, &err, executable.osType(), env, pwd);
if (err == ProcessArgs::SplitOk) {

View File

@@ -616,7 +616,7 @@ bool FilePath::isWritableFile() const
return s_deviceHooks.isWritableFile(*this);
}
const QFileInfo fi{m_data};
return fi.exists() && fi.isWritable() && !fi.isDir();
return fi.isWritable() && !fi.isDir();
}
bool FilePath::ensureWritableDir() const
@@ -626,7 +626,7 @@ bool FilePath::ensureWritableDir() const
return s_deviceHooks.ensureWritableDir(*this);
}
const QFileInfo fi{m_data};
if (exists() && fi.isDir() && fi.isWritable())
if (fi.isDir() && fi.isWritable())
return true;
return QDir().mkpath(m_data);
}
@@ -652,7 +652,7 @@ bool FilePath::isExecutableFile() const
return s_deviceHooks.isExecutableFile(*this);
}
const QFileInfo fi{m_data};
return fi.exists() && fi.isExecutable() && !fi.isDir();
return fi.isExecutable() && !fi.isDir();
}
bool FilePath::isReadableFile() const
@@ -662,7 +662,7 @@ bool FilePath::isReadableFile() const
return s_deviceHooks.isReadableFile(*this);
}
const QFileInfo fi{m_data};
return fi.exists() && fi.isReadable() && !fi.isDir();
return fi.isReadable() && !fi.isDir();
}
bool FilePath::isReadableDir() const
@@ -672,7 +672,7 @@ bool FilePath::isReadableDir() const
return s_deviceHooks.isReadableDir(*this);
}
const QFileInfo fi{m_data};
return fi.exists() && fi.isReadable() && fi.isDir();
return fi.isReadable() && fi.isDir();
}
bool FilePath::isFile() const
@@ -682,7 +682,7 @@ bool FilePath::isFile() const
return s_deviceHooks.isFile(*this);
}
const QFileInfo fi{m_data};
return fi.exists() && fi.isFile();
return fi.isFile();
}
bool FilePath::isDir() const
@@ -692,7 +692,7 @@ bool FilePath::isDir() const
return s_deviceHooks.isDir(*this);
}
const QFileInfo fi{m_data};
return fi.exists() && fi.isDir();
return fi.isDir();
}
bool FilePath::createDir() const

View File

@@ -195,6 +195,11 @@ bool ProjectIntroPage::validate()
return false;
}
void ProjectIntroPage::fieldsUpdated()
{
slotChanged();
}
void ProjectIntroPage::slotChanged()
{
const bool newComplete = validate();
@@ -286,6 +291,8 @@ void ProjectIntroPage::displayStatusMessage(InfoLabel::InfoType t, const QString
{
d->m_ui.stateLabel->setType(t);
d->m_ui.stateLabel->setText(s);
emit statusMessageChanged(t, s);
}
void ProjectIntroPage::hideStatusLabel()

View File

@@ -66,8 +66,14 @@ public:
bool validateProjectName(const QString &name, QString *errorMessage);
// Calls slotChanged() - i.e. tell the page that some of its fields have been updated.
// This function is useful if you programmatically update the fields of the page (i.e. from
// your client code).
void fieldsUpdated();
signals:
void activated();
void statusMessageChanged(InfoLabel::InfoType type, const QString &message);
public slots:
void setFilePath(const FilePath &path);

View File

@@ -88,9 +88,9 @@ QTextCursor selectAt(QTextCursor textCursor, int line, int column, uint length)
if (column < 1)
column = 1;
const int anchorPosition = positionInText(textCursor.document(), line, column + length);
const int anchorPosition = positionInText(textCursor.document(), line, column);
textCursor.setPosition(anchorPosition);
textCursor.setPosition(anchorPosition - length, QTextCursor::KeepAnchor);
textCursor.setPosition(anchorPosition + int(length), QTextCursor::KeepAnchor);
return textCursor;
}

View File

@@ -23,12 +23,13 @@
**
****************************************************************************/
#include "androidqmlpreviewworker.h"
#include "androidavdmanager.h"
#include "androiddevice.h"
#include "androiddeviceinfo.h"
#include "androidglobal.h"
#include "androidmanager.h"
#include "androidqmlpreviewworker.h"
#include <coreplugin/icore.h>
@@ -44,10 +45,11 @@
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/runextensions.h>
#include <QDateTime>
#include <QDeadlineTimer>
#include <QThread>
#include <QTemporaryDir>
#include <QImageReader>
#include <QtConcurrent>
namespace Android {
namespace Internal {
@@ -80,173 +82,143 @@ ApkInfo::ApkInfo() :
Q_GLOBAL_STATIC(ApkInfo, apkInfo)
const char packageSuffix[] = ".qmlrc";
static const char packageSuffix[] = ".qmlrc";
static inline bool isMainThread()
FilePath AndroidQmlPreviewWorker::designViewerApkPath(const QString &abi) const
{
return QCoreApplication::instance()->thread() == QThread::currentThread();
}
static FilePath viewerApkPath(const QString &avdAbi)
{
if (avdAbi.isEmpty())
if (abi.isEmpty())
return {};
if (apkInfo()->abis.contains(avdAbi))
return Core::ICore::resourcePath(QString("android/qtdesignviewer/designviewer_%1.apk").
arg(avdAbi));
if (apkInfo()->abis.contains(abi)) {
return Core::ICore::resourcePath(QString("android/qtdesignviewer/designviewer_%1.apk")
.arg(abi));
}
return {};
}
static SdkToolResult runAdbCommandAsyncAndWait(const QString &dev, const QStringList &arguments)
SdkToolResult AndroidQmlPreviewWorker::runAdbCommand(const QStringList &arguments) const
{
QStringList args;
if (!dev.isEmpty())
args << AndroidDeviceInfo::adbSelector(dev);
args << arguments;
QFuture<SdkToolResult> asyncResult = QtConcurrent::run([args] {
return AndroidManager::runAdbCommand(args);});
while (asyncResult.isRunning()) {
QCoreApplication::instance()->processEvents(QEventLoop::AllEvents, 100);
}
return asyncResult.result();
}
static SdkToolResult runAdbCommand(const QString &dev, const QStringList &arguments)
{
if (isMainThread())
return runAdbCommandAsyncAndWait(dev, arguments);
QStringList args;
if (!dev.isEmpty())
args << AndroidDeviceInfo::adbSelector(dev);
if (!m_serialNumber.isEmpty())
args << AndroidDeviceInfo::adbSelector(m_serialNumber);
args << arguments;
return AndroidManager::runAdbCommand(args);
}
static SdkToolResult runAdbShellCommand(const QString &dev, const QStringList &arguments)
SdkToolResult AndroidQmlPreviewWorker::runAdbShellCommand(const QStringList &arguments) const
{
const QStringList shellCmd{"shell"};
return runAdbCommand(dev, shellCmd + arguments);
return runAdbCommand(QStringList() << "shell" << arguments);
}
static QString startAvd(const AndroidAvdManager &avd, const QString &name)
{
QFuture<QString> asyncRes = QtConcurrent::run([avd, name] {
return avd.startAvd(name);
});
while (asyncRes.isRunning())
QCoreApplication::instance()->processEvents(QEventLoop::AllEvents, 100);
return asyncRes.result();
}
static int pidofPreview(const QString &dev)
int AndroidQmlPreviewWorker::pidofPreview() const
{
const QStringList command{"pidof", apkInfo()->appId};
const SdkToolResult res = runAdbShellCommand(dev, command);
const SdkToolResult res = runAdbShellCommand(command);
return res.success() ? res.stdOut().toInt() : -1;
}
static bool isPreviewRunning(const QString &dev, int lastKnownPid = -1)
bool AndroidQmlPreviewWorker::isPreviewRunning(int lastKnownPid) const
{
const int pid = pidofPreview(dev);
const int pid = pidofPreview();
return (lastKnownPid > 1) ? lastKnownPid == pid : pid > 1;
}
AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(ProjectExplorer::RunControl *runControl)
: ProjectExplorer::RunWorker(runControl)
, m_rc(runControl)
, m_config(AndroidConfigurations::currentConfig())
void AndroidQmlPreviewWorker::startPidWatcher()
{
}
QStringList filterAppLog(const QStringList& oldList, const QStringList& newList)
{
QStringList list = Utils::filtered(newList,
[](const auto & arg){return arg.contains(apkInfo()->name);});
for (const auto &oldEntry : oldList) {
list.removeAll(oldEntry);
}
return list;
}
void AndroidQmlPreviewWorker::start()
{
UploadInfo transfer;
const bool res = ensureAvdIsRunning()
&& checkAndInstallPreviewApp()
&& prepareUpload(transfer)
&& uploadFiles(transfer)
&& runPreviewApp(transfer);
if (!res) {
reportFailure();
return;
}
reportStarted();
//Thread to monitor preview life
QtConcurrent::run([this]() {
QElapsedTimer timer;
timer.start();
while (runControl() && runControl()->isRunning()) {
m_pidFutureWatcher.setFuture(Utils::runAsync([this]() {
// wait for started
const int sleepTimeMs = 2000;
QDeadlineTimer deadline(20000);
while (!m_pidFutureWatcher.isCanceled() && !deadline.hasExpired()) {
if (m_viewerPid == -1) {
m_viewerPid = pidofPreview(m_devInfo.serialNumber);
if (m_viewerPid > 0)
QMetaObject::invokeMethod(this, &AndroidQmlPreviewWorker::startLogcat);
} else if (timer.elapsed() > 2000) {
//Get the application output
if (!isPreviewRunning(m_devInfo.serialNumber, m_viewerPid))
QMetaObject::invokeMethod(this, &AndroidQmlPreviewWorker::stop);
m_viewerPid = pidofPreview();
if (m_viewerPid > 0) {
emit previewPidChanged();
break;
}
}
QThread::msleep(sleepTimeMs);
}
timer.restart();
while (!m_pidFutureWatcher.isCanceled()) {
if (!isPreviewRunning(m_viewerPid)) {
stop();
break;
}
QThread::msleep(100);
QThread::msleep(sleepTimeMs);
}
});
}));
}
void AndroidQmlPreviewWorker::startLogcat()
{
QtConcurrent::run([this]() {
QElapsedTimer timer;
timer.start();
int initialPid = m_viewerPid; // to check if our initial process is still alive
QStringList logLines;
auto appendLogLinesCall = [&logLines, this](){ appendLogLines(logLines); };
auto runCondition = [this, initialPid](){ return (runControl() && runControl()->isRunning())
&& initialPid == m_viewerPid;};
QString timeFilter;
while (runCondition()) {
if (timer.elapsed() > 2000) {
//Get the application output
QStringList logcatCmd = {"logcat", QString("--pid=%1").arg(initialPid), "-t"};
if (!timeFilter.isEmpty())
logcatCmd.append(QString("%1").arg(timeFilter));
QString args = QString("logcat --pid=%1").arg(m_viewerPid);
if (!m_logcatStartTimeStamp.isEmpty())
args += QString(" -T '%1'").arg(m_logcatStartTimeStamp);
Utils::CommandLine cmd(AndroidConfigurations::currentConfig().adbToolPath());
cmd.setArguments(args);
m_logcatProcess.setCommand(cmd);
m_logcatProcess.setUseCtrlCStub(true);
m_logcatProcess.start();
}
void AndroidQmlPreviewWorker::filterLogcatAndAppendMessage(const QString &stdOut)
{
for (const QString &line : stdOut.split('\n')) {
QStringList splittedLine = line.split(QLatin1String("%1: ").arg(apkInfo()->name));
if (splittedLine.count() == 1)
continue;
const QString outLine = splittedLine.last();
const QString firstPart = splittedLine.first();
if (firstPart.contains(" I ") || firstPart.contains(" D "))
appendMessage(outLine, NormalMessageFormat);
else
logcatCmd.append(QString("1000")); //show last 1000 lines (but for the 1st time)
appendMessage(outLine, ErrorMessageFormat);
}
}
const SdkToolResult logcatResult = runAdbCommand(m_devInfo.serialNumber, logcatCmd);
if (runCondition()) {
const QStringList output = logcatResult.stdOut().split('\n');
const QStringList filtered = filterAppLog(logLines, output);
AndroidQmlPreviewWorker::AndroidQmlPreviewWorker(ProjectExplorer::RunControl *runControl)
: ProjectExplorer::RunWorker(runControl),
m_rc(runControl),
m_androidConfig(AndroidConfigurations::currentConfig())
{
connect(this, &RunWorker::started, this, &AndroidQmlPreviewWorker::startPidWatcher);
connect(this, &RunWorker::stopped, &m_pidFutureWatcher, &QFutureWatcher<void>::cancel);
connect(this, &AndroidQmlPreviewWorker::previewPidChanged,
this, &AndroidQmlPreviewWorker::startLogcat);
if (!filtered.isEmpty()){
const QString lastLine = filtered.last();
timeFilter = lastLine.left(lastLine.indexOf(" ", lastLine.indexOf(" ") + 1));
QMetaObject::invokeMethod(this, appendLogLinesCall);
logLines = filtered;
}
}
timer.restart();
}
QThread::msleep(100);
}
connect(this, &RunWorker::stopped, &m_logcatProcess, &Utils::QtcProcess::stopProcess);
m_logcatProcess.setStdOutCallback([this](const QString &stdOut) {
filterLogcatAndAppendMessage(stdOut);
});
}
AndroidQmlPreviewWorker::~AndroidQmlPreviewWorker()
{
m_pidFutureWatcher.cancel();
m_pidFutureWatcher.waitForFinished();
}
void AndroidQmlPreviewWorker::start()
{
const SdkToolResult dateResult = runAdbCommand({"shell", "date", "+%s"});
if (dateResult.success()) {
m_logcatStartTimeStamp = QDateTime::fromSecsSinceEpoch(dateResult.stdOut().toInt())
.toString("MM-dd hh:mm:ss.mmm");
}
const bool previewStarted = ensureAvdIsRunning()
&& checkAndInstallPreviewApp()
&& uploadPreviewArtefacts()
&& preparePreviewArtefacts()
&& startPreviewApp();
previewStarted ? reportStarted() : reportStopped();
}
void AndroidQmlPreviewWorker::stop()
{
if (!isPreviewRunning(m_devInfo.serialNumber, m_viewerPid) || stopPreviewApp())
if (!isPreviewRunning(m_viewerPid) || stopPreviewApp())
appendMessage(tr("%1 has been stopped.").arg(apkInfo()->name), NormalMessageFormat);
m_viewerPid = -1;
reportStopped();
@@ -254,28 +226,35 @@ void AndroidQmlPreviewWorker::stop()
bool AndroidQmlPreviewWorker::ensureAvdIsRunning()
{
AndroidAvdManager avdMan(m_config);
AndroidAvdManager avdMananager(m_androidConfig);
QString devSN = AndroidManager::deviceSerialNumber(m_rc->target());
if (devSN.isEmpty())
devSN = m_devInfo.serialNumber;
devSN = m_serialNumber;
if (!avdMan.isAvdBooted(devSN)) {
m_devInfo = {};
if (!avdMananager.isAvdBooted(devSN)) {
using namespace ProjectExplorer;
const IDevice *dev = DeviceKitAspect::device(m_rc->target()->kit()).data();
if (!dev) {
appendMessage(tr("Selected device is invalid."), ErrorMessageFormat);
return false;
}
if (dev->deviceState() == IDevice::DeviceDisconnected) {
appendMessage(tr("Selected device is disconnected."), ErrorMessageFormat);
return false;
}
AndroidDeviceInfo devInfoLocal = AndroidDevice::androidDeviceInfoFromIDevice(dev);
if (devInfoLocal.isValid()) {
if (devInfoLocal.type == AndroidDeviceInfo::Emulator) {
if (dev->machineType() == IDevice::Emulator) {
appendMessage(tr("Launching AVD."), NormalMessageFormat);
devInfoLocal.serialNumber = startAvd(avdMan, devInfoLocal.avdname);
devInfoLocal.serialNumber = avdMananager.startAvd(devInfoLocal.avdname);
}
if (devInfoLocal.serialNumber.isEmpty()) {
appendMessage(tr("Could not run AVD."), ErrorMessageFormat);
appendMessage(tr("Could not start AVD."), ErrorMessageFormat);
} else {
m_devInfo = devInfoLocal;
m_avdAbis = m_config.getAbis(m_config.adbToolPath(), m_devInfo.serialNumber);
m_serialNumber = devInfoLocal.serialNumber;
m_avdAbis = m_androidConfig.getAbis(m_androidConfig.adbToolPath(), m_serialNumber);
}
return !devInfoLocal.serialNumber.isEmpty();
} else {
@@ -283,7 +262,7 @@ bool AndroidQmlPreviewWorker::ensureAvdIsRunning()
}
return false;
}
m_avdAbis = m_config.getAbis(m_config.adbToolPath(), m_devInfo.serialNumber);
m_avdAbis = m_androidConfig.getAbis(m_androidConfig.adbToolPath(), m_serialNumber);
return true;
}
@@ -291,7 +270,7 @@ bool AndroidQmlPreviewWorker::checkAndInstallPreviewApp()
{
const QStringList command {"pm", "list", "packages", apkInfo()->appId};
appendMessage(tr("Checking if %1 app is installed.").arg(apkInfo()->name), NormalMessageFormat);
const SdkToolResult res = runAdbShellCommand(m_devInfo.serialNumber, command);
const SdkToolResult res = runAdbShellCommand(command);
if (!res.success()) {
appendMessage(res.stdErr(), ErrorMessageFormat);
return false;
@@ -303,7 +282,7 @@ bool AndroidQmlPreviewWorker::checkAndInstallPreviewApp()
ErrorMessageFormat);
return false;
}
const FilePath apkPath = viewerApkPath(m_avdAbis.first());
const FilePath apkPath = designViewerApkPath(m_avdAbis.first());
if (!apkPath.exists()) {
appendMessage(tr("Cannot install %1 app for %2 architecture. "
"The appropriate APK was not found in resources folders.").
@@ -313,32 +292,29 @@ bool AndroidQmlPreviewWorker::checkAndInstallPreviewApp()
appendMessage(tr("Installing %1 APK.").arg(apkInfo()->name), NormalMessageFormat);
const SdkToolResult res = runAdbCommand(m_devInfo.serialNumber, {"install",
apkPath.toString()});
if (!res.success()) {
const SdkToolResult res = runAdbCommand({"install", apkPath.toString()});
if (!res.success())
appendMessage(res.stdErr(), StdErrFormat);
return false;
}
}
return true;
}
bool AndroidQmlPreviewWorker::prepareUpload(UploadInfo &transfer)
return res.success();
}
bool AndroidQmlPreviewWorker::preparePreviewArtefacts()
{
if (m_rc->project()->id() == QmlProjectManager::Constants::QML_PROJECT_ID) {
const auto bs = m_rc->target()->buildSystem();
if (bs) {
transfer.uploadPackage = FilePath::fromString(
m_uploadInfo.uploadPackage = FilePath::fromString(
bs->additionalData(QmlProjectManager::Constants::mainFilePath).toString());
transfer.projectFolder = bs->projectDirectory();
m_uploadInfo.projectFolder = bs->projectDirectory();
return true;
}
} else {
const FilePaths allFiles = m_rc->project()->files(m_rc->project()->SourceFiles);
const FilePaths filesToExport = Utils::filtered(allFiles,[](const FilePath &path) {
return path.suffix() == "qmlproject";});
return path.suffix() == "qmlproject";
});
if (filesToExport.size() > 1) {
appendMessage(tr("Too many .qmlproject files in your project. Open directly the "
@@ -348,10 +324,9 @@ bool AndroidQmlPreviewWorker::prepareUpload(UploadInfo &transfer)
appendMessage(tr("No .qmlproject file found among project files."), ErrorMessageFormat);
} else {
const FilePath qmlprojectFile = filesToExport.first();
transfer.uploadPackage = transfer.
projectFolder.
resolvePath(qmlprojectFile.fileName());
transfer.projectFolder = qmlprojectFile.parentDir();
m_uploadInfo.uploadPackage = m_uploadInfo.projectFolder.resolvePath(
qmlprojectFile.fileName());
m_uploadInfo.projectFolder = qmlprojectFile.parentDir();
return true;
}
}
@@ -366,16 +341,15 @@ FilePath AndroidQmlPreviewWorker::createQmlrcFile(const FilePath &workFolder,
const FilePath rccBinary = qtVersion->rccFilePath();
QtcProcess rccProcess;
FilePath qrcPath = FilePath::fromString(basename) + ".qrc4viewer";
const FilePath qmlrcPath = FilePath::fromString(QDir::tempPath() + "/" + basename +
packageSuffix);
const FilePath qmlrcPath = FilePath::fromString(QDir::tempPath()) / basename + packageSuffix;
rccProcess.setWorkingDirectory(workFolder);
const QStringList arguments[2] = {{"--project", "--output", qrcPath.fileName()},
{"--binary", "--output", qmlrcPath.path(),
qrcPath.fileName()}};
for (const auto &arguments : arguments) {
rccProcess.setCommand({rccBinary, arguments});
for (const QStringList &args : arguments) {
rccProcess.setCommand({rccBinary, args});
rccProcess.start();
if (!rccProcess.waitForStarted()) {
appendMessage(tr("Could not create file for %1 \"%2\"").
@@ -420,72 +394,55 @@ FilePath AndroidQmlPreviewWorker::createQmlrcFile(const FilePath &workFolder,
return qmlrcPath;
}
bool AndroidQmlPreviewWorker::uploadFiles(const UploadInfo &transfer)
bool AndroidQmlPreviewWorker::uploadPreviewArtefacts()
{
appendMessage(tr("Uploading files."), NormalMessageFormat);
const FilePath qresPath = createQmlrcFile(FilePath::fromString(transfer.projectFolder.path()),
transfer.uploadPackage.baseName());
const FilePath qresPath = createQmlrcFile(m_uploadInfo.projectFolder,
m_uploadInfo.uploadPackage.baseName());
if (!qresPath.exists())
return false;
runAdbShellCommand(m_devInfo.serialNumber, {"mkdir", "-p", apkInfo()->uploadDir});
const SdkToolResult res = runAdbCommand(m_devInfo.serialNumber,
{"push", qresPath.resolvePath(QString()).toString(),
runAdbShellCommand({"mkdir", "-p", apkInfo()->uploadDir});
const SdkToolResult res = runAdbCommand({"push", qresPath.resolvePath(QString()).toString(),
apkInfo()->uploadDir});
if (!res.success()) {
appendMessage(res.stdOut(), ErrorMessageFormat);
if (res.stdOut().contains("Permission denied"))
if (res.stdOut().contains("Permission denied")) {
appendMessage("'Permission denied' error detected. Try restarting your device "
"and then running the preview.", NormalMessageFormat);
}
}
qresPath.removeFile();
return res.success();
}
bool AndroidQmlPreviewWorker::runPreviewApp(const UploadInfo &transfer)
bool AndroidQmlPreviewWorker::startPreviewApp()
{
stopPreviewApp();
appendMessage(tr("Starting %1.").arg(apkInfo()->name), NormalMessageFormat);
const QDir destDir(apkInfo()->uploadDir);
const QString qmlrcPath = destDir.filePath(m_uploadInfo.uploadPackage.baseName()
+ packageSuffix);
const QStringList command{"am", "start",
"-n", apkInfo()->activityId,
"-e", "extraappparams",
QString::fromLatin1(
destDir.filePath(transfer.uploadPackage.baseName() + packageSuffix).
toUtf8().
toBase64())};
const SdkToolResult res = runAdbShellCommand(m_devInfo.serialNumber, command);
if (!res.success()) {
appendMessage(res.stdErr(), ErrorMessageFormat);
return res.success();
}
"-e", "extraappparams", QLatin1String(qmlrcPath.toUtf8().toBase64())};
const SdkToolResult result = runAdbShellCommand(command);
if (result.success())
appendMessage(tr("%1 is running.").arg(apkInfo()->name), NormalMessageFormat);
m_viewerPid = pidofPreview(m_devInfo.serialNumber);
return true;
else
appendMessage(result.stdErr(), ErrorMessageFormat);
return result.success();
}
bool AndroidQmlPreviewWorker::stopPreviewApp()
{
const QStringList command{"am", "force-stop", apkInfo()->appId};
const SdkToolResult res = runAdbShellCommand(m_devInfo.serialNumber, command);
if (!res.success()) {
const SdkToolResult res = runAdbShellCommand(command);
if (!res.success())
appendMessage(res.stdErr(), ErrorMessageFormat);
return res.success();
}
return true;
}
void AndroidQmlPreviewWorker::appendLogLines(const QStringList & lines)
{
for (const QString& line : lines) {
const int charsToSkip = apkInfo()->name.length() + 2; // strlen(": ") == 2
const QString formatted = line.mid(line.indexOf(apkInfo()->name) + charsToSkip);
// TODO: See AndroidRunnerWorker::logcatProcess() - filtering for logs to decide format.
appendMessage(formatted, StdOutFormat);
}
}
} // namespace Internal
} // namespace Android

View File

@@ -25,9 +25,12 @@
#pragma once
#include "androidconfigurations.h"
#include <projectexplorer/runcontrol.h>
#include <utils/environment.h>
#include <QFutureWatcher>
namespace Android {
class SdkToolResult;
@@ -45,6 +48,10 @@ class AndroidQmlPreviewWorker : public ProjectExplorer::RunWorker
Q_OBJECT
public:
AndroidQmlPreviewWorker(ProjectExplorer::RunControl *runControl);
~AndroidQmlPreviewWorker();
signals:
void previewPidChanged();
private:
void start() override;
@@ -52,22 +59,33 @@ private:
bool ensureAvdIsRunning();
bool checkAndInstallPreviewApp();
bool prepareUpload(UploadInfo &transfer);
bool uploadFiles(const UploadInfo &transfer);
bool preparePreviewArtefacts();
bool uploadPreviewArtefacts();
bool runPreviewApp(const UploadInfo &transfer);
SdkToolResult runAdbCommand(const QStringList &arguments) const;
SdkToolResult runAdbShellCommand(const QStringList &arguments) const;
int pidofPreview() const;
bool isPreviewRunning(int lastKnownPid = -1) const;
void startPidWatcher();
void startLogcat();
void filterLogcatAndAppendMessage(const QString &stdOut);
bool startPreviewApp();
bool stopPreviewApp();
void startLogcat();
void appendLogLines(const QStringList &lines);
Utils::FilePath designViewerApkPath(const QString &abi) const;
Utils::FilePath createQmlrcFile(const Utils::FilePath &workFolder, const QString &basename);
ProjectExplorer::RunControl *m_rc = nullptr;
AndroidConfig m_config;
AndroidDeviceInfo m_devInfo;
AndroidConfig m_androidConfig;
QString m_serialNumber;
QStringList m_avdAbis;
int m_viewerPid = -1;
QFutureWatcher<void> m_pidFutureWatcher;
Utils::QtcProcess m_logcatProcess;
QString m_logcatStartTimeStamp;
UploadInfo m_uploadInfo;
};
} // namespace Internal

View File

@@ -123,7 +123,7 @@ void DeviceSelectorDetailsPanel::refresh()
m_memoryView->refresh();
m_algorithmView->refresh();
m_algorithmView->setAlgorithm(m_selection.algorithmIndex);
m_peripheralDescriptionFileChooser->setPath(m_selection.svd);
m_peripheralDescriptionFileChooser->setFilePath(Utils::FilePath::fromString(m_selection.svd));
}
// DeviceSelector

View File

@@ -2616,7 +2616,9 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
} else if (token.type == "type") {
styles.mainStyle = C_TYPE;
} else if (token.type == "typeParameter") {
styles.mainStyle = C_TYPE;
// clangd reports both type and non-type template parameters as type parameters,
// but the latter can be distinguished by the readonly modifier.
styles.mainStyle = token.modifiers.contains("readonly") ? C_PARAMETER : C_TYPE;
}
if (token.modifiers.contains("declaration"))
styles.mixinStyles.push_back(C_DECLARATION);

View File

@@ -506,9 +506,6 @@ void ClangdTestLocalReferences::test()
client()->findLocalUsages(doc, cursor, std::move(handler));
timer.start(10000);
loop.exec();
QEXPECT_FAIL("cursor not on identifier", "clangd bug: go to definition does not return", Abort);
QEXPECT_FAIL("template parameter member access",
"clangd bug: go to definition does not return", Abort);
QVERIFY(timer.isActive());
timer.stop();
@@ -909,7 +906,7 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("template parameter default argument") << 265 << 41 << 265 << 44
<< QList<int>{C_TYPE} << 0;
QTest::newRow("template non-type parameter") << 265 << 50 << 265 << 74
<< QList<int>{C_LOCAL, C_DECLARATION} << 0;
<< QList<int>{C_PARAMETER, C_DECLARATION} << 0;
QTest::newRow("template non-type parameter default argument") << 265 << 77 << 265 << 78
<< QList<int>{C_NUMBER} << 0;
QTest::newRow("template template parameter") << 265 << 103 << 265 << 128
@@ -935,7 +932,7 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("local var declaration of template parameter type") << 268 << 27 << 268 << 57
<< QList<int>{C_LOCAL, C_DECLARATION} << 0;
QTest::newRow("reference to non-type template parameter") << 269 << 46 << 269 << 70
<< QList<int>{C_LOCAL} << 0;
<< QList<int>{C_PARAMETER} << 0;
QTest::newRow("local var declaration initialized with non-type template parameter")
<< 269 << 10 << 269 << 43
<< QList<int>{C_LOCAL, C_DECLARATION} << 0;
@@ -1331,12 +1328,6 @@ void ClangdTestHighlighting::test()
QEXPECT_FAIL("non-final virtual function call via pointer",
"clangd < 14 does not send virtual modifier", Continue);
}
QEXPECT_FAIL("template non-type parameter",
"FIXME: clangd reports non-type template parameters at \"typeParameter\"",
Continue);
QEXPECT_FAIL("reference to non-type template parameter",
"FIXME: clangd reports non-type template parameters at \"typeParameter\"",
Continue);
QEXPECT_FAIL("non-const reference via member function call as output argument (function)",
"Without punctuation and comment tokens from clangd, it's not possible "
"to highlight entire expressions. But do we really want this? What about nested "
@@ -1627,7 +1618,7 @@ void ClangdTestCompletion::testFunctionHintsFiltered()
QVERIFY(proposal);
QCOMPARE(proposal->size(), 2);
QVERIFY(hasItem(proposal, "func(const S &amp;s, <b>int j</b>) -&gt; void"));
QEXPECT_FAIL("", "FIXME: LanguageClient handles active parameter only in active signature", Abort);
QEXPECT_FAIL("", "QTCREATORBUG-26346", Abort);
QVERIFY(hasItem(proposal, "func(const S &amp;s, <b>int j</b>, int k) -&gt; void"));
}
@@ -1640,7 +1631,7 @@ void ClangdTestCompletion::testFunctionHintConstructor()
QVERIFY(!hasItem(proposal, "globalVariable"));
QVERIFY(!hasItem(proposal, " class"));
QVERIFY(hasItem(proposal, "Foo(<b>int</b>)"));
QEXPECT_FAIL("", "FIXME: LanguageClient handles active parameter only in active signature", Abort);
QEXPECT_FAIL("", "QTCREATORBUG-26346", Abort);
QVERIFY(hasItem(proposal, "Foo(<b>int</b>, double)"));
}
@@ -1669,8 +1660,7 @@ void ClangdTestCompletion::testCompletePrivateFunctionDefinition()
getProposal("privateFuncDefCompletion.cpp", proposal);
QVERIFY(proposal);
QEXPECT_FAIL("", "FIXME: clangd needs to differentiate "
"between function call and function definiton", Abort);
QEXPECT_FAIL("", "https://github.com/clangd/clangd/issues/880", Abort);
QCOMPARE(proposal->size(), 1);
QVERIFY(hasItem(proposal, " theFunc()"));
}

View File

@@ -67,7 +67,7 @@ SettingsPageWidget::SettingsPageWidget()
const ClearCaseSettings &s = ClearCasePlugin::settings();
m_ui.commandPathChooser->setPath(s.ccCommand);
m_ui.commandPathChooser->setFilePath(FilePath::fromString(s.ccCommand));
m_ui.timeOutSpinBox->setValue(s.timeOutS);
m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut);
m_ui.noCommentCheckBox->setChecked(s.noComment);

View File

@@ -35,6 +35,7 @@
#include "cmakeprojectnodes.h"
#include "cmakeprojectplugin.h"
#include "cmakespecificsettings.h"
#include "projecttreehelper.h"
#include "utils/algorithm.h"
#include <android/androidconstants.h>
@@ -158,8 +159,7 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc)
m_treeScanner.setFilter([this](const MimeType &mimeType, const FilePath &fn) {
// Mime checks requires more resources, so keep it last in check list
auto isIgnored = fn.toString().startsWith(projectFilePath().toString() + ".user")
|| TreeScanner::isWellKnownBinary(mimeType, fn);
auto isIgnored = TreeScanner::isWellKnownBinary(mimeType, fn);
// Cache mime check result for speed up
if (!isIgnored) {
@@ -213,7 +213,6 @@ CMakeBuildSystem::~CMakeBuildSystem()
delete m_cppCodeModelUpdater;
qDeleteAll(m_extraCompilers);
qDeleteAll(m_allFiles.allFiles);
}
void CMakeBuildSystem::triggerParsing()
@@ -244,28 +243,11 @@ void CMakeBuildSystem::triggerParsing()
qCDebug(cmakeBuildSystemLog) << "ParseGuard acquired.";
if (m_allFiles.allFiles.isEmpty()) {
qCDebug(cmakeBuildSystemLog)
<< "No treescanner information available, forcing treescanner run.";
updateReparseParameters(REPARSE_SCAN);
}
int reparseParameters = takeReparseParameters();
m_waitingForScan = (reparseParameters & REPARSE_SCAN) != 0;
m_waitingForParse = true;
m_combinedScanAndParseResult = true;
if (m_waitingForScan) {
qCDebug(cmakeBuildSystemLog) << "Starting TreeScanner";
QTC_CHECK(m_treeScanner.isFinished());
if (m_treeScanner.asyncScanForFiles(projectDirectory()))
Core::ProgressManager::addTask(m_treeScanner.future(),
tr("Scan \"%1\" project tree")
.arg(project()->displayName()),
"CMake.Scan.Tree");
}
QTC_ASSERT(m_parameters.isValid(), return );
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
@@ -365,8 +347,6 @@ QString CMakeBuildSystem::reparseParametersString(int reparseFlags)
result += " FORCE_CMAKE_RUN";
if (reparseFlags & REPARSE_FORCE_INITIAL_CONFIGURATION)
result += " FORCE_CONFIG";
if (reparseFlags & REPARSE_SCAN)
result += " SCAN";
}
return result.trimmed();
}
@@ -442,7 +422,7 @@ void CMakeBuildSystem::runCMakeAndScanProjectTree()
BuildDirParameters parameters(cmakeBuildConfiguration());
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to \"Rescan Project\" command";
setParametersAndRequestParse(parameters,
REPARSE_FORCE_CMAKE_RUN | REPARSE_SCAN | REPARSE_URGENT);
REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT);
}
void CMakeBuildSystem::runCMakeWithExtraArguments()
@@ -461,18 +441,6 @@ void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget)
cmakeBuildConfiguration()->buildTarget(buildTarget);
}
void CMakeBuildSystem::handleTreeScanningFinished()
{
QTC_CHECK(m_waitingForScan);
qDeleteAll(m_allFiles.allFiles);
m_allFiles = m_treeScanner.release();
m_waitingForScan = false;
combineScanAndParse(m_reader.lastCMakeExitCode() != 0);
}
bool CMakeBuildSystem::persistCMakeState()
{
BuildDirParameters parameters(cmakeBuildConfiguration());
@@ -524,17 +492,10 @@ void CMakeBuildSystem::clearCMakeCache()
path.removeRecursively();
}
std::unique_ptr<CMakeProjectNode> CMakeBuildSystem::generateProjectTree(
const TreeScanner::Result &allFiles, bool failedToParse)
{
auto root = m_reader.generateProjectTree(allFiles, failedToParse);
return root;
}
void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
{
if (cmakeBuildConfiguration()->isActive()) {
if (m_waitingForParse || m_waitingForScan)
if (m_waitingForParse)
return;
if (m_combinedScanAndParseResult) {
@@ -548,6 +509,15 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
"<p>The backup of the previous configuration has been restored.</p>"
"<p>Have a look at the Issues pane or in the \"Projects > Build\" settings "
"for more information about the failure.</p"));
m_reader.resetData();
m_currentGuard = {};
m_testNames.clear();
emitBuildSystemUpdated();
runCTest();
} else {
updateFallbackProjectData();
@@ -558,15 +528,6 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
"for more information about the failure.</p"));
}
}
m_reader.resetData();
m_currentGuard = {};
m_testNames.clear();
emitBuildSystemUpdated();
runCTest();
}
void CMakeBuildSystem::checkAndReportError(QString &errorMessage)
@@ -614,7 +575,7 @@ void CMakeBuildSystem::updateProjectData()
Project *p = project();
{
auto newRoot = generateProjectTree(m_allFiles, false);
auto newRoot = m_reader.rootProjectNode();
if (newRoot) {
setRootProjectNode(std::move(newRoot));
@@ -707,16 +668,51 @@ void CMakeBuildSystem::updateProjectData()
qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date.";
}
void CMakeBuildSystem::handleTreeScanningFinished()
{
TreeScanner::Result result = m_treeScanner.release();
m_allFiles = result.folderNode;
qDeleteAll(result.allFiles);
updateFileSystemNodes();
}
void CMakeBuildSystem::updateFileSystemNodes()
{
auto newRoot = std::make_unique<CMakeProjectNode>(m_parameters.sourceDirectory);
newRoot->setDisplayName(m_parameters.sourceDirectory.fileName());
if (!m_reader.topCmakeFile().isEmpty()) {
auto node = std::make_unique<FileNode>(m_reader.topCmakeFile(), FileType::Project);
node->setIsGenerated(false);
std::vector<std::unique_ptr<FileNode>> fileNodes;
fileNodes.emplace_back(std::move(node));
addCMakeLists(newRoot.get(), std::move(fileNodes));
}
addFileSystemNodes(newRoot.get(), m_allFiles);
setRootProjectNode(std::move(newRoot));
m_reader.resetData();
m_currentGuard = {};
emitBuildSystemUpdated();
qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date.";
}
void CMakeBuildSystem::updateFallbackProjectData()
{
qCDebug(cmakeBuildSystemLog) << "Updating fallback CMake project data";
QTC_ASSERT(m_treeScanner.isFinished() && !m_reader.isParsing(), return );
auto newRoot = generateProjectTree(m_allFiles, true);
setRootProjectNode(std::move(newRoot));
qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date.";
qCDebug(cmakeBuildSystemLog) << "Starting TreeScanner";
QTC_CHECK(m_treeScanner.isFinished());
if (m_treeScanner.asyncScanForFiles(projectDirectory()))
Core::ProgressManager::addTask(m_treeScanner.future(),
tr("Scan \"%1\" project tree")
.arg(project()->displayName()),
"CMake.Scan.Tree");
}
void CMakeBuildSystem::updateCMakeConfiguration(QString &errorMessage)
@@ -899,7 +895,7 @@ void CMakeBuildSystem::becameDirty()
if (isParsing())
return;
setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_SCAN);
setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_DEFAULT);
}
void CMakeBuildSystem::updateReparseParameters(const int parameters)

View File

@@ -37,7 +37,10 @@
#include <utils/temporarydirectory.h>
namespace CppEditor { class CppProjectUpdater; }
namespace ProjectExplorer { class ExtraCompiler; }
namespace ProjectExplorer {
class ExtraCompiler;
class FolderNode;
}
namespace CMakeProjectManager {
@@ -113,8 +116,7 @@ private:
REPARSE_FORCE_INITIAL_CONFIGURATION
= (1 << 1), // Force initial configuration arguments to cmake
REPARSE_FORCE_EXTRA_CONFIGURATION = (1 << 2), // Force extra configuration arguments to cmake
REPARSE_SCAN = (1 << 3), // Run filesystem scan
REPARSE_URGENT = (1 << 4), // Do not delay the parser run by 1s
REPARSE_URGENT = (1 << 3), // Do not delay the parser run by 1s
};
QString reparseParametersString(int reparseFlags);
void setParametersAndRequestParse(const BuildDirParameters &parameters,
@@ -132,9 +134,6 @@ private:
// Combining Treescanner and Parser states:
void combineScanAndParse(bool restoredFromBackup);
std::unique_ptr<CMakeProjectNode> generateProjectTree(
const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse);
void checkAndReportError(QString &errorMessage);
void updateCMakeConfiguration(QString &errorMessage);
@@ -146,6 +145,8 @@ private:
const QList<QByteArray> &moduleMappings);
void updateInitialCMakeExpandableVars();
void updateFileSystemNodes();
void handleParsingSucceeded(bool restoredFromBackup);
void handleParsingFailed(const QString &msg);
@@ -161,10 +162,9 @@ private:
void runCTest();
ProjectExplorer::TreeScanner m_treeScanner;
ProjectExplorer::TreeScanner::Result m_allFiles;
std::shared_ptr<ProjectExplorer::FolderNode> m_allFiles;
QHash<QString, bool> m_mimeBinaryCache;
bool m_waitingForScan = false;
bool m_waitingForParse = false;
bool m_combinedScanAndParseResult = false;

View File

@@ -721,31 +721,5 @@ FileApiQtcData extractData(FileApiData &input,
return result;
}
FileApiQtcData generateFallbackData(const FilePath &topCmakeFile,
const FilePath &sourceDirectory,
const FilePath &buildDirectory,
QString errorMessage)
{
Q_UNUSED(buildDirectory)
FileApiQtcData result;
result.rootProjectNode.reset(new CMakeProjectNode{sourceDirectory});
result.rootProjectNode->setDisplayName(sourceDirectory.fileName());
result.errorMessage = errorMessage;
if (!topCmakeFile.isEmpty()) {
auto node = std::make_unique<FileNode>(topCmakeFile, FileType::Project);
node->setIsGenerated(false);
std::vector<std::unique_ptr<FileNode>> fileNodes;
fileNodes.emplace_back(std::move(node));
addCMakeLists(result.rootProjectNode.get(), std::move(fileNodes));
}
return result;
}
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -75,10 +75,6 @@ public:
FileApiQtcData extractData(FileApiData &data,
const Utils::FilePath &sourceDirectory,
const Utils::FilePath &buildDirectory);
FileApiQtcData generateFallbackData(const Utils::FilePath &topCmakeFile,
const Utils::FilePath &sourceDirectory,
const Utils::FilePath &buildDirectory,
QString errorMessage);
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -27,7 +27,6 @@
#include "fileapidataextractor.h"
#include "fileapiparser.h"
#include "projecttreehelper.h"
#include <coreplugin/messagemanager.h>
@@ -214,15 +213,6 @@ bool FileApiReader::usesAllCapsTargets() const
return m_usesAllCapsTargets;
}
std::unique_ptr<CMakeProjectNode> FileApiReader::generateProjectTree(
const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse)
{
if (failedToParse)
addFileSystemNodes(m_rootProjectNode.get(), allFiles.folderNode);
return std::exchange(m_rootProjectNode, {});
}
RawProjectParts FileApiReader::createRawProjectParts(QString &errorMessage)
{
Q_UNUSED(errorMessage)
@@ -250,37 +240,29 @@ void FileApiReader::endState(const FilePath &replyFilePath, bool restoredFromBac
const FilePath sourceDirectory = m_parameters.sourceDirectory;
const FilePath buildDirectory = m_parameters.buildDirectory;
const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{};
const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType;
QTC_CHECK(!replyFilePath.needsDevice());
m_lastReplyTimestamp = replyFilePath.lastModified();
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
[replyFilePath, sourceDirectory, buildDirectory, topCmakeFile, cmakeBuildType](
[replyFilePath, sourceDirectory, buildDirectory, cmakeBuildType](
QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi) {
auto result = std::make_shared<FileApiQtcData>();
FileApiData data = FileApiParser::parseData(fi,
replyFilePath,
cmakeBuildType,
result->errorMessage);
if (!result->errorMessage.isEmpty()) {
*result = generateFallbackData(topCmakeFile,
sourceDirectory,
buildDirectory,
result->errorMessage);
} else {
if (result->errorMessage.isEmpty())
*result = extractData(data, sourceDirectory, buildDirectory);
}
if (!result->errorMessage.isEmpty()) {
else
qWarning() << result->errorMessage;
}
fi.reportResult(result);
});
onResultReady(m_future.value(),
this,
[this, topCmakeFile, sourceDirectory, buildDirectory, restoredFromBackup](
[this, sourceDirectory, buildDirectory, restoredFromBackup](
const std::shared_ptr<FileApiQtcData> &value) {
m_isParsing = false;
m_cache = std::move(value->cache);
@@ -348,6 +330,16 @@ void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &conf
QTC_CHECK(settingsFile.writeFileContents(contents));
}
std::unique_ptr<CMakeProjectNode> FileApiReader::rootProjectNode()
{
return std::exchange(m_rootProjectNode, {});
}
FilePath FileApiReader::topCmakeFile() const
{
return m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{};
}
int FileApiReader::lastCMakeExitCode() const
{
return m_lastCMakeExitCode;

View File

@@ -71,8 +71,6 @@ public:
QList<CMakeBuildTarget> takeBuildTargets(QString &errorMessage);
CMakeConfig takeParsedConfiguration(QString &errorMessage);
QString ctestPath() const;
std::unique_ptr<CMakeProjectNode> generateProjectTree(
const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse);
ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage);
bool isMultiConfig() const;
@@ -80,6 +78,10 @@ public:
int lastCMakeExitCode() const;
std::unique_ptr<CMakeProjectNode> rootProjectNode();
Utils::FilePath topCmakeFile() const;
signals:
void configurationStarted() const;
void dataAvailable(bool restoredFromBackup) const;

View File

@@ -243,9 +243,15 @@ void CppLocalRenaming::forgetRenamingSelection()
m_renameSelectionIndex = -1;
}
bool CppLocalRenaming::isWithinSelection(const QTextEdit::ExtraSelection &selection, int position)
{
return selection.cursor.selectionStart() <= position
&& position <= selection.cursor.selectionEnd();
}
bool CppLocalRenaming::isWithinRenameSelection(int position)
{
return renameSelectionBegin() <= position && position <= renameSelectionEnd();
return isWithinSelection(renameSelection(), position);
}
bool CppLocalRenaming::isSameSelection(int cursorPosition) const
@@ -254,14 +260,14 @@ bool CppLocalRenaming::isSameSelection(int cursorPosition) const
return false;
const QTextEdit::ExtraSelection &sel = m_selections[m_renameSelectionIndex];
return (sel.cursor.position() <= cursorPosition && cursorPosition <= sel.cursor.anchor());
return isWithinSelection(sel, cursorPosition);
}
bool CppLocalRenaming::findRenameSelection(int cursorPosition)
{
for (int i = 0, total = m_selections.size(); i < total; ++i) {
const QTextEdit::ExtraSelection &sel = m_selections.at(i);
if (sel.cursor.position() <= cursorPosition && cursorPosition <= sel.cursor.anchor()) {
if (isWithinSelection(sel, cursorPosition)) {
m_renameSelectionIndex = i;
return true;
}

View File

@@ -72,11 +72,12 @@ private:
// The "rename selection" is the local use selection on which the user started the renaming
bool findRenameSelection(int cursorPosition);
void forgetRenamingSelection();
static bool isWithinSelection(const QTextEdit::ExtraSelection &selection, int position);
bool isWithinRenameSelection(int position);
QTextEdit::ExtraSelection &renameSelection();
int renameSelectionBegin() { return renameSelection().cursor.position(); }
int renameSelectionEnd() { return renameSelection().cursor.anchor(); }
int renameSelectionBegin() { return renameSelection().cursor.selectionStart(); }
int renameSelectionEnd() { return renameSelection().cursor.selectionEnd(); }
void updateRenamingSelectionCursor(const QTextCursor &cursor);
void updateRenamingSelectionFormat(const QTextCharFormat &format);

View File

@@ -308,7 +308,8 @@ DebuggerKitAspect::ConfigurationErrors DebuggerKitAspect::configurationErrors(co
ConfigurationErrors result = NoConfigurationError;
const FilePath debugger = item->command();
if (!debugger.exists() || debugger.isDir())
const bool found = debugger.exists() && !debugger.isDir();
if (!found)
result |= DebuggerNotFound;
else if (!debugger.isExecutableFile())
result |= DebuggerNotExecutable;
@@ -321,7 +322,7 @@ DebuggerKitAspect::ConfigurationErrors DebuggerKitAspect::configurationErrors(co
result |= DebuggerDoesNotMatch;
}
if (!debugger.exists() || debugger.isDir()) {
if (!found) {
if (item->engineType() == NoEngineType)
return NoDebugger;

View File

@@ -897,7 +897,10 @@ void DockerDevicePrivate::startContainer()
void DockerDevicePrivate::tryCreateLocalFileAccess()
{
if (!m_container.isEmpty() || DockerPlugin::isDaemonRunning().value_or(true) == false)
if (!m_container.isEmpty())
return;
if (DockerPlugin::isDaemonRunning().value_or(true) == false)
return;
if (!m_shell)

View File

@@ -87,6 +87,7 @@
#include <QClipboard>
#include <QFileDialog>
#include <QMenu>
#include <QTimer>
#include <QVBoxLayout>
#ifdef WITH_TESTS
@@ -477,8 +478,11 @@ void GitPluginPrivate::onApplySettings()
bool gitFoundOk;
QString errorMessage;
m_settings.gitExecutable(&gitFoundOk, &errorMessage);
if (!gitFoundOk)
if (!gitFoundOk) {
QTimer::singleShot(0, this, [this, errorMessage] {
Core::AsynchronousMessageBox::warning(tr("Git Settings"), errorMessage);
});
}
}
void GitPluginPrivate::cleanCommitMessageFile()

View File

@@ -248,6 +248,7 @@ static ClientCapabilities generateClientCapabilities()
signatureHelp.setDynamicRegistration(true);
TextDocumentClientCapabilities::SignatureHelpCapabilities::SignatureInformationCapabilities info;
info.setDocumentationFormat({MarkupKind::markdown, MarkupKind::plaintext});
info.setActiveParameterSupport(true);
signatureHelp.setSignatureInformation(info);
documentCapabilities.setSignatureHelp(signatureHelp);

View File

@@ -61,11 +61,12 @@ QString FunctionHintProposalModel::text(int index) const
if (index < 0 || m_sigis.signatures().size() <= index)
return {};
const SignatureInformation signature = m_sigis.signatures().at(index);
int parametersIndex = signature.activeParameter().value_or(-1);
if (parametersIndex < 0) {
if (index == m_sigis.activeSignature().value_or(-1))
parametersIndex = m_sigis.activeParameter().value_or(-1);
}
QString label = signature.label();
if (index != m_sigis.activeSignature().value_or(-1))
return label;
const int parametersIndex = m_sigis.activeParameter().value_or(-1);
if (parametersIndex < 0)
return label;

View File

@@ -78,14 +78,18 @@ static void handleGotoDefinitionResponse(const GotoDefinitionRequest::Response &
{
if (Utils::optional<GotoResult> _result = response.result()) {
const GotoResult result = _result.value();
if (Utils::holds_alternative<std::nullptr_t>(result))
return;
if (auto ploc = Utils::get_if<Location>(&result)) {
if (Utils::holds_alternative<std::nullptr_t>(result)) {
callback({});
} else if (auto ploc = Utils::get_if<Location>(&result)) {
callback(linkUnderCursor.value_or(ploc->toLink()));
} else if (auto plloc = Utils::get_if<QList<Location>>(&result)) {
if (!plloc->isEmpty())
callback(linkUnderCursor.value_or(plloc->value(0).toLink()));
else
callback({});
}
} else {
callback({});
}
}

View File

@@ -62,7 +62,9 @@ void DocumentLocatorFilter::updateCurrentClient()
disconnect(m_resetSymbolsConnection);
TextEditor::TextDocument *document = TextEditor::TextDocument::currentTextDocument();
if (Client *client = LanguageClientManager::clientForDocument(document)) {
if (Client *client = LanguageClientManager::clientForDocument(document);
client && client->locatorsEnabled()) {
setEnabled(true);
if (m_symbolCache != client->documentSymbolCache()) {
disconnect(m_updateSymbolsConnection);
m_symbolCache = client->documentSymbolCache();
@@ -76,6 +78,7 @@ void DocumentLocatorFilter::updateCurrentClient()
disconnect(m_updateSymbolsConnection);
m_symbolCache.clear();
m_currentUri.clear();
setEnabled(false);
}
}

View File

@@ -956,6 +956,15 @@ void CheckBoxField::setup(JsonFieldPage *page, const QString &name)
});
}
void CheckBoxField::setChecked(bool value)
{
auto w = qobject_cast<QCheckBox *>(widget());
QTC_ASSERT(w, return);
w->setChecked(value);
w->clicked(value);
}
bool CheckBoxField::validate(MacroExpander *expander, QString *message)
{
if (!JsonFieldPage::Field::validate(expander, message))

View File

@@ -230,11 +230,13 @@ private:
Utils::PathChooser::Kind m_kind = Utils::PathChooser::ExistingDirectory;
};
class CheckBoxField : public JsonFieldPage::Field
class PROJECTEXPLORER_EXPORT CheckBoxField : public JsonFieldPage::Field
{
public:
bool suppressName() const override { return true; }
void setChecked(bool);
private:
bool parseData(const QVariant &data, QString *errorMessage) override;

View File

@@ -257,12 +257,14 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
.arg(currentFile.fileName())
.arg(line).arg(column)
.arg(error.errorString()));
qWarning() << "Failed to parse wizard: " << currentFile.fileName();
continue;
}
if (!json.isObject()) {
verboseLog.append(tr("* Did not find a JSON object in \"%1\".\n")
.arg(currentFile.fileName()));
qWarning() << "Failed to parse wizard: " << currentFile.fileName();
continue;
}
@@ -280,6 +282,7 @@ QList<Core::IWizardFactory *> JsonWizardFactory::createWizardFactories()
JsonWizardFactory *factory = createWizardFactory(data, currentDir, &errorMessage);
if (!factory) {
verboseLog.append(tr("* Failed to create: %1\n").arg(errorMessage));
qWarning() << "Failed to create wizard: " << currentFile.fileName();
continue;
}

View File

@@ -51,8 +51,6 @@
#include <QCheckBox>
#include <QComboBox>
#include <QDir>
#include <QFileInfo>
#include <QFontMetrics>
#include <QGridLayout>
#include <QLabel>
@@ -133,18 +131,16 @@ Tasks SysRootKitAspect::validate(const Kit *k) const
if (dir.isEmpty())
return result;
if (dir.toString().startsWith("target:") || dir.toString().startsWith("remote:"))
if (dir.startsWith("target:") || dir.startsWith("remote:"))
return result;
const QFileInfo fi = dir.toFileInfo();
if (!fi.exists()) {
if (!dir.exists()) {
result << BuildSystemTask(Task::Warning,
tr("Sys Root \"%1\" does not exist in the file system.").arg(dir.toUserOutput()));
} else if (!fi.isDir()) {
} else if (!dir.isDir()) {
result << BuildSystemTask(Task::Warning,
tr("Sys Root \"%1\" is not a directory.").arg(dir.toUserOutput()));
} else if (QDir(dir.toString()).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) {
} else if (dir.dirEntries(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) {
result << BuildSystemTask(Task::Warning,
tr("Sys Root \"%1\" is empty.").arg(dir.toUserOutput()));
}
@@ -626,11 +622,10 @@ QList<ToolChain *> ToolChainKitAspect::toolChains(const Kit *k)
const QVariantMap value = k->value(ToolChainKitAspect::id()).toMap();
const QList<ToolChain *> tcList
= Utils::transform<QList>(ToolChainManager::allLanguages(),
[&value](Utils::Id l) -> ToolChain * {
= transform<QList>(ToolChainManager::allLanguages(), [&value](Id l) {
return ToolChainManager::findToolChain(value.value(l.toString()).toByteArray());
});
return Utils::filtered(tcList, [](ToolChain *tc) { return tc; });
return filtered(tcList, [](ToolChain *tc) { return tc; });
}
void ToolChainKitAspect::setToolChain(Kit *k, ToolChain *tc)
@@ -664,7 +659,7 @@ void ToolChainKitAspect::setAllToolChainsToMatch(Kit *k, ToolChain *tc)
QVariantMap result = k->value(ToolChainKitAspect::id()).toMap();
result.insert(tc->language().toString(), tc->id());
for (Utils::Id l : ToolChainManager::allLanguages()) {
for (const Id l : ToolChainManager::allLanguages()) {
if (l == tc->language())
continue;
@@ -692,7 +687,7 @@ void ToolChainKitAspect::setAllToolChainsToMatch(Kit *k, ToolChain *tc)
k->setValue(id(), result);
}
void ToolChainKitAspect::clearToolChain(Kit *k, Utils::Id language)
void ToolChainKitAspect::clearToolChain(Kit *k, Id language)
{
QTC_ASSERT(language.isValid(), return);
QTC_ASSERT(k, return);
@@ -710,7 +705,7 @@ Abi ToolChainKitAspect::targetAbi(const Kit *k)
QHash<Abi, int> abiCount;
foreach (ToolChain *tc, tcList) {
Abi ta = tc->targetAbi();
if (tc->language() == Utils::Id(Constants::CXX_LANGUAGE_ID))
if (tc->language() == Id(Constants::CXX_LANGUAGE_ID))
cxxAbi = tc->targetAbi();
abiCount[ta] = (abiCount.contains(ta) ? abiCount[ta] + 1 : 1);
}
@@ -799,7 +794,7 @@ private:
void refresh() override
{
Utils::Id devType = DeviceTypeKitAspect::deviceTypeId(m_kit);
Id devType = DeviceTypeKitAspect::deviceTypeId(m_kit);
if (!devType.isValid())
m_comboBox->setCurrentIndex(-1);
for (int i = 0; i < m_comboBox->count(); ++i) {
@@ -812,7 +807,7 @@ private:
void currentTypeChanged(int idx)
{
Utils::Id type = idx < 0 ? Utils::Id() : Utils::Id::fromSetting(m_comboBox->itemData(idx));
Id type = idx < 0 ? Id() : Id::fromSetting(m_comboBox->itemData(idx));
DeviceTypeKitAspect::setDeviceTypeId(m_kit, type);
}
@@ -851,7 +846,7 @@ KitAspectWidget *DeviceTypeKitAspect::createConfigWidget(Kit *k) const
KitAspect::ItemList DeviceTypeKitAspect::toUserOutput(const Kit *k) const
{
QTC_ASSERT(k, return {});
Utils::Id type = deviceTypeId(k);
Id type = deviceTypeId(k);
QString typeDisplayName = tr("Unknown device type");
if (type.isValid()) {
if (IDeviceFactory *factory = IDeviceFactory::find(type))
@@ -860,33 +855,33 @@ KitAspect::ItemList DeviceTypeKitAspect::toUserOutput(const Kit *k) const
return {{tr("Device type"), typeDisplayName}};
}
const Utils::Id DeviceTypeKitAspect::id()
const Id DeviceTypeKitAspect::id()
{
return "PE.Profile.DeviceType";
}
const Utils::Id DeviceTypeKitAspect::deviceTypeId(const Kit *k)
const Id DeviceTypeKitAspect::deviceTypeId(const Kit *k)
{
return k ? Utils::Id::fromSetting(k->value(DeviceTypeKitAspect::id())) : Utils::Id();
return k ? Id::fromSetting(k->value(DeviceTypeKitAspect::id())) : Id();
}
void DeviceTypeKitAspect::setDeviceTypeId(Kit *k, Utils::Id type)
void DeviceTypeKitAspect::setDeviceTypeId(Kit *k, Id type)
{
QTC_ASSERT(k, return);
k->setValue(DeviceTypeKitAspect::id(), type.toSetting());
}
QSet<Utils::Id> DeviceTypeKitAspect::supportedPlatforms(const Kit *k) const
QSet<Id> DeviceTypeKitAspect::supportedPlatforms(const Kit *k) const
{
return {deviceTypeId(k)};
}
QSet<Utils::Id> DeviceTypeKitAspect::availableFeatures(const Kit *k) const
QSet<Id> DeviceTypeKitAspect::availableFeatures(const Kit *k) const
{
Utils::Id id = DeviceTypeKitAspect::deviceTypeId(k);
Id id = DeviceTypeKitAspect::deviceTypeId(k);
if (id.isValid())
return {id.withPrefix("DeviceType.")};
return QSet<Utils::Id>();
return {};
}
// --------------------------------------------------------------------------
@@ -1225,7 +1220,7 @@ private:
QComboBox *m_comboBox;
QWidget *m_manageButton;
DeviceManagerModel *m_model;
Utils::Id m_selectedId;
Id m_selectedId;
};
} // namespace Internal

View File

@@ -34,6 +34,9 @@
#include <QCoreApplication>
using namespace Core;
using namespace Utils;
namespace ProjectExplorer {
namespace Internal {
@@ -49,8 +52,8 @@ public:
ProjectExplorerSettings settings() const;
void setSettings(const ProjectExplorerSettings &s);
QString projectsDirectory() const;
void setProjectsDirectory(const QString &pd);
FilePath projectsDirectory() const;
void setProjectsDirectory(const FilePath &pd);
bool useProjectsDirectory();
void setUseProjectsDirectory(bool v);
@@ -68,7 +71,7 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget(QWidget *parent) :
QWidget(parent)
{
m_ui.setupUi(this);
setJomVisible(Utils::HostOsInfo::isWindowsHost());
setJomVisible(HostOsInfo::isWindowsHost());
m_ui.stopBeforeBuildComboBox->addItem(tr("None"), int(StopBeforeBuild::None));
m_ui.stopBeforeBuildComboBox->addItem(tr("All"), int(StopBeforeBuild::All));
m_ui.stopBeforeBuildComboBox->addItem(tr("Same Project"), int(StopBeforeBuild::SameProject));
@@ -135,14 +138,14 @@ void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &
m_ui.lowBuildPriorityCheckBox->setChecked(m_settings.lowBuildPriority);
}
QString ProjectExplorerSettingsWidget::projectsDirectory() const
FilePath ProjectExplorerSettingsWidget::projectsDirectory() const
{
return m_ui.projectsDirectoryPathChooser->filePath().toString();
return m_ui.projectsDirectoryPathChooser->filePath();
}
void ProjectExplorerSettingsWidget::setProjectsDirectory(const QString &pd)
void ProjectExplorerSettingsWidget::setProjectsDirectory(const FilePath &pd)
{
m_ui.projectsDirectoryPathChooser->setPath(pd);
m_ui.projectsDirectoryPathChooser->setFilePath(pd);
}
bool ProjectExplorerSettingsWidget::useProjectsDirectory()
@@ -179,8 +182,8 @@ QWidget *ProjectExplorerSettingsPage::widget()
if (!m_widget) {
m_widget = new ProjectExplorerSettingsWidget;
m_widget->setSettings(ProjectExplorerPlugin::projectExplorerSettings());
m_widget->setProjectsDirectory(Core::DocumentManager::projectsDirectory().toString());
m_widget->setUseProjectsDirectory(Core::DocumentManager::useProjectsDirectory());
m_widget->setProjectsDirectory(DocumentManager::projectsDirectory());
m_widget->setUseProjectsDirectory(DocumentManager::useProjectsDirectory());
}
return m_widget;
}
@@ -189,9 +192,8 @@ void ProjectExplorerSettingsPage::apply()
{
if (m_widget) {
ProjectExplorerPlugin::setProjectExplorerSettings(m_widget->settings());
Core::DocumentManager::setProjectsDirectory(
Utils::FilePath::fromString(m_widget->projectsDirectory()));
Core::DocumentManager::setUseProjectsDirectory(m_widget->useProjectsDirectory());
DocumentManager::setProjectsDirectory(m_widget->projectsDirectory());
DocumentManager::setUseProjectsDirectory(m_widget->useProjectsDirectory());
}
}

View File

@@ -320,14 +320,14 @@ public:
QFontMetrics fm(option.widget->font());
for (const QString &project : projects) {
// Project name.
QFileInfo fi(project);
QString completeBase = fi.completeBaseName();
FilePath projectPath = FilePath::fromString(project);
QString completeBase = projectPath.completeBaseName();
painter->setPen(textColor);
painter->drawText(x1, yy, completeBase);
yy += 18;
// Project path.
QString pathWithTilde = Utils::withTildeHomePath(QDir::toNativeSeparators(project));
QString pathWithTilde = Utils::withTildeHomePath(projectPath.toUserOutput());
painter->setPen(foregroundColor1);
painter->drawText(x1, yy, fm.elidedText(pathWithTilde, Qt::ElideMiddle, rc.width() - 40));
yy += 22;
@@ -454,7 +454,7 @@ public:
painter->drawPixmap(x + 11, y + 6, projectIcon);
QString projectName = idx.data(Qt::DisplayRole).toString();
QString projectPath = idx.data(ProjectModel::FilePathRole).toString();
FilePath projectPath = FilePath::fromVariant(idx.data(ProjectModel::FilePathRole));
painter->setPen(themeColor(Theme::Welcome_ForegroundSecondaryColor));
painter->setFont(sizedFont(10, option.widget));
@@ -468,7 +468,7 @@ public:
painter->setPen(themeColor(Theme::Welcome_ForegroundPrimaryColor));
painter->setFont(sizedFont(13, option.widget));
QString pathWithTilde = Utils::withTildeHomePath(QDir::toNativeSeparators(projectPath));
QString pathWithTilde = Utils::withTildeHomePath(projectPath.toUserOutput());
painter->drawText(x + 36, secondBase, pathWithTilde);
}

View File

@@ -38,8 +38,8 @@
#include <QTextStream>
#include <QVBoxLayout>
using namespace QmakeProjectManager;
using namespace QmakeProjectManager::Internal;
namespace QmakeProjectManager {
namespace Internal {
const char qt_file_dialog_filter_reg_exp[] =
"^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$";
@@ -79,8 +79,8 @@ static bool validateLibraryPath(const Utils::FilePath &filePath,
return false;
}
AddLibraryWizard::AddLibraryWizard(const QString &fileName, QWidget *parent) :
Utils::Wizard(parent), m_proFile(fileName)
AddLibraryWizard::AddLibraryWizard(const Utils::FilePath &proFile, QWidget *parent) :
Utils::Wizard(parent), m_proFile(proFile)
{
setWindowTitle(tr("Add Library"));
m_libraryTypePage = new LibraryTypePage(this);
@@ -93,7 +93,7 @@ AddLibraryWizard::AddLibraryWizard(const QString &fileName, QWidget *parent) :
AddLibraryWizard::~AddLibraryWizard() = default;
QString AddLibraryWizard::proFile() const
Utils::FilePath AddLibraryWizard::proFile() const
{
return m_proFile;
}
@@ -294,10 +294,9 @@ SummaryPage::SummaryPage(AddLibraryWizard *parent)
void SummaryPage::initializePage()
{
m_snippet = m_libraryWizard->snippet();
QFileInfo fi(m_libraryWizard->proFile());
m_summaryLabel->setText(
tr("The following snippet will be added to the<br><b>%1</b> file:")
.arg(fi.fileName()));
.arg(m_libraryWizard->proFile().fileName()));
QString richSnippet;
{
QTextStream str(&richSnippet);
@@ -316,3 +315,6 @@ QString SummaryPage::snippet() const
{
return m_snippet;
}
} // Internal
} // QmakeProjectManager

View File

@@ -76,20 +76,18 @@ public:
Q_DECLARE_FLAGS(Platforms, Platform)
explicit AddLibraryWizard(const QString &fileName, QWidget *parent = nullptr);
explicit AddLibraryWizard(const Utils::FilePath &proFile, QWidget *parent = nullptr);
~AddLibraryWizard() override;
LibraryKind libraryKind() const;
QString proFile() const;
Utils::FilePath proFile() const;
QString snippet() const;
signals:
private:
LibraryTypePage *m_libraryTypePage = nullptr;
DetailsPage *m_detailsPage = nullptr;
SummaryPage *m_summaryPage = nullptr;
QString m_proFile;
Utils::FilePath m_proFile;
};
class LibraryTypePage : public QWizardPage

View File

@@ -40,22 +40,24 @@
#include <QTextStream>
using namespace ProjectExplorer;
using namespace QmakeProjectManager;
using namespace QmakeProjectManager::Internal;
using namespace Utils;
namespace QmakeProjectManager {
namespace Internal {
static void fillLibraryPlatformTypes(QComboBox *comboBox)
{
comboBox->clear();
comboBox->addItem("Windows (*.lib lib*.a)", int(Utils::OsTypeWindows));
comboBox->addItem("Linux (lib*.so lib*.a)", int(Utils::OsTypeLinux));
comboBox->addItem("macOS (*.dylib *.a *.framework)", int(Utils::OsTypeMac));
const int currentIndex = comboBox->findData(int(Utils::HostOsInfo::hostOs()));
comboBox->addItem("Windows (*.lib lib*.a)", int(OsTypeWindows));
comboBox->addItem("Linux (lib*.so lib*.a)", int(OsTypeLinux));
comboBox->addItem("macOS (*.dylib *.a *.framework)", int(OsTypeMac));
const int currentIndex = comboBox->findData(int(HostOsInfo::hostOs()));
comboBox->setCurrentIndex(std::max(0, currentIndex));
}
LibraryDetailsController::LibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent) :
const FilePath &proFile, QObject *parent) :
QObject(parent),
m_proFile(proFile),
m_libraryDetailsWidget(libraryDetails)
@@ -65,12 +67,12 @@ LibraryDetailsController::LibraryDetailsController(
setLinkageGroupVisible(true);
setMacLibraryGroupVisible(true);
setPackageLineEditVisible(false);
const bool isMacOs = libraryPlatformType() == Utils::OsTypeMac;
const bool isWindows = libraryPlatformType() == Utils::OsTypeWindows;
const bool isMacOs = libraryPlatformType() == OsTypeMac;
const bool isWindows = libraryPlatformType() == OsTypeWindows;
setMacLibraryRadiosVisible(!isMacOs);
setLinkageRadiosVisible(isWindows);
connect(m_libraryDetailsWidget->includePathChooser, &Utils::PathChooser::rawPathChanged,
connect(m_libraryDetailsWidget->includePathChooser, &PathChooser::rawPathChanged,
this, &LibraryDetailsController::slotIncludePathChanged);
connect(m_libraryDetailsWidget->frameworkRadio, &QAbstractButton::clicked,
this, &LibraryDetailsController::slotMacLibraryTypeChanged);
@@ -108,9 +110,9 @@ AddLibraryWizard::MacLibraryType LibraryDetailsController::macLibraryType() cons
return m_macLibraryType;
}
Utils::OsType LibraryDetailsController::libraryPlatformType() const
OsType LibraryDetailsController::libraryPlatformType() const
{
return Utils::OsType(m_libraryDetailsWidget->libraryTypeComboBox->currentData().value<int>());
return OsType(m_libraryDetailsWidget->libraryTypeComboBox->currentData().value<int>());
}
QString LibraryDetailsController::libraryPlatformFilter() const
@@ -198,7 +200,7 @@ void LibraryDetailsController::updateGui()
// UGLY HACK END
}
QString LibraryDetailsController::proFile() const
FilePath LibraryDetailsController::proFile() const
{
return m_proFile;
}
@@ -397,7 +399,7 @@ static QString smartQuote(const QString &aString)
{
// The OS type is not important in that case, but use always the same
// in order not to generate different quoting depending on host platform
return Utils::ProcessArgs::quoteArg(aString, Utils::OsTypeLinux);
return ProcessArgs::quoteArg(aString, OsTypeLinux);
}
static QString appendSeparator(const QString &aString)
@@ -622,15 +624,15 @@ static QString generatePreTargetDepsSnippet(AddLibraryWizard::Platforms platform
NonInternalLibraryDetailsController::NonInternalLibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent) :
const FilePath &proFile, QObject *parent) :
LibraryDetailsController(libraryDetails, proFile, parent)
{
setLibraryComboBoxVisible(false);
setLibraryPathChooserVisible(true);
connect(libraryDetailsWidget()->libraryPathChooser, &Utils::PathChooser::validChanged,
connect(libraryDetailsWidget()->libraryPathChooser, &PathChooser::validChanged,
this, &LibraryDetailsController::completeChanged);
connect(libraryDetailsWidget()->libraryPathChooser, &Utils::PathChooser::rawPathChanged,
connect(libraryDetailsWidget()->libraryPathChooser, &PathChooser::rawPathChanged,
this, &NonInternalLibraryDetailsController::slotLibraryPathChanged);
connect(libraryDetailsWidget()->removeSuffixCheckBox, &QAbstractButton::toggled,
this, &NonInternalLibraryDetailsController::slotRemoveSuffixChanged);
@@ -646,7 +648,7 @@ NonInternalLibraryDetailsController::NonInternalLibraryDetailsController(
AddLibraryWizard::LinkageType NonInternalLibraryDetailsController::suggestedLinkageType() const
{
AddLibraryWizard::LinkageType type = AddLibraryWizard::NoLinkage;
if (libraryPlatformType() != Utils::OsTypeWindows) {
if (libraryPlatformType() != OsTypeWindows) {
if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
if (fi.suffix() == QLatin1String("a"))
@@ -661,7 +663,7 @@ AddLibraryWizard::LinkageType NonInternalLibraryDetailsController::suggestedLink
AddLibraryWizard::MacLibraryType NonInternalLibraryDetailsController::suggestedMacLibraryType() const
{
AddLibraryWizard::MacLibraryType type = AddLibraryWizard::NoLibraryType;
if (libraryPlatformType() == Utils::OsTypeMac) {
if (libraryPlatformType() == OsTypeMac) {
if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
if (fi.suffix() == QLatin1String("framework"))
@@ -695,7 +697,7 @@ QString NonInternalLibraryDetailsController::suggestedIncludePath() const
void NonInternalLibraryDetailsController::updateWindowsOptionsEnablement()
{
bool ena = platforms() & (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform);
if (libraryPlatformType() == Utils::OsTypeWindows) {
if (libraryPlatformType() == OsTypeWindows) {
libraryDetailsWidget()->addSuffixCheckBox->setEnabled(ena);
ena = true;
}
@@ -732,10 +734,10 @@ void NonInternalLibraryDetailsController::slotRemoveSuffixChanged(bool ena)
void NonInternalLibraryDetailsController::handleLibraryTypeChange()
{
libraryDetailsWidget()->libraryPathChooser->setPromptDialogFilter(libraryPlatformFilter());
const bool isMacOs = libraryPlatformType() == Utils::OsTypeMac;
const bool isWindows = libraryPlatformType() == Utils::OsTypeWindows;
libraryDetailsWidget()->libraryPathChooser->setExpectedKind(isMacOs ? Utils::PathChooser::Any
: Utils::PathChooser::File);
const bool isMacOs = libraryPlatformType() == OsTypeMac;
const bool isWindows = libraryPlatformType() == OsTypeWindows;
libraryDetailsWidget()->libraryPathChooser->setExpectedKind(isMacOs ? PathChooser::Any
: PathChooser::File);
setMacLibraryRadiosVisible(!isMacOs);
setLinkageRadiosVisible(isWindows);
setRemoveSuffixVisible(isWindows);
@@ -752,7 +754,7 @@ void NonInternalLibraryDetailsController::slotLibraryTypeChanged()
void NonInternalLibraryDetailsController::handleLibraryPathChange()
{
if (libraryPlatformType() == Utils::OsTypeWindows) {
if (libraryPlatformType() == OsTypeWindows) {
bool subfoldersEnabled = true;
bool removeSuffixEnabled = true;
if (libraryDetailsWidget()->libraryPathChooser->isValid()) {
@@ -797,13 +799,13 @@ QString NonInternalLibraryDetailsController::snippet() const
QString libName;
const bool removeSuffix = isWindowsGroupVisible()
&& libraryDetailsWidget()->removeSuffixCheckBox->isChecked();
if (libraryPlatformType() == Utils::OsTypeWindows) {
if (libraryPlatformType() == OsTypeWindows) {
libName = fi.completeBaseName();
if (removeSuffix && !libName.isEmpty()) // remove last letter which needs to be "d"
libName = libName.left(libName.size() - 1);
if (fi.completeSuffix() == QLatin1String("a")) // the mingw lib case
libName = libName.mid(3); // cut the "lib" prefix
} else if (libraryPlatformType() == Utils::OsTypeMac) {
} else if (libraryPlatformType() == OsTypeMac) {
if (macLibraryType() == AddLibraryWizard::FrameworkType)
libName = fi.completeBaseName();
else
@@ -817,7 +819,7 @@ QString NonInternalLibraryDetailsController::snippet() const
if (isWindowsGroupVisible()) {
// when we are on Win but we don't generate the code for Win
// we still need to remove "debug" or "release" subfolder
const bool useSubfoldersCondition = (libraryPlatformType() == Utils::OsTypeWindows)
const bool useSubfoldersCondition = (libraryPlatformType() == OsTypeWindows)
? true : platforms() & (AddLibraryWizard::WindowsMinGWPlatform
| AddLibraryWizard::WindowsMSVCPlatform);
if (useSubfoldersCondition)
@@ -829,10 +831,10 @@ QString NonInternalLibraryDetailsController::snippet() const
QString targetRelativePath;
QString includeRelativePath;
if (isIncludePathVisible()) { // generate also the path to lib
QFileInfo pfi(proFile());
QFileInfo pfi = proFile().toFileInfo();
QDir pdir = pfi.absoluteDir();
QString absoluteLibraryPath = fi.absolutePath();
if (libraryPlatformType() == Utils::OsTypeWindows && useSubfolders) { // drop last subfolder which needs to be "debug" or "release"
if (libraryPlatformType() == OsTypeWindows && useSubfolders) { // drop last subfolder which needs to be "debug" or "release"
QFileInfo libfi(absoluteLibraryPath);
absoluteLibraryPath = libfi.absolutePath();
}
@@ -862,7 +864,7 @@ QString NonInternalLibraryDetailsController::snippet() const
PackageLibraryDetailsController::PackageLibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent)
const FilePath &proFile, QObject *parent)
: NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
{
setPlatformsVisible(false);
@@ -897,11 +899,11 @@ QString PackageLibraryDetailsController::snippet() const
bool PackageLibraryDetailsController::isLinkPackageGenerated() const
{
const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(proFile()));
const Project *project = SessionManager::projectForFile(proFile());
if (!project)
return false;
const ProjectNode *projectNode = project->findNodeForBuildKey(proFile());
const ProjectNode *projectNode = project->findNodeForBuildKey(proFile().toString());
if (!projectNode)
return false;
@@ -921,7 +923,7 @@ bool PackageLibraryDetailsController::isLinkPackageGenerated() const
SystemLibraryDetailsController::SystemLibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent)
const FilePath &proFile, QObject *parent)
: NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
{
setIncludePathVisible(false);
@@ -934,7 +936,7 @@ SystemLibraryDetailsController::SystemLibraryDetailsController(
ExternalLibraryDetailsController::ExternalLibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent)
const FilePath &proFile, QObject *parent)
: NonInternalLibraryDetailsController(libraryDetails, proFile, parent)
{
setIncludePathVisible(true);
@@ -949,7 +951,7 @@ void ExternalLibraryDetailsController::updateWindowsOptionsEnablement()
bool subfoldersEnabled = true;
bool removeSuffixEnabled = true;
if (libraryPlatformType() == Utils::OsTypeWindows
if (libraryPlatformType() == OsTypeWindows
&& libraryDetailsWidget()->libraryPathChooser->isValid()) {
QFileInfo fi(libraryDetailsWidget()->libraryPathChooser->filePath().toString());
QFileInfo dfi(fi.absolutePath());
@@ -968,9 +970,8 @@ void ExternalLibraryDetailsController::updateWindowsOptionsEnablement()
/////////////
InternalLibraryDetailsController::InternalLibraryDetailsController(
Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile, QObject *parent)
InternalLibraryDetailsController::InternalLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const FilePath &proFile, QObject *parent)
: LibraryDetailsController(libraryDetails, proFile, parent)
{
setLinkageRadiosVisible(false);
@@ -980,7 +981,7 @@ InternalLibraryDetailsController::InternalLibraryDetailsController(
setWindowsGroupVisible(true);
setRemoveSuffixVisible(false);
if (Utils::HostOsInfo::isWindowsHost())
if (HostOsInfo::isWindowsHost())
libraryDetailsWidget()->useSubfoldersCheckBox->setEnabled(true);
connect(libraryDetailsWidget()->libraryComboBox,
@@ -1034,7 +1035,7 @@ QString InternalLibraryDetailsController::suggestedIncludePath() const
void InternalLibraryDetailsController::updateWindowsOptionsEnablement()
{
if (Utils::HostOsInfo::isWindowsHost())
if (HostOsInfo::isWindowsHost())
libraryDetailsWidget()->addSuffixCheckBox->setEnabled(true);
libraryDetailsWidget()->winGroupBox->setEnabled(platforms()
& (AddLibraryWizard::WindowsMinGWPlatform | AddLibraryWizard::WindowsMSVCPlatform));
@@ -1047,7 +1048,7 @@ void InternalLibraryDetailsController::updateProFile()
libraryDetailsWidget()->libraryComboBox->clear();
const QmakeProject *project
= dynamic_cast<QmakeProject *>(SessionManager::projectForFile(Utils::FilePath::fromString(proFile())));
= dynamic_cast<QmakeProject *>(SessionManager::projectForFile(proFile()));
if (!project)
return;
@@ -1091,7 +1092,7 @@ void InternalLibraryDetailsController::slotCurrentLibraryChanged()
currentIndex, Qt::ToolTipRole).toString());
QmakeProFile *proFile = m_proFiles.at(currentIndex);
const QStringList configVar = proFile->variableValue(Variable::Config);
if (Utils::HostOsInfo::isWindowsHost()) {
if (HostOsInfo::isWindowsHost()) {
bool useSubfolders = false;
if (configVar.contains(QLatin1String("debug_and_release"))
&& configVar.contains(QLatin1String("debug_and_release_target")))
@@ -1130,10 +1131,10 @@ QString InternalLibraryDetailsController::snippet() const
// relative path for the project for which we insert the snippet,
// it's relative to the root project
const QString proRelavitePath = rootDir.relativeFilePath(proFile());
const QString proRelavitePath = rootDir.relativeFilePath(proFile().toString());
// project for which we insert the snippet
const Project *project = SessionManager::projectForFile(Utils::FilePath::fromString(proFile()));
const Project *project = SessionManager::projectForFile(proFile());
// the build directory of the active build configuration
QDir rootBuildDir = rootDir; // If the project is unconfigured use the project dir
@@ -1147,7 +1148,7 @@ QString InternalLibraryDetailsController::snippet() const
QDir projectBuildDir(pfi.absolutePath());
// current project node from combobox
QFileInfo fi(proFile());
QFileInfo fi = proFile().toFileInfo();
QDir projectSrcDir(fi.absolutePath());
// project node which we want to link against
@@ -1175,3 +1176,6 @@ QString InternalLibraryDetailsController::snippet() const
useSubfolders, addSuffix);
return snippetMessage;
}
} // Internal
} // QmakeProjectManager

View File

@@ -38,7 +38,7 @@ class LibraryDetailsController : public QObject
Q_OBJECT
public:
explicit LibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile,
const Utils::FilePath &proFile,
QObject *parent = nullptr);
virtual bool isComplete() const = 0;
virtual QString snippet() const = 0;
@@ -54,7 +54,7 @@ protected:
AddLibraryWizard::MacLibraryType macLibraryType() const;
Utils::OsType libraryPlatformType() const;
QString libraryPlatformFilter() const;
QString proFile() const;
Utils::FilePath proFile() const;
bool isIncludePathChanged() const;
bool guiSignalsIgnored() const;
@@ -99,7 +99,7 @@ private:
AddLibraryWizard::LinkageType m_linkageType = AddLibraryWizard::NoLinkage;
AddLibraryWizard::MacLibraryType m_macLibraryType = AddLibraryWizard::NoLibraryType;
QString m_proFile;
Utils::FilePath m_proFile;
bool m_ignoreGuiSignals = false;
bool m_includePathChanged = false;
@@ -118,7 +118,7 @@ class NonInternalLibraryDetailsController : public LibraryDetailsController
Q_OBJECT
public:
explicit NonInternalLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile,
const Utils::FilePath &proFile,
QObject *parent = nullptr);
bool isComplete() const override;
QString snippet() const override;
@@ -143,7 +143,7 @@ class PackageLibraryDetailsController : public NonInternalLibraryDetailsControll
Q_OBJECT
public:
explicit PackageLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile,
const Utils::FilePath &proFile,
QObject *parent = nullptr);
bool isComplete() const override;
QString snippet() const override;
@@ -160,7 +160,7 @@ class SystemLibraryDetailsController : public NonInternalLibraryDetailsControlle
Q_OBJECT
public:
explicit SystemLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile,
const Utils::FilePath &proFile,
QObject *parent = nullptr);
protected:
void updateWindowsOptionsEnablement() override final {
@@ -173,7 +173,7 @@ class ExternalLibraryDetailsController : public NonInternalLibraryDetailsControl
Q_OBJECT
public:
explicit ExternalLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile,
const Utils::FilePath &proFile,
QObject *parent = nullptr);
protected:
void updateWindowsOptionsEnablement() override final;
@@ -184,7 +184,7 @@ class InternalLibraryDetailsController : public LibraryDetailsController
Q_OBJECT
public:
explicit InternalLibraryDetailsController(Ui::LibraryDetailsWidget *libraryDetails,
const QString &proFile,
const Utils::FilePath &proFile,
QObject *parent = nullptr);
bool isComplete() const override;
QString snippet() const override;

View File

@@ -73,6 +73,7 @@
using namespace Core;
using namespace ProjectExplorer;
using namespace TextEditor;
using namespace Utils;
namespace QmakeProjectManager {
namespace Internal {
@@ -90,7 +91,7 @@ public:
void buildStateChanged(Project *pro);
void updateBuildFileAction();
void disableBuildFileMenus();
void enableBuildFileMenus(const Utils::FilePath &file);
void enableBuildFileMenus(const FilePath &file);
Core::Context projectContext;
@@ -114,15 +115,15 @@ public:
QAction *m_runQMakeAction = nullptr;
QAction *m_runQMakeActionContextMenu = nullptr;
Utils::ParameterAction *m_buildSubProjectContextMenu = nullptr;
ParameterAction *m_buildSubProjectContextMenu = nullptr;
QAction *m_subProjectRebuildSeparator = nullptr;
QAction *m_rebuildSubProjectContextMenu = nullptr;
QAction *m_cleanSubProjectContextMenu = nullptr;
QAction *m_buildFileContextMenu = nullptr;
Utils::ParameterAction *m_buildSubProjectAction = nullptr;
ParameterAction *m_buildSubProjectAction = nullptr;
QAction *m_rebuildSubProjectAction = nullptr;
QAction *m_cleanSubProjectAction = nullptr;
Utils::ParameterAction *m_buildFileAction = nullptr;
ParameterAction *m_buildFileAction = nullptr;
QAction *m_addLibraryAction = nullptr;
QAction *m_addLibraryActionContextMenu = nullptr;
@@ -140,7 +141,7 @@ public:
void buildFile();
void handleSubDirContextMenu(QmakeBuildSystem::Action action, bool isFileBuild);
void addLibraryImpl(const QString &fileName, TextEditor::BaseTextEditor *editor);
void addLibraryImpl(const FilePath &filePath, TextEditor::BaseTextEditor *editor);
void runQMakeImpl(Project *p, ProjectExplorer::Node *node);
};
@@ -181,8 +182,8 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString
//register actions
Command *command = nullptr;
d->m_buildSubProjectContextMenu = new Utils::ParameterAction(tr("Build"), tr("Build \"%1\""),
Utils::ParameterAction::AlwaysEnabled/*handled manually*/,
d->m_buildSubProjectContextMenu = new ParameterAction(tr("Build"), tr("Build \"%1\""),
ParameterAction::AlwaysEnabled/*handled manually*/,
this);
command = ActionManager::registerAction(d->m_buildSubProjectContextMenu, Constants::BUILDSUBDIRCONTEXTMENU, projectContext);
command->setAttribute(Command::CA_Hide);
@@ -227,8 +228,8 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString
connect(d->m_buildFileContextMenu, &QAction::triggered,
d, &QmakeProjectManagerPluginPrivate::buildFileContextMenu);
d->m_buildSubProjectAction = new Utils::ParameterAction(tr("Build &Subproject"), tr("Build &Subproject \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
d->m_buildSubProjectAction = new ParameterAction(tr("Build &Subproject"), tr("Build &Subproject \"%1\""),
ParameterAction::AlwaysEnabled, this);
command = ActionManager::registerAction(d->m_buildSubProjectAction, Constants::BUILDSUBDIR, projectContext);
command->setAttribute(Command::CA_Hide);
command->setAttribute(Command::CA_UpdateText);
@@ -244,8 +245,7 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString
connect(d->m_runQMakeAction, &QAction::triggered,
d, &QmakeProjectManagerPluginPrivate::runQMake);
d->m_rebuildSubProjectAction = new QAction(Icons::REBUILD.icon(), tr("Rebuild"),
this);
d->m_rebuildSubProjectAction = new QAction(ProjectExplorer::Icons::REBUILD.icon(), tr("Rebuild"), this);
d->m_rebuildSubProjectAction->setWhatsThis(tr("Rebuild Subproject"));
command = ActionManager::registerAction(d->m_rebuildSubProjectAction, Constants::REBUILDSUBDIR, projectContext);
command->setAttribute(Command::CA_Hide);
@@ -265,8 +265,8 @@ bool QmakeProjectManagerPlugin::initialize(const QStringList &arguments, QString
connect(d->m_cleanSubProjectAction, &QAction::triggered,
d, &QmakeProjectManagerPluginPrivate::cleanSubDirContextMenu);
d->m_buildFileAction = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""),
Utils::ParameterAction::AlwaysEnabled, this);
d->m_buildFileAction = new ParameterAction(tr("Build File"), tr("Build File \"%1\""),
ParameterAction::AlwaysEnabled, this);
command = ActionManager::registerAction(d->m_buildFileAction, Constants::BUILDFILE, projectContext);
command->setAttribute(Command::CA_Hide);
command->setAttribute(Command::CA_UpdateText);
@@ -361,33 +361,33 @@ static QmakeProFileNode *buildableFileProFile(Node *node)
void QmakeProjectManagerPluginPrivate::addLibrary()
{
if (auto editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::currentEditor()))
addLibraryImpl(editor->document()->filePath().toString(), editor);
addLibraryImpl(editor->document()->filePath(), editor);
}
void QmakeProjectManagerPluginPrivate::addLibraryContextMenu()
{
QString projectPath;
FilePath projectPath;
Node *node = ProjectTree::currentNode();
if (ContainerNode *cn = node->asContainerNode())
projectPath = cn->project()->projectFilePath().toString();
projectPath = cn->project()->projectFilePath();
else if (dynamic_cast<QmakeProFileNode *>(node))
projectPath = node->filePath().toString();
projectPath = node->filePath();
addLibraryImpl(projectPath, nullptr);
}
void QmakeProjectManagerPluginPrivate::addLibraryImpl(const QString &fileName, BaseTextEditor *editor)
void QmakeProjectManagerPluginPrivate::addLibraryImpl(const FilePath &filePath, BaseTextEditor *editor)
{
if (fileName.isEmpty())
if (filePath.isEmpty())
return;
Internal::AddLibraryWizard wizard(fileName, Core::ICore::dialogParent());
Internal::AddLibraryWizard wizard(filePath, Core::ICore::dialogParent());
if (wizard.exec() != QDialog::Accepted)
return;
if (!editor)
editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::openEditor(fileName,
editor = qobject_cast<BaseTextEditor *>(Core::EditorManager::openEditor(filePath,
Constants::PROFILE_EDITOR_ID, Core::EditorManager::DoNotMakeVisible));
if (!editor)
return;
@@ -448,7 +448,7 @@ void QmakeProjectManagerPluginPrivate::buildFile()
if (!currentDocument)
return;
const Utils::FilePath file = currentDocument->filePath();
const FilePath file = currentDocument->filePath();
Node *n = ProjectTree::nodeForFile(file);
FileNode *node = n ? n->asFileNode() : nullptr;
if (!node)
@@ -599,7 +599,7 @@ void QmakeProjectManagerPluginPrivate::disableBuildFileMenus()
m_buildFileContextMenu->setEnabled(false);
}
void QmakeProjectManagerPluginPrivate::enableBuildFileMenus(const Utils::FilePath &file)
void QmakeProjectManagerPluginPrivate::enableBuildFileMenus(const FilePath &file)
{
bool visible = false;
bool enabled = false;

View File

@@ -58,6 +58,7 @@
#include <QGraphicsLinearLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QMimeData>
#include <exception>
@@ -241,6 +242,56 @@ ModelNodePreviewImageOperation DesignerActionManager::modelNodePreviewOperation(
return op;
}
bool DesignerActionManager::externalDragHasSupportedAssets(const QMimeData *mimeData) const
{
if (!mimeData->hasUrls())
return false;
QSet<QString> filtersSet;
const QList<AddResourceHandler> handlers = addResourceHandler();
for (const AddResourceHandler &handler : handlers)
filtersSet.insert(handler.filter);
const QList<QUrl> urls = mimeData->urls();
for (const QUrl &url : urls) {
QString suffix = "*." + url.fileName().split('.').last().toLower();
if (filtersSet.contains(suffix)) // accept drop if it contains a valid file
return true;
}
return false;
}
void DesignerActionManager::handleExternalAssetsDrop(const QMimeData *mimeData) const
{
const QList<AddResourceHandler> handlers = addResourceHandler();
// create suffix to categry and category to operation hashes
QHash<QString, QString> suffixCategory;
QHash<QString, AddResourceOperation> categoryOperation;
for (const AddResourceHandler &handler : handlers) {
suffixCategory.insert(handler.filter, handler.category);
categoryOperation.insert(handler.category, handler.operation);
}
// add files grouped by categories (so that files under same category run under 1 operation)
QHash<QString, QStringList> categoryFiles;
const QList<QUrl> urls = mimeData->urls();
for (const QUrl &url : urls) {
QString suffix = "*." + url.fileName().split('.').last().toLower();
QString category = suffixCategory.value(suffix);
if (!category.isEmpty())
categoryFiles[category].append(url.toLocalFile());
}
// run operations
const QStringList categories = categoryFiles.keys();
for (const QString &category : categories) {
AddResourceOperation operation = categoryOperation.value(category);
QStringList files = categoryFiles.value(category);
operation(files, {});
}
}
class VisiblityModelNodeAction : public ModelNodeContextMenuAction
{
public:

View File

@@ -38,6 +38,7 @@
QT_BEGIN_NAMESPACE
class QGraphicsItem;
class QGraphicsWidget;
class QMimeData;
QT_END_NAMESPACE
namespace QmlDesigner {
@@ -135,6 +136,8 @@ public:
void registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler);
bool hasModelNodePreviewHandler(const ModelNode &node) const;
ModelNodePreviewImageOperation modelNodePreviewOperation(const ModelNode &node) const;
bool externalDragHasSupportedAssets(const QMimeData *data) const;
void handleExternalAssetsDrop(const QMimeData *data) const;
private:
void addTransitionEffectAction(const TypeName &typeName);

View File

@@ -81,6 +81,18 @@ void CurveEditor::clearCanvas()
m_view->reset({});
}
void CurveEditor::showEvent(QShowEvent *event)
{
emit viewEnabledChanged(true);
QWidget::showEvent(event);
}
void CurveEditor::hideEvent(QHideEvent *event)
{
emit viewEnabledChanged(false);
QWidget::hideEvent(event);
}
QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
{
auto *bar = new QToolBar;

View File

@@ -49,6 +49,13 @@ public:
void clearCanvas();
signals:
void viewEnabledChanged(const bool);
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
private:
QToolBar *createToolBar(CurveEditorModel *model);

View File

@@ -51,6 +51,13 @@ CurveEditorView::CurveEditorView(QObject *parent)
connect(m_model, &CurveEditorModel::commitStartFrame, this, &CurveEditorView::commitStartFrame);
connect(m_model, &CurveEditorModel::commitEndFrame, this, &CurveEditorView::commitEndFrame);
connect(m_model, &CurveEditorModel::curveChanged, this, &CurveEditorView::commitKeyframes);
connect(m_editor, &CurveEditor::viewEnabledChanged, this, [this](bool enabled){
setEnabled(enabled);
if (enabled)
init();
});
setEnabled(false);
}
CurveEditorView::~CurveEditorView() {}
@@ -70,10 +77,8 @@ void CurveEditorView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
QmlTimeline timeline = activeTimeline();
if (timeline.isValid()) {
m_model->setTimeline(timeline);
}
if (isEnabled())
init();
}
void CurveEditorView::modelAboutToBeDetached(Model *model)
@@ -389,4 +394,13 @@ void CurveEditorView::commitEndFrame(int frame)
timeline.modelNode().variantProperty("endFrame").setValue(frame);
}
void CurveEditorView::init()
{
QmlTimeline timeline = activeTimeline();
if (timeline.isValid()) {
m_model->setTimeline(timeline);
}
}
} // namespace QmlDesigner

View File

@@ -85,6 +85,7 @@ private:
void commitCurrentFrame(int frame);
void commitStartFrame(int frame);
void commitEndFrame(int frame);
void init();
private:
bool m_block;

View File

@@ -40,6 +40,7 @@
#include <utils/utilsicons.h>
#include <QActionGroup>
#include <QMimeData>
#include <QVBoxLayout>
namespace QmlDesigner {
@@ -47,6 +48,8 @@ namespace QmlDesigner {
Edit3DWidget::Edit3DWidget(Edit3DView *view) :
m_view(view)
{
setAcceptDrops(true);
Core::Context context(Constants::C_QMLEDITOR3D);
m_context = new Core::IContext(this);
m_context->setContext(context);
@@ -159,4 +162,19 @@ Edit3DView *Edit3DWidget::view() const
return m_view.data();
}
void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
dragEnterEvent->acceptProposedAction();
}
void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
}
} // namespace QmlDesigner

View File

@@ -48,6 +48,10 @@ public:
void showCanvas(bool show);
protected:
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private:
void linkActivated(const QString &link);

View File

@@ -53,6 +53,7 @@
#include <QActionGroup>
#include <QFileDialog>
#include <QMimeData>
#include <QPainter>
#include <QPicture>
#include <QVBoxLayout>
@@ -63,6 +64,8 @@ namespace QmlDesigner {
FormEditorWidget::FormEditorWidget(FormEditorView *view)
: m_formEditorView(view)
{
setAcceptDrops(true);
Core::Context context(Constants::C_QMLFORMEDITOR);
m_context = new Core::IContext(this);
m_context->setContext(context);
@@ -582,4 +585,19 @@ void FormEditorWidget::showEvent(QShowEvent *event)
}
}
void FormEditorWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
dragEnterEvent->acceptProposedAction();
}
void FormEditorWidget::dropEvent(QDropEvent *dropEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
}
} // namespace QmlDesigner

View File

@@ -49,6 +49,7 @@ class QmlItemNode;
class FormEditorWidget : public QWidget
{
Q_OBJECT
public:
FormEditorWidget(FormEditorView *view);
@@ -93,6 +94,8 @@ protected:
DocumentWarningWidget *errorWidget();
void hideEvent(QHideEvent *event) override;
void showEvent(QShowEvent *event) override;
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private:
void changeTransformTool(bool checked);

View File

@@ -144,6 +144,17 @@ void ItemLibraryCategoriesModel::resetModel()
endResetModel();
}
bool ItemLibraryCategoriesModel::isAllCategoriesHidden() const
{
for (const auto &category : std::as_const(m_categoryList)) {
// ignore "All Other Components" as its categoryVisible is always true
if (category->isCategoryVisible() && category->categoryName() != "All Other Components")
return false;
}
return true;
}
void ItemLibraryCategoriesModel::showAllCategories(bool show)
{
for (const auto &category : std::as_const(m_categoryList)) {
@@ -153,9 +164,43 @@ void ItemLibraryCategoriesModel::showAllCategories(bool show)
category->ownerImport()->importName());
}
}
emit dataChanged(index(0), index(m_categoryList.size() - 1), {m_roleNames.key("categoryVisible")});
}
QObject *ItemLibraryCategoriesModel::selectFirstVisibleCategory()
{
for (int i = 0; i < m_categoryList.length(); ++i) {
const auto category = m_categoryList.at(i);
if (category->isCategoryVisible()) {
category->setCategorySelected(true);
emit dataChanged(index(i),index(i), {m_roleNames.key("categorySelected")});
return category;
}
}
return nullptr;
}
void ItemLibraryCategoriesModel::clearSelectedCategories()
{
for (const auto &category : std::as_const(m_categoryList))
category->setCategorySelected(false);
emit dataChanged(index(0), index(m_categoryList.size() - 1), {m_roleNames.key("categorySelected")});
}
void ItemLibraryCategoriesModel::selectCategory(int categoryIndex)
{
const auto category = m_categoryList.at(categoryIndex);
if (!category->categorySelected()) {
clearSelectedCategories();
category->setCategorySelected(true);
emit dataChanged(index(categoryIndex),index(categoryIndex), {m_roleNames.key("categorySelected")});
}
}
void ItemLibraryCategoriesModel::addRoleNames()
{
int role = 0;

View File

@@ -52,9 +52,13 @@ public:
const QList<QPointer<ItemLibraryCategory>> &categorySections() const;
bool isAllCategoriesHidden() const;
void sortCategorySections();
void resetModel();
void showAllCategories(bool show = true);
void clearSelectedCategories();
QObject *selectFirstVisibleCategory();
void selectCategory(int categoryIndex);
private:
void addRoleNames();

View File

@@ -26,6 +26,7 @@
#include "itemlibrarycategory.h"
#include "itemlibraryitem.h"
#include "itemlibrarywidget.h"
namespace QmlDesigner {
@@ -46,6 +47,11 @@ bool ItemLibraryCategory::categoryExpanded() const
return m_categoryExpanded;
}
bool ItemLibraryCategory::categorySelected() const
{
return m_categorySelected;
}
QString ItemLibraryCategory::sortingName() const
{
if (ItemLibraryModel::categorySortingHash.contains(categoryName()))
@@ -84,6 +90,10 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
hasVisibleItems = true;
}
// update item model in horizontal view so search text matches item grid
if (ItemLibraryWidget::isHorizontalLayout)
m_itemModel.resetModel();
// expand category if it has an item matching search criteria
if (!searchText.isEmpty() && hasVisibleItems && !categoryExpanded())
setExpanded(true);
@@ -124,4 +134,9 @@ void ItemLibraryCategory::setExpanded(bool expanded)
m_categoryExpanded = expanded;
}
void ItemLibraryCategory::setCategorySelected(bool selected)
{
m_categorySelected = selected;
}
} // namespace QmlDesigner

View File

@@ -39,6 +39,7 @@ class ItemLibraryCategory : public QObject
Q_PROPERTY(QString categoryName READ categoryName FINAL)
Q_PROPERTY(bool categoryVisible READ isCategoryVisible WRITE setCategoryVisible NOTIFY categoryVisibilityChanged FINAL)
Q_PROPERTY(bool categoryExpanded READ categoryExpanded WRITE setExpanded NOTIFY expandedChanged FINAL)
Q_PROPERTY(bool categorySelected READ categorySelected WRITE setCategorySelected NOTIFY categorySelectedChanged FINAL)
Q_PROPERTY(QObject *itemModel READ itemModel NOTIFY itemModelChanged FINAL)
public:
@@ -46,6 +47,7 @@ public:
QString categoryName() const;
bool categoryExpanded() const;
bool categorySelected() const;
QString sortingName() const;
void addItem(ItemLibraryItem *item);
@@ -60,6 +62,7 @@ public:
void sortItems();
void setExpanded(bool expanded);
void setCategorySelected(bool selected);
ItemLibraryImport *ownerImport() const { return m_ownerImport; }
@@ -68,6 +71,7 @@ signals:
void visibilityChanged();
void expandedChanged();
void categoryVisibilityChanged();
void categorySelectedChanged();
private:
ItemLibraryItemsModel m_itemModel;
@@ -75,6 +79,7 @@ private:
QString m_name;
bool m_categoryExpanded = true;
bool m_isVisible = true;
bool m_categorySelected = false;
};
} // namespace QmlDesigner

View File

@@ -138,6 +138,26 @@ void ItemLibraryImport::showAllCategories(bool show)
m_categoryModel.showAllCategories(show);
}
void ItemLibraryImport::selectCategory(int categoryIndex)
{
m_categoryModel.selectCategory(categoryIndex);
}
QObject *ItemLibraryImport::selectFirstVisibleCategory()
{
return m_categoryModel.selectFirstVisibleCategory();
}
void ItemLibraryImport::clearSelectedCategories()
{
m_categoryModel.clearSelectedCategories();
}
bool ItemLibraryImport::isAllCategoriesHidden() const
{
return m_categoryModel.isAllCategoriesHidden();
}
Import ItemLibraryImport::importEntry() const
{
return m_import;

View File

@@ -68,6 +68,7 @@ public:
bool importCatVisibleState() const;
bool hasCategories() const;
bool hasSingleCategory() const;
bool isAllCategoriesHidden() const;
ItemLibraryCategory *getCategorySection(const QString &categoryName) const;
void addCategory(ItemLibraryCategory *category);
@@ -80,6 +81,9 @@ public:
void setImportCatVisibleState(bool show);
void expandCategories(bool expand = true);
void showAllCategories(bool show = true);
void selectCategory(int categoryIndex);
QObject *selectFirstVisibleCategory();
void clearSelectedCategories();
static QString userComponentsTitle();
static QString quick3DAssetsTitle();

View File

@@ -90,6 +90,40 @@ bool ItemLibraryModel::getIsAnyCategoryHidden() const
return false;
}
void ItemLibraryModel::selectImportCategory(const QString importUrl, int categoryIndex)
{
ItemLibraryImport *selectedCategoryImport = importByUrl(importUrl);
for (int i = 0; i < m_importList.length(); ++i) {
const auto importToSelect = m_importList.at(i);
if (selectedCategoryImport == importToSelect)
importToSelect->selectCategory(categoryIndex);
else
importToSelect->clearSelectedCategories();
}
}
bool ItemLibraryModel::isAllCategoriesHidden() const
{
for (int i = 0; i < m_importList.length(); ++i) {
if (!m_importList.at(i)->isAllCategoriesHidden())
return false;
}
return true;
}
QObject *ItemLibraryModel::selectImportFirstVisibleCategory()
{
for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) {
if (!import->isAllCategoriesHidden())
return import->selectFirstVisibleCategory();
}
return nullptr;
}
bool ItemLibraryModel::isAnyCategoryHidden() const
{
return m_isAnyCategoryHidden;

View File

@@ -77,6 +77,9 @@ public:
Q_INVOKABLE void collapseAll();
Q_INVOKABLE void showHiddenCategories();
Q_INVOKABLE bool getIsAnyCategoryHidden() const;
Q_INVOKABLE void selectImportCategory(const QString importUrl, int categoryIndex);
Q_INVOKABLE QObject *selectImportFirstVisibleCategory();
Q_INVOKABLE bool isAllCategoriesHidden() const;
Import entryToImport(const ItemLibraryEntry &entry);

View File

@@ -143,6 +143,11 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
return QObject::eventFilter(obj, event);
}
void ItemLibraryWidget::resizeEvent(QResizeEvent *event)
{
isHorizontalLayout = event->size().width() >= HORIZONTAL_LAYOUT_WIDTH_LIMIT;
}
ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
AsynchronousImageCache &asynchronousFontImageCache,
SynchronousImageCache &synchronousFontImageCache)
@@ -196,6 +201,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache,
{{"itemLibraryIconWidth"}, m_itemIconSize.width()},
{{"itemLibraryIconHeight"}, m_itemIconSize.height()},
{{"rootView"}, QVariant::fromValue(this)},
{{"widthLimit"}, HORIZONTAL_LAYOUT_WIDTH_LIMIT},
{{"highlightColor"}, Utils::StyleHelper::notTooBrightHighlightColor()},
});

View File

@@ -92,6 +92,8 @@ public:
void setFlowMode(bool b);
static QPair<QString, QByteArray> getAssetTypeAndData(const QString &assetPath);
inline static bool isHorizontalLayout = false;
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos);
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
Q_INVOKABLE void removeImport(const QString &importUrl);
@@ -110,6 +112,7 @@ signals:
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private:
void reloadQmlSource();
@@ -149,6 +152,8 @@ private:
bool m_updateRetry = false;
QString m_filterText;
QPoint m_dragStartPoint;
inline static int HORIZONTAL_LAYOUT_WIDTH_LIMIT = 600;
};
} // namespace QmlDesigner

View File

@@ -49,6 +49,8 @@ NavigatorWidget::NavigatorWidget(NavigatorView *view)
: m_treeView(new NavigatorTreeView)
, m_navigatorView(view)
{
setAcceptDrops(true);
m_treeView->setDragEnabled(true);
m_treeView->setAcceptDrops(true);
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
@@ -184,4 +186,19 @@ NavigatorView *NavigatorWidget::navigatorView() const
return m_navigatorView.data();
}
void NavigatorWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
dragEnterEvent->acceptProposedAction();
}
void NavigatorWidget::dropEvent(QDropEvent *dropEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
}
}

View File

@@ -43,6 +43,7 @@ class NavigatorView;
class NavigatorWidget: public QFrame
{
Q_OBJECT
public:
NavigatorWidget(NavigatorView *view);
@@ -63,10 +64,13 @@ signals:
void filterToggled(bool);
void reverseOrderToggled(bool);
private: // functions
protected:
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private:
NavigatorView *navigatorView() const;
private: // variables
NavigatorTreeView *m_treeView;
QPointer<NavigatorView> m_navigatorView;
};

View File

@@ -53,6 +53,8 @@ TextEditorWidget::TextEditorWidget(TextEditorView *textEditorView)
, m_textEditorView(textEditorView)
, m_statusBar(new TextEditorStatusBar(this))
{
setAcceptDrops(true);
QBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
@@ -216,5 +218,19 @@ bool TextEditorWidget::eventFilter( QObject *, QEvent *event)
return false;
}
void TextEditorWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
dragEnterEvent->acceptProposedAction();
}
void TextEditorWidget::dropEvent(QDropEvent *dropEvent)
{
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager();
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
}
} // namespace QmlDesigner

View File

@@ -63,6 +63,8 @@ public:
protected:
bool eventFilter(QObject *object, QEvent *event) override;
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private:
void updateSelectionByCursorPosition();

View File

@@ -71,6 +71,7 @@ TimelineView::TimelineView(QObject *parent)
, m_timelineWidget(nullptr)
{
EasingCurve::registerStreamOperators();
setEnabled(false);
}
TimelineView::~TimelineView() = default;

View File

@@ -606,13 +606,7 @@ void TimelineWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event)
/*
m_timelineView->setEnabled(true);
TODO See QDS-4191
*/
if (m_timelineView->model())
init();
graphicsScene()->setWidth(m_graphicsView->viewport()->width());
graphicsScene()->invalidateLayout();
@@ -620,6 +614,10 @@ void TimelineWidget::showEvent(QShowEvent *event)
graphicsScene()->onShow();
QWidget::showEvent(event);
//All the events have to be fully processed before we call init()
if (m_timelineView->model())
QTimer::singleShot(0, [this]() { init(); });
}
void TimelineWidget::resizeEvent(QResizeEvent *event)
@@ -630,7 +628,7 @@ void TimelineWidget::resizeEvent(QResizeEvent *event)
void TimelineWidget::hideEvent(QHideEvent *event)
{
/* m_timelineView->setEnabled(false); TODO See QDS-4191 */
m_timelineView->setEnabled(false);
QWidget::hideEvent(event);
}

View File

@@ -33,30 +33,28 @@
#include <QDir>
#include <QHBoxLayout>
using namespace Utils;
namespace Qnx {
namespace Internal {
QnxBaseQtConfigWidget::QnxBaseQtConfigWidget(QnxQtVersion *version) :
m_version(version),
m_sdpPathChooser(new Utils::PathChooser)
m_sdpPathChooser(new PathChooser)
{
QTC_ASSERT(version, return);
auto layout = new QHBoxLayout(this);
layout->addWidget(m_sdpPathChooser);
m_sdpPathChooser->setExpectedKind(Utils::PathChooser::ExistingDirectory);
m_sdpPathChooser->setHistoryCompleter(QLatin1String("Qnx.Sdp.History"));
m_sdpPathChooser->setPath(version->sdpPath());
m_sdpPathChooser->setExpectedKind(PathChooser::ExistingDirectory);
m_sdpPathChooser->setHistoryCompleter("Qnx.Sdp.History");
m_sdpPathChooser->setFilePath(version->sdpPath());
connect(m_sdpPathChooser, &Utils::PathChooser::rawPathChanged,
this, &QnxBaseQtConfigWidget::updateSdpPath);
}
void QnxBaseQtConfigWidget::updateSdpPath(const QString &path)
{
m_version->setSdpPath(path);
connect(m_sdpPathChooser, &PathChooser::rawPathChanged, [this] {
m_version->setSdpPath(m_sdpPathChooser->filePath());
emit changed();
});
}
} // namespace Internal

View File

@@ -27,7 +27,10 @@
#include <qtsupport/qtconfigwidget.h>
namespace Utils { class PathChooser; }
namespace Utils {
class PathChooser;
class FilePath;
} // Utils
namespace Qnx {
namespace Internal {
@@ -41,9 +44,6 @@ class QnxBaseQtConfigWidget : public QtSupport::QtConfigWidget
public:
explicit QnxBaseQtConfigWidget(QnxQtVersion *version);
private slots:
void updateSdpPath(const QString &path);
private:
QnxQtVersion *m_version;
Utils::PathChooser *m_sdpPathChooser;

View File

@@ -225,7 +225,7 @@ QnxQtVersion *QnxConfiguration::qnxQtVersion(const Target &target) const
QtVersionManager::instance()->versions(Utils::equal(&BaseQtVersion::type,
QString::fromLatin1(Constants::QNX_QNX_QT)))) {
auto qnxQt = dynamic_cast<QnxQtVersion *>(version);
if (qnxQt && FilePath::fromString(qnxQt->sdpPath()) == sdpPath()) {
if (qnxQt && qnxQt->sdpPath() == sdpPath()) {
foreach (const Abi &qtAbi, version->qtAbis()) {
if ((qtAbi == target.m_abi) && (qnxQt->cpuDir() == target.cpuDir()))
return qnxQt;
@@ -240,7 +240,7 @@ QList<ToolChain *> QnxConfiguration::autoDetect(const QList<ToolChain *> &alread
{
QList<ToolChain *> result;
foreach (const Target &target, m_targets)
for (const Target &target : qAsConst(m_targets))
result += findToolChain(alreadyKnown, target.m_abi);
return result;
@@ -286,7 +286,7 @@ QnxConfiguration::QnxToolChainMap QnxConfiguration::createToolChain(const Target
"QCC for %1 (%2)")
.arg(displayName())
.arg(target.shortDescription()));
toolChain->setSdpPath(sdpPath().toString());
toolChain->setSdpPath(sdpPath());
toolChain->setCpuDir(target.cpuDir());
toolChain->resetToolChain(qccCompilerPath());
ToolChainManager::registerToolChain(toolChain);
@@ -372,11 +372,11 @@ void QnxConfiguration::setVersion(const QnxVersionNumber &version)
void QnxConfiguration::readInformation()
{
const QString qConfigPath = m_qnxConfiguration.pathAppended("qconfig").toString();
QList <ConfigInstallInformation> installInfoList = QnxUtils::installedConfigs(qConfigPath);
const QList <ConfigInstallInformation> installInfoList = QnxUtils::installedConfigs(qConfigPath);
if (installInfoList.isEmpty())
return;
foreach (const ConfigInstallInformation &info, installInfoList) {
for (const ConfigInstallInformation &info : installInfoList) {
if (m_qnxHost == FilePath::fromString(info.host).canonicalPath()
&& m_qnxTarget == FilePath::fromString(info.target).canonicalPath()) {
m_configName = info.name;
@@ -386,11 +386,11 @@ void QnxConfiguration::readInformation()
}
}
void QnxConfiguration::setDefaultConfiguration(const Utils::FilePath &envScript)
void QnxConfiguration::setDefaultConfiguration(const FilePath &envScript)
{
QTC_ASSERT(!envScript.isEmpty(), return);
m_envFile = envScript;
m_qnxEnv = QnxUtils::qnxEnvironmentFromEnvFile(m_envFile.toString());
m_qnxEnv = QnxUtils::qnxEnvironmentFromEnvFile(m_envFile);
foreach (const EnvironmentItem &item, m_qnxEnv) {
if (item.name == QNXConfiguration)
m_qnxConfiguration = FilePath::fromString(item.value).canonicalPath();

View File

@@ -109,14 +109,14 @@ QString QnxQtVersion::cpuDir() const
QVariantMap QnxQtVersion::toMap() const
{
QVariantMap result = BaseQtVersion::toMap();
result.insert(QLatin1String(SDP_PATH_KEY), sdpPath());
result.insert(SDP_PATH_KEY, sdpPath().toVariant());
return result;
}
void QnxQtVersion::fromMap(const QVariantMap &map)
{
BaseQtVersion::fromMap(map);
setSdpPath(QDir::fromNativeSeparators(map.value(QLatin1String(SDP_PATH_KEY)).toString()));
setSdpPath(FilePath::fromVariant(map.value(SDP_PATH_KEY)));
}
Abis QnxQtVersion::detectQtAbis() const
@@ -134,7 +134,7 @@ void QnxQtVersion::addToEnvironment(const Kit *k, Environment &env) const
env.prependOrSetLibrarySearchPath(libraryPath().toString());
}
void QnxQtVersion::setupQmakeRunEnvironment(Utils::Environment &env) const
void QnxQtVersion::setupQmakeRunEnvironment(Environment &env) const
{
if (!sdpPath().isEmpty())
updateEnvironment();
@@ -160,12 +160,12 @@ QString QnxQtVersion::invalidReason() const
return QtSupport::BaseQtVersion::invalidReason();
}
QString QnxQtVersion::sdpPath() const
FilePath QnxQtVersion::sdpPath() const
{
return m_sdpPath;
}
void QnxQtVersion::setSdpPath(const QString &sdpPath)
void QnxQtVersion::setSdpPath(const FilePath &sdpPath)
{
if (m_sdpPath == sdpPath)
return;

View File

@@ -63,15 +63,15 @@ public:
bool isValid() const override;
QString invalidReason() const override;
QString sdpPath() const;
void setSdpPath(const QString &sdpPath);
Utils::FilePath sdpPath() const;
void setSdpPath(const Utils::FilePath &sdpPath);
private:
void updateEnvironment() const;
Utils::EnvironmentItems environment() const;
QString m_sdpPath;
Utils::FilePath m_sdpPath;
mutable QString m_cpuDir;
mutable bool m_environmentUpToDate = false;

View File

@@ -41,8 +41,8 @@ using namespace Utils;
namespace Qnx {
namespace Internal {
static const char CompilerSdpPath[] = "Qnx.QnxToolChain.NDKPath";
static const char CpuDirKey[] = "Qnx.QnxToolChain.CpuDir";
const char CompilerSdpPath[] = "Qnx.QnxToolChain.NDKPath";
const char CpuDirKey[] = "Qnx.QnxToolChain.CpuDir";
static Abis detectTargetAbis(const FilePath &sdpPath)
{
@@ -50,8 +50,8 @@ static Abis detectTargetAbis(const FilePath &sdpPath)
FilePath qnxTarget;
if (!sdpPath.fileName().isEmpty()) {
Utils::EnvironmentItems environment = QnxUtils::qnxEnvironment(sdpPath.toString());
foreach (const Utils::EnvironmentItem &item, environment) {
const EnvironmentItems environment = QnxUtils::qnxEnvironment(sdpPath);
for (const EnvironmentItem &item : environment) {
if (item.name == QLatin1String("QNX_TARGET"))
qnxTarget = FilePath::fromString(item.value);
}
@@ -137,7 +137,7 @@ QStringList QnxToolChain::suggestedMkspecList() const
QVariantMap QnxToolChain::toMap() const
{
QVariantMap data = GccToolChain::toMap();
data.insert(QLatin1String(CompilerSdpPath), m_sdpPath);
data.insert(QLatin1String(CompilerSdpPath), m_sdpPath.toVariant());
data.insert(QLatin1String(CpuDirKey), m_cpuDir);
return data;
}
@@ -147,7 +147,7 @@ bool QnxToolChain::fromMap(const QVariantMap &data)
if (!GccToolChain::fromMap(data))
return false;
m_sdpPath = data.value(QLatin1String(CompilerSdpPath)).toString();
m_sdpPath = FilePath::fromVariant(data.value(CompilerSdpPath));
m_cpuDir = data.value(QLatin1String(CpuDirKey)).toString();
// Make the ABIs QNX specific (if they aren't already).
@@ -157,12 +157,12 @@ bool QnxToolChain::fromMap(const QVariantMap &data)
return true;
}
QString QnxToolChain::sdpPath() const
FilePath QnxToolChain::sdpPath() const
{
return m_sdpPath;
}
void QnxToolChain::setSdpPath(const QString &sdpPath)
void QnxToolChain::setSdpPath(const FilePath &sdpPath)
{
if (m_sdpPath == sdpPath)
return;
@@ -185,7 +185,7 @@ void QnxToolChain::setCpuDir(const QString &cpuDir)
GccToolChain::DetectedAbisResult QnxToolChain::detectSupportedAbis() const
{
return detectTargetAbis(FilePath::fromString(m_sdpPath));
return detectTargetAbis(m_sdpPath);
}
bool QnxToolChain::operator ==(const ToolChain &other) const
@@ -243,7 +243,7 @@ QnxToolChainConfigWidget::QnxToolChainConfigWidget(QnxToolChain *tc)
m_sdpPath->setExpectedKind(PathChooser::ExistingDirectory);
m_sdpPath->setHistoryCompleter(QLatin1String("Qnx.Sdp.History"));
m_sdpPath->setPath(tc->sdpPath());
m_sdpPath->setFilePath(tc->sdpPath());
m_sdpPath->setEnabled(!tc->isAutoDetected());
const Abis abiList = detectTargetAbis(m_sdpPath->filePath());
@@ -270,7 +270,7 @@ void QnxToolChainConfigWidget::applyImpl()
Q_ASSERT(tc);
QString displayName = tc->displayName();
tc->setDisplayName(displayName); // reset display name
tc->setSdpPath(m_sdpPath->filePath().toString());
tc->setSdpPath(m_sdpPath->filePath());
tc->setTargetAbi(m_abiWidget->currentAbi());
tc->resetToolChain(m_compilerCommand->filePath());
}
@@ -281,7 +281,7 @@ void QnxToolChainConfigWidget::discardImpl()
QSignalBlocker blocker(this);
auto tc = static_cast<const QnxToolChain *>(toolChain());
m_compilerCommand->setFilePath(tc->compilerCommand());
m_sdpPath->setPath(tc->sdpPath());
m_sdpPath->setFilePath(tc->sdpPath());
m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
if (!m_compilerCommand->filePath().toString().isEmpty())
m_abiWidget->setEnabled(true);
@@ -292,7 +292,7 @@ bool QnxToolChainConfigWidget::isDirtyImpl() const
auto tc = static_cast<const QnxToolChain *>(toolChain());
Q_ASSERT(tc);
return m_compilerCommand->filePath() != tc->compilerCommand()
|| m_sdpPath->filePath().toString() != tc->sdpPath()
|| m_sdpPath->filePath() != tc->sdpPath()
|| m_abiWidget->currentAbi() != tc->targetAbi();
}

View File

@@ -46,8 +46,8 @@ public:
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override;
QString sdpPath() const;
void setSdpPath(const QString &sdpPath);
Utils::FilePath sdpPath() const;
void setSdpPath(const Utils::FilePath &sdpPath);
QString cpuDir() const;
void setCpuDir(const QString &cpuDir);
@@ -57,7 +57,7 @@ protected:
DetectedAbisResult detectSupportedAbis() const override;
private:
QString m_sdpPath;
Utils::FilePath m_sdpPath;
QString m_cpuDir;
};

View File

@@ -78,11 +78,11 @@ QString QnxUtils::cpuDirShortDescription(const QString &cpuDir)
return cpuDir;
}
EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const QString &fileName)
EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const FilePath &filePath)
{
EnvironmentItems items;
if (!QFileInfo::exists(fileName))
if (!filePath.exists())
return items;
const bool isWindows = HostOsInfo::isWindowsHost();
@@ -97,10 +97,10 @@ EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const QString &fileName)
QTextStream fileContent(&tmpFile);
if (isWindows)
fileContent << "@echo off\n"
<< "call " << fileName << '\n';
<< "call " << filePath.path() << '\n';
else
fileContent << "#!/bin/bash\n"
<< ". " << fileName << '\n';
<< ". " << filePath.path() << '\n';
QString linePattern = QString::fromLatin1(isWindows ? "echo %1=%%1%" : "echo %1=$%1");
for (int i = 0, len = sizeof(EVAL_ENV_VARS) / sizeof(const char *); i < len; ++i)
fileContent << linePattern.arg(QLatin1String(EVAL_ENV_VARS[i])) << QLatin1Char('\n');
@@ -140,19 +140,18 @@ EnvironmentItems QnxUtils::qnxEnvironmentFromEnvFile(const QString &fileName)
return items;
}
QString QnxUtils::envFilePath(const QString &sdpPath)
FilePath QnxUtils::envFilePath(const FilePath &sdpPath)
{
QDir sdp(sdpPath);
QStringList entries;
if (HostOsInfo::isWindowsHost())
entries = sdp.entryList(QStringList(QLatin1String("*-env.bat")));
FilePaths entries;
if (sdpPath.osType() == OsTypeWindows)
entries = sdpPath.dirEntries({"*-env.bat"});
else
entries = sdp.entryList(QStringList(QLatin1String("*-env.sh")));
entries = sdpPath.dirEntries({"*-env.sh"});
if (!entries.isEmpty())
return sdp.absoluteFilePath(entries.first());
return entries.first();
return QString();
return {};
}
QString QnxUtils::defaultTargetVersion(const QString &sdpPath)
@@ -208,7 +207,7 @@ QList<ConfigInstallInformation> QnxUtils::installedConfigs(const QString &config
return sdpList;
}
EnvironmentItems QnxUtils::qnxEnvironment(const QString &sdpPath)
EnvironmentItems QnxUtils::qnxEnvironment(const FilePath &sdpPath)
{
return qnxEnvironmentFromEnvFile(envFilePath(sdpPath));
}

View File

@@ -68,11 +68,11 @@ class QnxUtils
public:
static QString cpuDirFromAbi(const ProjectExplorer::Abi &abi);
static QString cpuDirShortDescription(const QString &cpuDir);
static Utils::EnvironmentItems qnxEnvironmentFromEnvFile(const QString &fileName);
static QString envFilePath(const QString &sdpPath);
static Utils::EnvironmentItems qnxEnvironmentFromEnvFile(const Utils::FilePath &filePath);
static Utils::FilePath envFilePath(const Utils::FilePath &sdpPath);
static QString defaultTargetVersion(const QString &sdpPath);
static QList<ConfigInstallInformation> installedConfigs(const QString &configPath = QString());
static Utils::EnvironmentItems qnxEnvironment(const QString &sdpPath);
static Utils::EnvironmentItems qnxEnvironment(const Utils::FilePath &sdpPath);
static QList<QnxTarget> findTargets(const Utils::FilePath &basePath);
static ProjectExplorer::Abi convertAbi(const ProjectExplorer::Abi &abi);
static ProjectExplorer::Abis convertAbis(const ProjectExplorer::Abis &abis);

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 374 KiB

After

Width:  |  Height:  |  Size: 372 KiB