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"); llvm::cl::OptionCategory CheckToolCategory("check tool options");
int main(int argc, const char **argv) 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(), ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList()); OptionsParser.getSourcePathList());
return 0; 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 \uicontrol {Qt Quick 3D} module to your project as instructed in
\l {Adding and Removing Modules}. \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. By default, all imported scenes are created with one directional light.
You can use the following components to add lights: 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} \li \l{DirectionalLight}{Light Directional}
\row
\li \inlineimage point.png
\li Point Light
\li
\li \l{PointLight}{Light Point} \li \l{PointLight}{Light Point}
\row
\li \inlineimage spot.png
\li Spot Light
\li
\li \l{SpotLight}{Light Spot} \li \l{SpotLight}{Light Spot}
\row
\li \inlineimage area.png
\li Area Light
\li \inlineimage ok.png
\li \l{AreaLight}{Light Area} \li \l{AreaLight}{Light Area}
\endlist \endtable
\note Each additional light negatively effects the rendering performance \note Each additional light negatively effects the rendering performance
of your scene. Keep scenes as simple as possible and use lights sparingly. of your scene. Keep scenes as simple as possible and use lights sparingly.
Use a \l{SceneEnvironment}{Scene Environment} component to apply image-based Use a \l{SceneEnvironment}{Scene Environment} component to apply image-based
lighting that can produce soft and subtle lighting. lighting that can produce soft and subtle lighting.
You can edit light properties in the \uicontrol Properties view. The To edit light properties, select a light component in \uicontrol Navigator,
\uicontrol Scope property specifies which node, with it's children, or \uicontrol {3D Editor}, and then adjust its properties in the
is illuminated by a light. \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 illuminated by a light. Set the \uicontrol {Ambient color} property to
specify the ambient color applied to materials before being illuminated by specify the ambient color applied to materials before being illuminated by
the light. 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 \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. 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 If the \uicontrol {Casts shadow} property is enabled, shadows are positioned
parallel to the light direction. A directional light has infinite range and parallel to the light direction. A directional light has infinite range and
@@ -96,20 +133,17 @@
\section1 Point Light \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 strength in all directions from the center of the light. This is similar
to the way a light bulb emits light. 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 Lighting is applied outwards from the center of a point light, becoming
increasingly dim away from the center. Moving a point light changes the increasingly dim away from the center. Moving a point light changes the
position from where the light is emitted. Rotating or scaling a point position from where the light is emitted. Rotating or scaling a point
light does not have any effect. 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 To control the fade-off and range of a point light, set the
\uicontrol {Constant fade}, \uicontrol {Linear fade}, and \uicontrol {Constant fade}, \uicontrol {Linear fade}, and
\uicontrol {Quadratic fade} properties. Constant fade is the constant \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 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, the point light fade exactly follows the inverse square law. For example,
when the distance to a component doubles, the light intensity decreases to 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 Aside from fade, a point light has the same properties as a directional
light. light.
@@ -136,7 +171,13 @@
The light intensity diminishes when approaching the value of the The light intensity diminishes when approaching the value of the
\uicontrol {Cone angle} property. The angle at which the light \uicontrol {Cone angle} property. The angle at which the light
intensity starts to diminish is defined by the 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 Inside the inner cone angle, the spot light behaves similarly to the point
light. There the light intensity diminishes according to inverse-square-law. light. There the light intensity diminishes according to inverse-square-law.
@@ -144,15 +185,17 @@
\uicontrol {Constant fade}, \uicontrol {Linear fade}, and \uicontrol {Constant fade}, \uicontrol {Linear fade}, and
\uicontrol {Quadratic fade} properties. \uicontrol {Quadratic fade} properties.
\image studio-3d-spot-light.png
\section1 Area Light \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 An area light is similar to the directional light. However, instead of
emitting an equally bright light across the whole scene, the area light emitting an equally bright light across the whole scene, the area light
emits directional light from a rectangle shaped component. You can set the emits directional light from a rectangle shaped component. Use the light
\uicontrol Width and \uicontrol Height properties to determine the size gizmo or the \uicontrol Properties view to set the \uicontrol Width (6)
of the area light. 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 Aside from the size, an area light has the same properties as a directional
light. light.
@@ -160,8 +203,6 @@
The image below shows an example on how to light a component with different The image below shows an example on how to light a component with different
colors using two different area lights. colors using two different area lights.
\image studio-3d-area-light.png
You can rotate, scale, and move area lights. You can rotate, scale, and move area lights.
\section1 Shadows \section1 Shadows

View File

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

View File

@@ -73,7 +73,7 @@ itemLibraryModel [
] ]
*/ */
ScrollView { Item {
id: itemsView id: itemsView
property string importToRemove: "" property string importToRemove: ""
@@ -81,6 +81,11 @@ ScrollView {
property var currentItem: null property var currentItem: null
property var currentCategory: null property var currentCategory: null
property var currentImport: 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 // called from C++ to close context menu on focus out
function closeContextMenu() function closeContextMenu()
@@ -91,15 +96,21 @@ ScrollView {
function showImportCategories() 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()) if (!itemLibraryModel.getIsAnyCategoryHidden())
itemLibraryModel.isAnyCategoryHidden = false itemLibraryModel.isAnyCategoryHidden = false
} }
onContentHeightChanged: { onWidthChanged: {
var maxPosition = Math.max(contentHeight - height, 0) itemsView.isHorizontalView = itemsView.width > widthLimit
if (contentY > maxPosition)
contentY = maxPosition
} }
Item { Item {
@@ -112,66 +123,68 @@ ScrollView {
property int cellVerticalMargin: 4 property int cellVerticalMargin: 4
// the following depend on the actual shape of the item delegate // the following depend on the actual shape of the item delegate
property int cellWidth: textWidth + 2 * cellHorizontalMargin property int cellWidth: styleConstants.textWidth + 2 * styleConstants.cellHorizontalMargin
property int cellHeight: itemLibraryIconHeight + textHeight + property int cellHeight: itemLibraryIconHeight + styleConstants.textHeight +
2 * cellVerticalMargin + cellVerticalSpacing 2 * styleConstants.cellVerticalMargin + styleConstants.cellVerticalSpacing
StudioControls.Menu { StudioControls.Menu {
id: moduleContextMenu id: moduleContextMenu
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Remove Module") text: qsTr("Remove Module")
visible: currentCategory === null visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
enabled: importToRemove !== "" enabled: itemsView.importToRemove !== ""
onTriggered: { onTriggered: {
showImportCategories() showImportCategories()
rootView.removeImport(importToRemove) rootView.removeImport(itemsView.importToRemove)
} }
} }
StudioControls.MenuSeparator { StudioControls.MenuSeparator {
visible: currentCategory === null visible: itemsView.currentCategory === null
height: StudioTheme.Values.border height: StudioTheme.Values.border
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Expand All") text: qsTr("Expand All")
visible: currentCategory === null visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.expandAll() onTriggered: itemLibraryModel.expandAll()
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Collapse All") text: qsTr("Collapse All")
visible: currentCategory === null visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: itemLibraryModel.collapseAll() onTriggered: itemLibraryModel.collapseAll()
} }
StudioControls.MenuSeparator { StudioControls.MenuSeparator {
visible: currentCategory === null visible: itemsView.currentCategory === null
height: StudioTheme.Values.border height: StudioTheme.Values.border
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Hide Category") text: qsTr("Hide Category")
visible: currentCategory visible: itemsView.currentCategory
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: { onTriggered: {
itemLibraryModel.isAnyCategoryHidden = true itemLibraryModel.isAnyCategoryHidden = true
currentCategory.categoryVisible = false itemsView.currentCategory.categoryVisible = false
itemsView.currentCategory.categorySelected = false
itemsView.selectedCategory = itemLibraryModel.selectImportFirstVisibleCategory()
} }
} }
StudioControls.MenuSeparator { StudioControls.MenuSeparator {
visible: currentCategory visible: itemsView.currentCategory
height: StudioTheme.Values.border height: StudioTheme.Values.border
} }
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Show Module Hidden Categories") text: qsTr("Show Module Hidden Categories")
enabled: currentImport && !currentImport.importCatVisibleState enabled: itemsView.currentImport && !itemsView.currentImport.importCatVisibleState
onTriggered: showImportCategories() onTriggered: showImportCategories()
} }
@@ -179,6 +192,12 @@ ScrollView {
text: qsTr("Show All Hidden Categories") text: qsTr("Show All Hidden Categories")
enabled: itemLibraryModel.isAnyCategoryHidden enabled: itemLibraryModel.isAnyCategoryHidden
onTriggered: { onTriggered: {
if (itemLibraryModel.isAllCategoriesHidden()) {
itemLibraryModel.showHiddenCategories()
itemsView.selectedCategory = itemLibraryModel.selectImportFirstVisibleCategory()
itemLibraryModel.isAnyCategoryHidden = false
}
itemLibraryModel.isAnyCategoryHidden = false itemLibraryModel.isAnyCategoryHidden = false
itemLibraryModel.showHiddenCategories() itemLibraryModel.showHiddenCategories()
} }
@@ -192,20 +211,39 @@ ScrollView {
StudioControls.MenuItem { StudioControls.MenuItem {
id: importMenuItem id: importMenuItem
text: qsTr("Add Module: ") + importToAdd text: qsTr("Add Module: ") + itemsView.importToAdd
enabled: importToAdd !== "" enabled: itemsView.importToAdd !== ""
onTriggered: rootView.addImportForItem(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 { Column {
spacing: 2 spacing: 2
Repeater { Repeater {
model: itemLibraryModel // to be set in Qml context model: itemLibraryModel // to be set in Qml context
delegate: Section { delegate: Section {
width: itemsView.width - width: itemsView.width -
(itemsView.verticalScrollBarVisible ? itemsView.verticalThickness : 0) (verticalScrollView.verticalScrollBarVisible
? verticalScrollView.verticalThickness : 0)
caption: importName caption: importName
visible: importVisible visible: importVisible
sectionHeight: 30 sectionHeight: 30
@@ -218,15 +256,14 @@ ScrollView {
expanded: importExpanded expanded: importExpanded
expandOnClick: false expandOnClick: false
useDefaulContextMenu: false useDefaulContextMenu: false
onToggleExpand: { onToggleExpand: {
if (categoryModel.rowCount() > 0) if (categoryModel.rowCount() > 0)
importExpanded = !importExpanded importExpanded = !importExpanded
} }
onShowContextMenu: { onShowContextMenu: {
importToRemove = importRemovable ? importUrl : "" itemsView.importToRemove = importRemovable ? importUrl : ""
currentImport = model itemsView.currentImport = model
currentCategory = null itemsView.currentCategory = null
if (!rootView.isSearchActive()) if (!rootView.isSearchActive())
moduleContextMenu.popup() moduleContextMenu.popup()
} }
@@ -238,22 +275,24 @@ ScrollView {
model: categoryModel model: categoryModel
delegate: Section { delegate: Section {
width: itemsView.width - width: itemsView.width -
(itemsView.verticalScrollBarVisible ? itemsView.verticalThickness : 0) (verticalScrollView.verticalScrollBarVisible
? verticalScrollView.verticalThickness : 0)
sectionBackgroundColor: "transparent" sectionBackgroundColor: "transparent"
showTopSeparator: index > 0 showTopSeparator: index > 0
hideHeader: categoryModel.rowCount() <= 1 hideHeader: categoryModel.rowCount() <= 1
leftPadding: 0 leftPadding: 0
rightPadding: 0 rightPadding: 0
addTopPadding: categoryModel.rowCount() > 1 addTopPadding: categoryModel.rowCount() > 1
addBottomPadding: index != categoryModel.rowCount() - 1 addBottomPadding: index !== categoryModel.rowCount() - 1
caption: categoryName + " (" + itemModel.rowCount() + ")" caption: categoryName + " (" + itemModel.rowCount() + ")"
visible: categoryVisible visible: categoryVisible
expanded: categoryExpanded expanded: categoryExpanded
expandOnClick: false expandOnClick: false
onToggleExpand: categoryExpanded = !categoryExpanded onToggleExpand: categoryExpanded = !categoryExpanded
useDefaulContextMenu: false
onShowContextMenu: { onShowContextMenu: {
currentCategory = model itemsView.currentCategory = model
currentImport = parent.currentImportModel itemsView.currentImport = parent.currentImportModel
if (!rootView.isSearchActive()) if (!rootView.isSearchActive())
moduleContextMenu.popup() moduleContextMenu.popup()
} }
@@ -267,6 +306,7 @@ ScrollView {
leftPadding: 6 leftPadding: 6
rightPadding: 6 rightPadding: 6
columns: itemGrid.actualWidth / styleConstants.cellWidth columns: itemGrid.actualWidth / styleConstants.cellWidth
rowSpacing: 7
Repeater { Repeater {
model: itemModel model: itemModel
@@ -278,7 +318,7 @@ ScrollView {
height: styleConstants.cellHeight height: styleConstants.cellHeight
onShowContextMenu: { onShowContextMenu: {
if (!itemUsable) { if (!itemUsable) {
importToAdd = itemRequiredImport itemsView.importToAdd = itemRequiredImport
itemContextMenu.popup() 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; Utils::optional<QList<MarkupKind>> documentationFormat() const;
void setDocumentationFormat(const QList<MarkupKind> &documentationFormat); void setDocumentationFormat(const QList<MarkupKind> &documentationFormat);
void clearDocumentationFormat() { remove(documentationFormatKey); } 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. // The client supports the following `SignatureInformation` specific properties.

View File

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

View File

@@ -145,6 +145,10 @@ public:
void setParameters(const QList<ParameterInformation> &parameters) void setParameters(const QList<ParameterInformation> &parameters)
{ insertArray(parametersKey, parameters); } { insertArray(parametersKey, parameters); }
void clearParameters() { remove(parametersKey); } 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) { switch (d->m_displayStyle) {
case PathChooserDisplay: case PathChooserDisplay:
if (d->m_pathChooserDisplay) if (d->m_pathChooserDisplay)
d->m_pathChooserDisplay->setPath(val.toString()); d->m_pathChooserDisplay->setFilePath(FilePath::fromVariant(val));
break; break;
case LineEditDisplay: case LineEditDisplay:
if (d->m_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, bool ProcessArgs::prepareCommand(const CommandLine &cmdLine, QString *outCmd, ProcessArgs *outArgs,
const Environment *env, const FilePath *pwd) const Environment *env, const FilePath *pwd)
{ {
const FilePath executable = cmdLine.executable(); FilePath executable = cmdLine.executable();
const QString arguments = cmdLine.arguments(); const QString arguments = cmdLine.arguments();
if (env && executable.isRelativePath())
executable = env->searchInPath(executable.toString());
ProcessArgs::SplitError err; ProcessArgs::SplitError err;
*outArgs = ProcessArgs::prepareArgs(arguments, &err, executable.osType(), env, pwd); *outArgs = ProcessArgs::prepareArgs(arguments, &err, executable.osType(), env, pwd);
if (err == ProcessArgs::SplitOk) { if (err == ProcessArgs::SplitOk) {

View File

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

View File

@@ -195,6 +195,11 @@ bool ProjectIntroPage::validate()
return false; return false;
} }
void ProjectIntroPage::fieldsUpdated()
{
slotChanged();
}
void ProjectIntroPage::slotChanged() void ProjectIntroPage::slotChanged()
{ {
const bool newComplete = validate(); 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->setType(t);
d->m_ui.stateLabel->setText(s); d->m_ui.stateLabel->setText(s);
emit statusMessageChanged(t, s);
} }
void ProjectIntroPage::hideStatusLabel() void ProjectIntroPage::hideStatusLabel()

View File

@@ -66,8 +66,14 @@ public:
bool validateProjectName(const QString &name, QString *errorMessage); 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: signals:
void activated(); void activated();
void statusMessageChanged(InfoLabel::InfoType type, const QString &message);
public slots: public slots:
void setFilePath(const FilePath &path); void setFilePath(const FilePath &path);

View File

@@ -88,9 +88,9 @@ QTextCursor selectAt(QTextCursor textCursor, int line, int column, uint length)
if (column < 1) if (column < 1)
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);
textCursor.setPosition(anchorPosition - length, QTextCursor::KeepAnchor); textCursor.setPosition(anchorPosition + int(length), QTextCursor::KeepAnchor);
return textCursor; return textCursor;
} }

View File

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

View File

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

View File

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

View File

@@ -2616,7 +2616,9 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
} else if (token.type == "type") { } else if (token.type == "type") {
styles.mainStyle = C_TYPE; styles.mainStyle = C_TYPE;
} else if (token.type == "typeParameter") { } 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")) if (token.modifiers.contains("declaration"))
styles.mixinStyles.push_back(C_DECLARATION); styles.mixinStyles.push_back(C_DECLARATION);

View File

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

View File

@@ -67,7 +67,7 @@ SettingsPageWidget::SettingsPageWidget()
const ClearCaseSettings &s = ClearCasePlugin::settings(); 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.timeOutSpinBox->setValue(s.timeOutS);
m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut); m_ui.autoCheckOutCheckBox->setChecked(s.autoCheckOut);
m_ui.noCommentCheckBox->setChecked(s.noComment); m_ui.noCommentCheckBox->setChecked(s.noComment);

View File

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

View File

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

View File

@@ -721,31 +721,5 @@ FileApiQtcData extractData(FileApiData &input,
return result; 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 Internal
} // namespace CMakeProjectManager } // namespace CMakeProjectManager

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -897,7 +897,10 @@ void DockerDevicePrivate::startContainer()
void DockerDevicePrivate::tryCreateLocalFileAccess() 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; return;
if (!m_shell) if (!m_shell)

View File

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

View File

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

View File

@@ -61,11 +61,12 @@ QString FunctionHintProposalModel::text(int index) const
if (index < 0 || m_sigis.signatures().size() <= index) if (index < 0 || m_sigis.signatures().size() <= index)
return {}; return {};
const SignatureInformation signature = m_sigis.signatures().at(index); 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(); 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) if (parametersIndex < 0)
return label; return label;

View File

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

View File

@@ -62,7 +62,9 @@ void DocumentLocatorFilter::updateCurrentClient()
disconnect(m_resetSymbolsConnection); disconnect(m_resetSymbolsConnection);
TextEditor::TextDocument *document = TextEditor::TextDocument::currentTextDocument(); 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()) { if (m_symbolCache != client->documentSymbolCache()) {
disconnect(m_updateSymbolsConnection); disconnect(m_updateSymbolsConnection);
m_symbolCache = client->documentSymbolCache(); m_symbolCache = client->documentSymbolCache();
@@ -76,6 +78,7 @@ void DocumentLocatorFilter::updateCurrentClient()
disconnect(m_updateSymbolsConnection); disconnect(m_updateSymbolsConnection);
m_symbolCache.clear(); m_symbolCache.clear();
m_currentUri.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) bool CheckBoxField::validate(MacroExpander *expander, QString *message)
{ {
if (!JsonFieldPage::Field::validate(expander, message)) if (!JsonFieldPage::Field::validate(expander, message))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -58,6 +58,7 @@
#include <QGraphicsLinearLayout> #include <QGraphicsLinearLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QMessageBox> #include <QMessageBox>
#include <QMimeData>
#include <exception> #include <exception>
@@ -241,6 +242,56 @@ ModelNodePreviewImageOperation DesignerActionManager::modelNodePreviewOperation(
return op; 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 class VisiblityModelNodeAction : public ModelNodeContextMenuAction
{ {
public: public:

View File

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

View File

@@ -81,6 +81,18 @@ void CurveEditor::clearCanvas()
m_view->reset({}); 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) QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
{ {
auto *bar = new QToolBar; auto *bar = new QToolBar;

View File

@@ -49,6 +49,13 @@ public:
void clearCanvas(); void clearCanvas();
signals:
void viewEnabledChanged(const bool);
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
private: private:
QToolBar *createToolBar(CurveEditorModel *model); 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::commitStartFrame, this, &CurveEditorView::commitStartFrame);
connect(m_model, &CurveEditorModel::commitEndFrame, this, &CurveEditorView::commitEndFrame); connect(m_model, &CurveEditorModel::commitEndFrame, this, &CurveEditorView::commitEndFrame);
connect(m_model, &CurveEditorModel::curveChanged, this, &CurveEditorView::commitKeyframes); 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() {} CurveEditorView::~CurveEditorView() {}
@@ -70,10 +77,8 @@ void CurveEditorView::modelAttached(Model *model)
{ {
AbstractView::modelAttached(model); AbstractView::modelAttached(model);
QmlTimeline timeline = activeTimeline(); if (isEnabled())
if (timeline.isValid()) { init();
m_model->setTimeline(timeline);
}
} }
void CurveEditorView::modelAboutToBeDetached(Model *model) void CurveEditorView::modelAboutToBeDetached(Model *model)
@@ -389,4 +394,13 @@ void CurveEditorView::commitEndFrame(int frame)
timeline.modelNode().variantProperty("endFrame").setValue(frame); timeline.modelNode().variantProperty("endFrame").setValue(frame);
} }
void CurveEditorView::init()
{
QmlTimeline timeline = activeTimeline();
if (timeline.isValid()) {
m_model->setTimeline(timeline);
}
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

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

View File

@@ -40,6 +40,7 @@
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
#include <QActionGroup> #include <QActionGroup>
#include <QMimeData>
#include <QVBoxLayout> #include <QVBoxLayout>
namespace QmlDesigner { namespace QmlDesigner {
@@ -47,6 +48,8 @@ namespace QmlDesigner {
Edit3DWidget::Edit3DWidget(Edit3DView *view) : Edit3DWidget::Edit3DWidget(Edit3DView *view) :
m_view(view) m_view(view)
{ {
setAcceptDrops(true);
Core::Context context(Constants::C_QMLEDITOR3D); Core::Context context(Constants::C_QMLEDITOR3D);
m_context = new Core::IContext(this); m_context = new Core::IContext(this);
m_context->setContext(context); m_context->setContext(context);
@@ -159,4 +162,19 @@ Edit3DView *Edit3DWidget::view() const
return m_view.data(); 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); void showCanvas(bool show);
protected:
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private: private:
void linkActivated(const QString &link); void linkActivated(const QString &link);

View File

@@ -53,6 +53,7 @@
#include <QActionGroup> #include <QActionGroup>
#include <QFileDialog> #include <QFileDialog>
#include <QMimeData>
#include <QPainter> #include <QPainter>
#include <QPicture> #include <QPicture>
#include <QVBoxLayout> #include <QVBoxLayout>
@@ -63,6 +64,8 @@ namespace QmlDesigner {
FormEditorWidget::FormEditorWidget(FormEditorView *view) FormEditorWidget::FormEditorWidget(FormEditorView *view)
: m_formEditorView(view) : m_formEditorView(view)
{ {
setAcceptDrops(true);
Core::Context context(Constants::C_QMLFORMEDITOR); Core::Context context(Constants::C_QMLFORMEDITOR);
m_context = new Core::IContext(this); m_context = new Core::IContext(this);
m_context->setContext(context); 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 } // namespace QmlDesigner

View File

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

View File

@@ -144,6 +144,17 @@ void ItemLibraryCategoriesModel::resetModel()
endResetModel(); 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) void ItemLibraryCategoriesModel::showAllCategories(bool show)
{ {
for (const auto &category : std::as_const(m_categoryList)) { for (const auto &category : std::as_const(m_categoryList)) {
@@ -153,9 +164,43 @@ void ItemLibraryCategoriesModel::showAllCategories(bool show)
category->ownerImport()->importName()); category->ownerImport()->importName());
} }
} }
emit dataChanged(index(0), index(m_categoryList.size() - 1), {m_roleNames.key("categoryVisible")}); 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() void ItemLibraryCategoriesModel::addRoleNames()
{ {
int role = 0; int role = 0;

View File

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

View File

@@ -26,6 +26,7 @@
#include "itemlibrarycategory.h" #include "itemlibrarycategory.h"
#include "itemlibraryitem.h" #include "itemlibraryitem.h"
#include "itemlibrarywidget.h"
namespace QmlDesigner { namespace QmlDesigner {
@@ -46,6 +47,11 @@ bool ItemLibraryCategory::categoryExpanded() const
return m_categoryExpanded; return m_categoryExpanded;
} }
bool ItemLibraryCategory::categorySelected() const
{
return m_categorySelected;
}
QString ItemLibraryCategory::sortingName() const QString ItemLibraryCategory::sortingName() const
{ {
if (ItemLibraryModel::categorySortingHash.contains(categoryName())) if (ItemLibraryModel::categorySortingHash.contains(categoryName()))
@@ -84,6 +90,10 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
hasVisibleItems = true; 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 // expand category if it has an item matching search criteria
if (!searchText.isEmpty() && hasVisibleItems && !categoryExpanded()) if (!searchText.isEmpty() && hasVisibleItems && !categoryExpanded())
setExpanded(true); setExpanded(true);
@@ -124,4 +134,9 @@ void ItemLibraryCategory::setExpanded(bool expanded)
m_categoryExpanded = expanded; m_categoryExpanded = expanded;
} }
void ItemLibraryCategory::setCategorySelected(bool selected)
{
m_categorySelected = selected;
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

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

View File

@@ -138,6 +138,26 @@ void ItemLibraryImport::showAllCategories(bool show)
m_categoryModel.showAllCategories(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 Import ItemLibraryImport::importEntry() const
{ {
return m_import; return m_import;

View File

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

View File

@@ -90,6 +90,40 @@ bool ItemLibraryModel::getIsAnyCategoryHidden() const
return false; 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 bool ItemLibraryModel::isAnyCategoryHidden() const
{ {
return m_isAnyCategoryHidden; return m_isAnyCategoryHidden;

View File

@@ -77,6 +77,9 @@ public:
Q_INVOKABLE void collapseAll(); Q_INVOKABLE void collapseAll();
Q_INVOKABLE void showHiddenCategories(); Q_INVOKABLE void showHiddenCategories();
Q_INVOKABLE bool getIsAnyCategoryHidden() const; 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); Import entryToImport(const ItemLibraryEntry &entry);

View File

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

View File

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

View File

@@ -49,6 +49,8 @@ NavigatorWidget::NavigatorWidget(NavigatorView *view)
: m_treeView(new NavigatorTreeView) : m_treeView(new NavigatorTreeView)
, m_navigatorView(view) , m_navigatorView(view)
{ {
setAcceptDrops(true);
m_treeView->setDragEnabled(true); m_treeView->setDragEnabled(true);
m_treeView->setAcceptDrops(true); m_treeView->setAcceptDrops(true);
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection); m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
@@ -184,4 +186,19 @@ NavigatorView *NavigatorWidget::navigatorView() const
return m_navigatorView.data(); 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 class NavigatorWidget: public QFrame
{ {
Q_OBJECT Q_OBJECT
public: public:
NavigatorWidget(NavigatorView *view); NavigatorWidget(NavigatorView *view);
@@ -63,10 +64,13 @@ signals:
void filterToggled(bool); void filterToggled(bool);
void reverseOrderToggled(bool); void reverseOrderToggled(bool);
private: // functions protected:
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
void dropEvent(QDropEvent *dropEvent) override;
private:
NavigatorView *navigatorView() const; NavigatorView *navigatorView() const;
private: // variables
NavigatorTreeView *m_treeView; NavigatorTreeView *m_treeView;
QPointer<NavigatorView> m_navigatorView; QPointer<NavigatorView> m_navigatorView;
}; };

View File

@@ -53,6 +53,8 @@ TextEditorWidget::TextEditorWidget(TextEditorView *textEditorView)
, m_textEditorView(textEditorView) , m_textEditorView(textEditorView)
, m_statusBar(new TextEditorStatusBar(this)) , m_statusBar(new TextEditorStatusBar(this))
{ {
setAcceptDrops(true);
QBoxLayout *layout = new QVBoxLayout(this); QBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0); layout->setSpacing(0);
@@ -216,5 +218,19 @@ bool TextEditorWidget::eventFilter( QObject *, QEvent *event)
return false; 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 } // namespace QmlDesigner

View File

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

View File

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

View File

@@ -606,13 +606,7 @@ void TimelineWidget::showEvent(QShowEvent *event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
/*
m_timelineView->setEnabled(true); m_timelineView->setEnabled(true);
TODO See QDS-4191
*/
if (m_timelineView->model())
init();
graphicsScene()->setWidth(m_graphicsView->viewport()->width()); graphicsScene()->setWidth(m_graphicsView->viewport()->width());
graphicsScene()->invalidateLayout(); graphicsScene()->invalidateLayout();
@@ -620,6 +614,10 @@ void TimelineWidget::showEvent(QShowEvent *event)
graphicsScene()->onShow(); graphicsScene()->onShow();
QWidget::showEvent(event); 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) void TimelineWidget::resizeEvent(QResizeEvent *event)
@@ -630,7 +628,7 @@ void TimelineWidget::resizeEvent(QResizeEvent *event)
void TimelineWidget::hideEvent(QHideEvent *event) void TimelineWidget::hideEvent(QHideEvent *event)
{ {
/* m_timelineView->setEnabled(false); TODO See QDS-4191 */ m_timelineView->setEnabled(false);
QWidget::hideEvent(event); QWidget::hideEvent(event);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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