Merge remote-tracking branch 'origin/4.15'

Change-Id: I528bff4d19dc4dfcb600e1e18b0d375c232eb417
This commit is contained in:
Eike Ziller
2021-03-05 17:55:17 +01:00
111 changed files with 2819 additions and 335 deletions

View File

@@ -94,7 +94,7 @@ function(qtc_output_binary_dir varName)
endfunction() endfunction()
function(add_qtc_library name) function(add_qtc_library name)
cmake_parse_arguments(_arg "STATIC;OBJECT;SKIP_TRANSLATION;ALLOW_ASCII_CASTS;UNVERSIONED" cmake_parse_arguments(_arg "STATIC;OBJECT;SKIP_TRANSLATION;ALLOW_ASCII_CASTS;UNVERSIONED;FEATURE_INFO"
"DESTINATION;COMPONENT;SOURCES_PREFIX;BUILD_DEFAULT" "DESTINATION;COMPONENT;SOURCES_PREFIX;BUILD_DEFAULT"
"CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES" ${ARGN} "CONDITION;DEPENDS;PUBLIC_DEPENDS;DEFINES;PUBLIC_DEFINES;INCLUDES;PUBLIC_INCLUDES;SOURCES;EXPLICIT_MOC;SKIP_AUTOMOC;EXTRA_TRANSLATIONS;PROPERTIES" ${ARGN}
) )
@@ -110,6 +110,7 @@ function(add_qtc_library name)
update_cached_list(__QTC_LIBRARIES "${name}") update_cached_list(__QTC_LIBRARIES "${name}")
condition_info(_extra_text _arg_CONDITION)
if (NOT _arg_CONDITION) if (NOT _arg_CONDITION)
set(_arg_CONDITION ON) set(_arg_CONDITION ON)
endif() endif()
@@ -131,6 +132,9 @@ function(add_qtc_library name)
set(_library_enabled OFF) set(_library_enabled OFF)
endif() endif()
if(DEFINED _arg_FEATURE_INFO)
add_feature_info("Library ${name}" _library_enabled "${_extra_text}")
endif()
if (NOT _library_enabled) if (NOT _library_enabled)
return() return()
endif() endif()

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -96,6 +96,7 @@
\li \l{Library} \li \l{Library}
\li \l{Navigator} \li \l{Navigator}
\li \l{Properties} \li \l{Properties}
\li \l{Transition Editor}
\endlist \endlist
\li \l {Creating UIs} \li \l {Creating UIs}
\list \list

View File

@@ -101,7 +101,7 @@
actions. actions.
\li \l{Adding States} \li \l{Adding States}
\row \row
\li \l{Animating Transitions Between States}{Transition Editor} \li \l{Transition Editor}
\li Enables you to make movement between states smooth by animating \li Enables you to make movement between states smooth by animating
the changes between states. the changes between states.
\li \l{Animating Transitions Between States} \li \l{Animating Transitions Between States}

View File

@@ -33,47 +33,129 @@
You design applications in the \uicontrol {Form Editor} view by placing You design applications in the \uicontrol {Form Editor} view by placing
\l{Component Types}{2D components} and \l{Assets}{assets} into it. \l{Component Types}{2D components} and \l{Assets}{assets} into it.
When you select items in \uicontrol {Form Editor}, markers
appear around their edges and in their corners. Depending on the shape of
the cursor, you can move, resize, or rotate the item by dragging it.
The following image shows the move cursor.
\image qmldesigner-form-editor.png "Form Editor view" \image qmldesigner-form-editor.png "Form Editor view"
\section1 Resizing 2D Items When you select components in \uicontrol {Form Editor}, markers appear
around their edges and in their corners. Depending on the shape of the
cursor, you can apply the following actions on the components by dragging
them:
When the resize cursor is displayed, you can drag the selection handles \list
to resize items. \li \l{Moving Components}{Move components}
\li \l{Resizing 2D Components}{Resize components}
\li \l{Rotating 2D Components}{Rotate components}
\endlist
\section1 Summary of Form Editor Buttons
The \uicontrol {Form Editor} toolbar contains the following buttons and
fields.
\table
\header
\li Button/Field
\li Tooltip
\li Read More
\row
\li \inlineimage no_snapping.png
\li Disables snapping.
\li \l{Snapping to Parent and Sibling Components}
\row
\li \inlineimage snapping_and_anchoring.png
\li Anchors the component to the components that it is snapped to.
\li \l{Snapping to Parent and Sibling Components}
\row
\li \inlineimage snapping.png
\li Snaps components to their parent or sibling components when you
align them.
\li \l{Snapping to Parent and Sibling Components}
\row
\li \inlineimage boundingrect.png
\li Hides and shows component boundaries.
\li \l{Hiding Component Boundaries}
\row
\li \uicontrol {Override Width}
\li Shows a preview of the component using the specified width.
\li \l{Previewing Component Size}
\row
\li \uicontrol {Override Height}
\li Shows a preview of the component using the specified height.
\li \l{Previewing Component Size}
\row
\li \inlineimage icons/canvas-color.png
\li Sets the color of the \uicontrol {Form Editor} working area.
\li \l{Setting Canvas Color}
\row
\li \inlineimage icons/zoomIn.png
\li Zooms in.
\li \l{Zooming}
\row
\li \inlineimage icons/zoomOut.png
\li Zooms out.
\li \l{Zooming}
\row
\li Zoom level
\li Sets the zoom level that you select from the list.
\li \l{Zooming}
\row
\li \inlineimage icons/zoomAll.png
\li Zooms to fit all content.
\li \l{Zooming}
\row
\li \inlineimage icons/zoomSelection.png
\li Zooms to fit the current selection.
\li \l{Zooming}
\row
\li \inlineimage reset.png
\li Refreshes the contents of \uicontrol {Form Editor}.
\li \l{Refreshing Form Editor Contents}
\endtable
\section1 Moving Components
When the move cursor is displayed, you can move the selected component to
any position in \uicontrol {Form Editor}.
\image qmldesigner-form-editor-move-cursor.png "Move cursor in Form Editor view"
For more information about alternative ways of positioning components in
UIs, see \l{Positioning Items}.
\section1 Resizing 2D Components
When the resize cursor is displayed, you can drag the markers to resize
components.
\image qtquick-designer-scaling-items.png "Form Editor view" \image qtquick-designer-scaling-items.png "Form Editor view"
\if defined(qtdesignstudio) To have the resizing done from the center of the selected component rather
To have the resizing done from the center of the selected item instead from than from its edges, press \key Alt (or the option key on \macos).
its edges, press \key Alt.
To preserve the image aspect ratio while resizing when using the corner To preserve the image aspect ratio while resizing when using the corner
handles, press \key Shift. This also works on items that are anchored markers, press \key Shift. This also works on components that are anchored
using left, right, top, or bottom anchors. using left, right, top, or bottom anchors.
To both resize from the center of the item and preserve the aspect ratio, To both resize from the center of the component and preserve the aspect
press \key Alt+Shift. ratio, press \key Alt+Shift (or the option key + \key Shift on \macos).
\endif
\section1 Rotating 2D Items For more information about alternative ways to specify the size of a
component in a UI, see \l{2D Geometry}.
\section1 Rotating 2D Components
When the rotation cursor \inlineimage icons/rotation-cursor.png When the rotation cursor \inlineimage icons/rotation-cursor.png
is displayed in one of the corners of an item, you can drag is displayed in one of the corners of a component, you can drag
clockwise or counter-clockwise to freely rotate the item around clockwise or counter-clockwise to freely rotate the component around
its origin in \uicontrol {Form Editor}. its origin.
\image qtquick-designer-rotating-items.png "2D rotation tool" \image qtquick-designer-rotating-items.png "2D rotation tool"
Additionally, press \key Shift or \key Alt to rotate items in steps of 5 or Additionally, press \key Shift or \key Alt (or the option key on \macos)
45 degrees, respectively. to rotate components in steps of 5 or 45 degrees, respectively.
You can set the \l{Managing 2D Transformations}{origin} in the You can set the \l{Managing 2D Transformations}{origin} in the
\uicontrol Origin field in the \uicontrol Advanced tab in the \uicontrol Origin field in the \uicontrol Advanced tab in the
\uicontrol Properties view. There, you can also enter the value \l Properties view. There, you can also enter the value
of the \uicontrol Rotation property in degrees. of the \uicontrol Rotation property in degrees.
\section1 Zooming \section1 Zooming
@@ -85,43 +167,23 @@
\image qmldesigner-zooming.gif "Zooming in Form Editor" \image qmldesigner-zooming.gif "Zooming in Form Editor"
The following table lists the zoom buttons: \section1 Snapping to Parent and Sibling Components
\table You can use snapping to align components in \uicontrol {Form Editor}.
\header Click the \inlineimage snapping.png
\li Icon button to have the components snap to their parent or sibling components.
\li Tooltip Snapping lines automatically appear to help you position the components.
\row
\li \inlineimage icons/zoomIn.png
\li Zoom in
\row
\li \inlineimage icons/zoomOut.png
\li Zoom out
\row
\li \inlineimage icons/zoomAll.png
\li Zoom to fit all content
\row
\li \inlineimage icons/zoomSelection.png
\li Zoom to fit the current selection
\endtable
\section1 Snapping to Parent and Sibling Items
When you are working on a design, you can use snapping to align
items in \uicontrol {Form Editor}. Click the \inlineimage snapping.png
button to have the items snap to their parent or sibling items. Snapping
lines automatically appear to help you position the items.
Click the \inlineimage snapping_and_anchoring.png Click the \inlineimage snapping_and_anchoring.png
button to anchor the item to the items that you snap to. button to anchor the component to the components that you snap to.
Only one snapping button can be selected at the time. Selecting Only one snapping button can be selected at the time. Selecting
one snapping button automatically deselects the others. one snapping button automatically deselects the others.
Choose \uicontrol Tools > \uicontrol Options > \uicontrol {Qt Quick} > Choose \uicontrol Tools > \uicontrol Options > \uicontrol {Qt Quick} >
\uicontrol {Qt Quick Designer} to specify settings for snapping. In the \uicontrol {Qt Quick Designer} to specify settings for snapping. In the
\uicontrol {Parent item padding} field, specify the \uicontrol {Parent item padding} field, specify the
distance in pixels between the parent item and the snapping lines. In the distance in pixels between the parent component and the snapping lines. In
\uicontrol {Sibling item spacing} field, specify the distance in pixels between the \uicontrol {Sibling item spacing} field, specify the distance in pixels
sibling items and the snapping lines. between sibling components and the snapping lines.
\image qtquick-designer-options.png "Qt Quick Designer options" \image qtquick-designer-options.png "Qt Quick Designer options"
@@ -130,33 +192,36 @@
\image qmldesigner-snap-margins.png "Snapping lines on canvas" \image qmldesigner-snap-margins.png "Snapping lines on canvas"
\section1 Hiding Item Boundaries For alternative ways of aligning and distributing components by using the
\l Properties view, see \l{Aligning and Distributing Items}.
\uicontrol {Form Editor} displays the boundaries of items. \section1 Hiding Component Boundaries
\uicontrol {Form Editor} displays the boundaries of components.
To hide them, select the \inlineimage boundingrect.png To hide them, select the \inlineimage boundingrect.png
button. button.
\section1 Previewing Component Size \section1 Previewing Component Size
The width and height of the root item in a QML file determine the size of The width and height of the root component in a UI file determine the size
the component. You can reuse components, such as buttons, in different of the component. You can reuse components, such as buttons, in different
sizes in other QML files and design UIs for use with different device sizes in other UI files and design UIs for use with different device
profiles, screen resolution, or screen orientation. The component size profiles, screen resolution, or screen orientation. The component size
might also be zero (0,0) if its final size is determined by property might also be zero (0,0) if its final size is determined by
bindings. \l{Setting Bindings}{property bindings}.
To experiment with different component sizes, enter values in the To experiment with different component sizes, enter values in the
\uicontrol {Override Width} and \uicontrol {Override Height} fields (1) on \uicontrol {Override Width} and \uicontrol {Override Height} fields (1) on
the canvas toolbar. The changes are displayed in the \uicontrol {Form Editor} the toolbar. The changes are displayed in the \uicontrol {Form Editor}
view (2) and in the \uicontrol States view (3), but the property view (2) and in the \uicontrol States view (3), but the property
values are not changed permanently in the QML file. You can permanently values are not changed permanently in the UI file. You can permanently
change the property values in the \uicontrol Properties view (4). change the property values in the \uicontrol Properties view (4).
\image qmldesigner-preview-size.png "Canvas width and height" \image qmldesigner-preview-size.png "Component width and height"
To set the initial size of the root item, select \uicontrol Tools > To set the initial size of the root component, select \uicontrol Tools >
\uicontrol Options > \uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer} and \uicontrol Options > \uicontrol {Qt Quick} > \uicontrol {Qt Quick Designer} and
specify the item width and height in the \uicontrol {Root Item Init Size} specify the component width and height in the \uicontrol {Root Item Init Size}
group. group.
\section1 Specifying Canvas Size \section1 Specifying Canvas Size
@@ -167,8 +232,8 @@
\section1 Setting Canvas Color \section1 Setting Canvas Color
If you set the background of the root item of your component transparent, If you set the background of the root component transparent, the color of
the canvas color can make it difficult to see the component you are working the working area can make it difficult to see the component you are working
on. To make components more visible, you can select the canvas color in on. To make components more visible, you can select the canvas color in
the \inlineimage icons/canvas-color.png the \inlineimage icons/canvas-color.png
list. By default, the color is transparent. Setting the canvas color does list. By default, the color is transparent. Setting the canvas color does
@@ -176,13 +241,14 @@
\image qmldesigner-canvas-color.png "Transparent canvas color for a transparent component" \image qmldesigner-canvas-color.png "Transparent canvas color for a transparent component"
\section1 Refreshing the Form Editor Contents \section1 Refreshing Form Editor Contents
When you open QML files in the Design mode, the items in the file are drawn When you open a UI file, the components in the file are drawn in
in \uicontrol {Form Editor}. When you edit the item properties, the QML \uicontrol {Form Editor}. When you edit component properties in
file and the contents of the editor might get out of sync. For example, when \l Properties, the code and its representation in \uicontrol {Form Editor}
you change the position of an item within a column or a row, the new might get out of sync. For example, when you change the position of a
position might not be displayed correctly in \uicontrol {Form Editor}. component within a column or a row, the new position might not be displayed
correctly in \uicontrol {Form Editor}.
To refresh the contents of \uicontrol {Form Editor}, press \key R or To refresh the contents of \uicontrol {Form Editor}, press \key R or
select the \inlineimage reset.png select the \inlineimage reset.png

View File

@@ -71,7 +71,7 @@
The value of the \uicontrol {Custom ID} field specifies the name of an The value of the \uicontrol {Custom ID} field specifies the name of an
\l{Annotating Designs}{annotation}. \l{Annotating Designs}{annotation}.
\section2 Geometry \section2 2D Geometry
In the \uicontrol Position group, you can set the position of a component on In the \uicontrol Position group, you can set the position of a component on
the x and y axis. The position of a component in the UI can be either the x and y axis. The position of a component in the UI can be either
@@ -83,7 +83,7 @@
it in the \uicontrol Z field in the \uicontrol Advanced tab. it in the \uicontrol Z field in the \uicontrol Advanced tab.
In the \uicontrol Size group, you can set the width and height of a In the \uicontrol Size group, you can set the width and height of a
component. You can also use the resize cursor to \l{Resizing 2D Items} component. You can also use the resize cursor to \l{Resizing 2D Components}
{resize 2D components} in \uicontrol {Form Editor} or the scaling gizmo {resize 2D components} in \uicontrol {Form Editor} or the scaling gizmo
to \l{Scaling Items}{scale 3D components} in \uicontrol {3D Editor}. to \l{Scaling Items}{scale 3D components} in \uicontrol {3D Editor}.
The values in the \uicontrol X and \uicontrol Y fields change accordingly. The values in the \uicontrol X and \uicontrol Y fields change accordingly.

View File

@@ -61,6 +61,8 @@
\li Show a different view. \li Show a different view.
\endlist \endlist
You can animate transitions between states in \l{Transition Editor}.
\section1 Creating States \section1 Creating States
To open the \uicontrol States view, select \uicontrol View > To open the \uicontrol States view, select \uicontrol View >
@@ -208,6 +210,4 @@
\if defined(qtcreator) \if defined(qtcreator)
\include qtquick-states-scxml.qdocinc scxml state machines \include qtquick-states-scxml.qdocinc scxml state machines
\endif \endif
\include qtquick-transition-editor.qdocinc transition editor
*/ */

View File

@@ -0,0 +1,143 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
**
****************************************************************************/
/*!
\page qtquick-transition-editor.html
\previouspage qtquick-states-view.html
\nextpage qtquick-timeline-view.html
\title Transition Editor
To make movement between states smooth, you can use
\uicontrol {Transition Editor} to animate the changes between
states.
First, you need to \l{Adding States}{add states} in the \l States view
and \l{Specifying Component Properties}{edit some properties} that can be
animated, such as colors or numbers, in the \l Properties view. For example,
you can animate the changes in the position of a component.
\image qtquick-transition-editor-view.png "Transition Editor view"
In \uicontrol {Transition Editor}, you can set the start frame, end
frame, and duration for the transition of each property. You can also
set an \l{Editing Easing Curves}{easing curve} for each animation and
the maximum duration of the whole transition.
\section1 Zooming in Transition Editor
Use the slider on the toolbar to set the zooming level in
\uicontrol {Transition Editor}. Select the \inlineimage zoom_small.png
and \inlineimage zoom_big.png
buttons to zoom out of or into the view.
\section1 Summary of Transition Editor Toolbar Actions
\table
\header
\li Button/Field
\li Action
\li Read More
\row
\li \inlineimage animation.png
\li Opens \uicontrol {Transition Settings} dialog for editing
transition settings.
\li \l{Specifying Transition Settings}
\row
\li Transition ID
\li Displays a list of transitions that you can open in
\uicontrol {Transition Editor}.
\li \l{Animating Transitions Between States}
\row
\li \inlineimage curve_editor.png
\li Opens \uicontrol {Easing Curve Editor} for attaching an easing
curve to the selected transition.
\li \l{Editing Easing Curves}
\row
\li \inlineimage zoom_small.png
\li \uicontrol {Zoom Out} (\key Ctrl+-): zooms out of the view.
\li \l{Zooming in Transition Editor}
\row
\li Slider
\li Sets the zooming level.
\li \l{Zooming in Transition Editor}
\row
\li \inlineimage zoom_big.png
\li \uicontrol {Zoom In} (\key Ctrl++): zooms into the view.
\li \l{Zooming in Transition Editor}
\row
\li Maximum Duration
\li Specifies the maximum duration of the transition.
\li
\endtable
\section1 Animating Transitions Between States
To animate transitions:
\list 1
\li Select \uicontrol View > \uicontrol Views >
\uicontrol {Transition Editor}.
\image qmldesigner-transition-editor-startup.png "Empty Transition Editor"
\li Select the \inlineimage plus.png
(\uicontrol {Add Transition}) button to add a transition. This
works only if you have added at least one state and modified at
least one property in it.
\image qtquick-transition-editor-view.png "Transition Editor view"
\li Move the blue bar next to the component or property name to set
the start and end frame of the animation of the property. Pull its
left and right edges to set the duration of the animation.
\li To attach an \l{Editing Easing Curves}{easing curve} to the
selected transition, select the \inlineimage curve_editor.png
(\uicontrol {Easing Curve Editor (C)}) button.
\endlist
\section1 Specifying Transition Settings
To modify transition settings, select the \inlineimage animation.png
(\uicontrol {Transition Settings (S)}) button in
\uicontrol {Transition Editor}.
\image qtquick-transition-editor-settings.png "Transition settings"
To add transitions:
\list 1
\li Select the \inlineimage plus.png
(\uicontrol {Add Transition}) button.
\li In the \uicontrol {Transition ID} field, enter an ID for the
transition.
\li In the \uicontrol From field, select the state to transition from.
\li In the \uicontrol To field, select the state to transition to.
\endlist
To remove the current transition, select the \inlineimage minus.png
(\uicontrol {Remove Transition}) button.
\if defined(qtcreator)
For an example of animating transitions between states, see
\l {Creating a Qt Quick Application}.
\endif
*/

View File

@@ -1,73 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
**
****************************************************************************/
/*!
//! [transition editor]
\section1 Animating Transitions Between States
To make movement between states smooth, you can use
\uicontrol {Transition Editor} to animate the changes between
states. First, you need to \l{Creating States}{add states} in
the \uicontrol States view and \l{Specifying Component Properties}
{edit some properties} that can be animated, such as colors or
numbers, in the \uicontrol Properties view. For example, you
can animate the changes in the position of an object.
In \uicontrol {Transition Editor}, you can set the start frame, end
frame, and duration for the transition of each property. You can also
set an easing curve for each transition.
Use the slider on the menu bar to the zooming level in the view.
To add transitions:
\list 1
\li Select \uicontrol View > \uicontrol Views >
\uicontrol {Transition Editor} to display the view.
\li Select the \inlineimage plus.png
(\uicontrol {Add Transition}) button to add a transition. This
works only if you have added at least one state and modified at
least one property in it.
\image qtquick-transition-editor-view.png "Transition Editor view"
\li Move the blue bar next to the component or property name to set
the start and end frame of the animation of the property. Pull its
left and right edges to set the duration of the animation.
\li To attach an easing curve to a transition, select
\inlineimage curve_editor.png
(\uicontrol {Easing Curve Editor (C)}) on the toolbar. For more
information, see \l{Editing Easing Curves}.
\li To modify transition settings, select the \inlineimage animation.png
(\uicontrol {Transition Settings (S)}) button on the toolbar.
\image qtquick-transition-editor-settings.png "Transition settings"
\endlist
\if defined(qtcreator)
For an example of animating transitions between states, see
\l {Creating a Qt Quick Application}.
\endif
//! [transition editor]
*/

View File

@@ -62,6 +62,7 @@
\li \l{Library} \li \l{Library}
\li \l{Navigator} \li \l{Navigator}
\li \l{Properties} \li \l{Properties}
\li \l{Transition Editor}
\endlist \endlist
\li \l{Managing Workspaces} \li \l{Managing Workspaces}
\li \l{Managing Sessions} \li \l{Managing Sessions}

View File

@@ -787,8 +787,6 @@ class Dumper(DumperBase):
def removeTypePrefix(self, name): def removeTypePrefix(self, name):
return re.sub('^(struct|class|union|enum|typedef) ', '', name) return re.sub('^(struct|class|union|enum|typedef) ', '', name)
__funcSignature_Regex__ = re.compile(r'^.+\(.*\)')
def lookupNativeType(self, name): def lookupNativeType(self, name):
#DumperBase.warn('LOOKUP TYPE NAME: %s' % name) #DumperBase.warn('LOOKUP TYPE NAME: %s' % name)
typeobj = self.typeCache.get(name) typeobj = self.typeCache.get(name)
@@ -809,7 +807,7 @@ class Dumper(DumperBase):
# Note that specifying a prefix like enum or typedef or class will make the call fail to # Note that specifying a prefix like enum or typedef or class will make the call fail to
# find the type, thus the prefix is stripped. # find the type, thus the prefix is stripped.
nonPrefixedName = self.canonicalTypeName(self.removeTypePrefix(name)) nonPrefixedName = self.canonicalTypeName(self.removeTypePrefix(name))
if __funcSignature_Regex__.match(nonPrefixedName) is not None: if re.match(r'^.+\(.*\)', nonPrefixedName) is not None:
return lldb.SBType() return lldb.SBType()
typeobjlist = self.target.FindTypes(nonPrefixedName) typeobjlist = self.target.FindTypes(nonPrefixedName)
@@ -851,7 +849,7 @@ class Dumper(DumperBase):
def lookupNativeTypeInAllModules(self, name): def lookupNativeTypeInAllModules(self, name):
needle = self.canonicalTypeName(name) needle = self.canonicalTypeName(name)
#DumperBase.warn('NEEDLE: %s ' % needle) #DumperBase.warn('NEEDLE: %s ' % needle)
self.warn('Searching for type %s across all target modules, this could be very slow' % name) DumperBase.warn('Searching for type %s across all target modules, this could be very slow' % name)
for i in range(self.target.GetNumModules()): for i in range(self.target.GetNumModules()):
module = self.target.GetModuleAtIndex(i) module = self.target.GetModuleAtIndex(i)
# SBModule.GetType is new somewhere after early 300.x # SBModule.GetType is new somewhere after early 300.x

View File

@@ -13,7 +13,6 @@ versionAtLeast(QT_VERSION, 5.15.0) {
HEADERS += $$PWD/qt5nodeinstanceserver.h \ HEADERS += $$PWD/qt5nodeinstanceserver.h \
$$PWD/capturenodeinstanceserverdispatcher.h \ $$PWD/capturenodeinstanceserverdispatcher.h \
$$PWD/capturescenecreatedcommand.h \
$$PWD/nodeinstanceserverdispatcher.h \ $$PWD/nodeinstanceserverdispatcher.h \
$$PWD/qt5captureimagenodeinstanceserver.h \ $$PWD/qt5captureimagenodeinstanceserver.h \
$$PWD/qt5capturepreviewnodeinstanceserver.h \ $$PWD/qt5capturepreviewnodeinstanceserver.h \

View File

@@ -29,6 +29,9 @@ import QtQuickDesignerTheme 1.0
import HelperWidgets 2.0 import HelperWidgets 2.0
Item { Item {
id: delegateRoot
signal showContextMenu()
Rectangle { Rectangle {
anchors.rightMargin: 1 anchors.rightMargin: 1
anchors.topMargin: 1 anchors.topMargin: 1
@@ -71,11 +74,12 @@ Item {
ImagePreviewTooltipArea { ImagePreviewTooltipArea {
id: mouseRegion id: mouseRegion
anchors.fill: parent anchors.fill: parent
onShowContextMenu: delegateRoot.showContextMenu()
onPressed: { onPressed: {
rootView.startDragAndDrop(itemLibraryEntry) if (mouse.button === Qt.LeftButton)
rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y))
} }
} }
} }

View File

@@ -77,11 +77,14 @@ ScrollView {
id: itemsView id: itemsView
property string importToRemove: "" property string importToRemove: ""
property string importToAdd: ""
property var currentItem: 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()
{ {
contextMenu.close() importContextMenu.close()
itemContextMenu.close()
} }
Item { Item {
@@ -99,11 +102,11 @@ ScrollView {
2 * cellVerticalMargin + cellVerticalSpacing 2 * cellVerticalMargin + cellVerticalSpacing
StudioControls.Menu { StudioControls.Menu {
id: contextMenu id: importContextMenu
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Remove Module") text: qsTr("Remove Module")
enabled: importToRemove !== "" && importToRemove !== "QtQuick" enabled: importToRemove !== ""
onTriggered: rootView.removeImport(importToRemove) onTriggered: rootView.removeImport(importToRemove)
} }
@@ -119,6 +122,19 @@ ScrollView {
onTriggered: itemLibraryModel.collapseAll() onTriggered: itemLibraryModel.collapseAll()
} }
} }
StudioControls.Menu {
id: itemContextMenu
// Workaround for menu item implicit width not properly propagating to menu
width: importMenuItem.implicitWidth
StudioControls.MenuItem {
id: importMenuItem
text: qsTr("Import Module: ") + importToAdd
enabled: currentItem
onTriggered: rootView.addImportForItem(currentItem)
}
}
} }
Column { Column {
@@ -144,8 +160,8 @@ ScrollView {
importExpanded = !importExpanded importExpanded = !importExpanded
} }
onShowContextMenu: { onShowContextMenu: {
importToRemove = importUsed ? "" : importUrl importToRemove = importRemovable ? importUrl : ""
contextMenu.popup() importContextMenu.popup()
} }
Column { Column {
@@ -180,6 +196,15 @@ ScrollView {
visible: itemVisible visible: itemVisible
width: styleConstants.cellWidth + itemGrid.flexibleWidth width: styleConstants.cellWidth + itemGrid.flexibleWidth
height: styleConstants.cellHeight height: styleConstants.cellHeight
onShowContextMenu: {
if (!itemUsable) {
importToAdd = itemRequiredImport
if (importToAdd !== "") {
currentItem = itemLibraryEntry
itemContextMenu.popup()
}
}
}
} }
} }
} }

View File

@@ -30,12 +30,19 @@ import QtQuick.Layouts 1.0
MouseArea { MouseArea {
id: mouseArea id: mouseArea
signal showContextMenu()
onExited: tooltipBackend.hideTooltip() onExited: tooltipBackend.hideTooltip()
onCanceled: tooltipBackend.hideTooltip() onCanceled: tooltipBackend.hideTooltip()
onClicked: forceActiveFocus()
onPositionChanged: tooltipBackend.reposition() onPositionChanged: tooltipBackend.reposition()
onClicked: {
forceActiveFocus()
if (mouse.button === Qt.RightButton)
showContextMenu()
}
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton
Timer { Timer {
interval: 1000 interval: 1000

View File

@@ -17,3 +17,11 @@ add_qtc_library(ExtensionSystem
pluginmanager_p.h pluginmanager_p.h
SKIP_AUTOMOC pluginmanager.cpp SKIP_AUTOMOC pluginmanager.cpp
) )
find_package(Qt5 COMPONENTS Test QUIET)
extend_qtc_library(ExtensionSystem
CONDITION TARGET Qt5::Test
DEPENDS Qt5::Test
DEFINES WITH_TESTS
)

View File

@@ -1474,7 +1474,7 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
return; return;
std::unique_ptr<LockFile> lockFile; std::unique_ptr<LockFile> lockFile;
if (enableCrashCheck) if (enableCrashCheck && destState < PluginSpec::Stopped)
lockFile.reset(new LockFile(this, spec)); lockFile.reset(new LockFile(this, spec));
switch (destState) { switch (destState) {

View File

@@ -5,6 +5,8 @@ if (WITH_TESTS)
endif() endif()
add_qtc_library(Tracing add_qtc_library(Tracing
CONDITION Qt5_VERSION VERSION_LESS 6.0.0
FEATURE_INFO
DEPENDS Utils Qt5::Qml Qt5::Quick DEPENDS Utils Qt5::Qml Qt5::Quick
PUBLIC_DEPENDS Qt5::Widgets PUBLIC_DEPENDS Qt5::Widgets
SOURCES ${TEST_SOURCES} SOURCES ${TEST_SOURCES}

View File

@@ -1131,7 +1131,9 @@ void StringAspect::update()
} }
if (d->m_textEditDisplay) { if (d->m_textEditDisplay) {
d->m_textEditDisplay->setText(displayedString); const QString old = d->m_textEditDisplay->document()->toPlainText();
if (displayedString != old)
d->m_textEditDisplay->setText(displayedString);
d->updateWidgetFromCheckStatus(d->m_textEditDisplay.data()); d->updateWidgetFromCheckStatus(d->m_textEditDisplay.data());
} }

View File

@@ -519,15 +519,14 @@ void CMakeBuildSettingsWidget::updateButtonState()
break; break;
case CMakeProjectManager::ConfigModel::DataItem::UNKNOWN: case CMakeProjectManager::ConfigModel::DataItem::UNKNOWN:
default: default:
ni.type = CMakeConfigItem::INTERNAL; ni.type = CMakeConfigItem::UNINITIALIZED;
break; break;
} }
return ni; return ni;
}); });
m_resetButton->setEnabled(m_configModel->hasChanges() && !isParsing); m_resetButton->setEnabled(m_configModel->hasChanges() && !isParsing);
m_reconfigureButton->setEnabled((!configChanges.isEmpty() || m_configModel->hasCMakeChanges()) m_reconfigureButton->setEnabled(!configChanges.isEmpty() && !isParsing);
&& !isParsing);
m_buildConfiguration->setConfigurationChanges(configChanges); m_buildConfiguration->setConfigurationChanges(configChanges);
} }

View File

@@ -56,6 +56,7 @@
#include <utils/checkablemessagebox.h> #include <utils/checkablemessagebox.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/macroexpander.h>
#include <utils/mimetypes/mimetype.h> #include <utils/mimetypes/mimetype.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -283,9 +284,8 @@ void CMakeBuildSystem::triggerParsing()
} }
if ((0 == (reparseParameters & REPARSE_FORCE_EXTRA_CONFIGURATION)) if ((0 == (reparseParameters & REPARSE_FORCE_EXTRA_CONFIGURATION))
&& !m_parameters.extraCMakeArguments.isEmpty()) { && mustApplyExtraArguments(m_parameters)) {
if (mustApplyExtraArguments()) reparseParameters |= REPARSE_FORCE_CMAKE_RUN | REPARSE_FORCE_EXTRA_CONFIGURATION;
reparseParameters |= REPARSE_FORCE_CMAKE_RUN | REPARSE_FORCE_EXTRA_CONFIGURATION;
} }
qCDebug(cmakeBuildSystemLog) << "Asking reader to parse"; qCDebug(cmakeBuildSystemLog) << "Asking reader to parse";
@@ -372,6 +372,27 @@ QString CMakeBuildSystem::reparseParametersString(int reparseFlags)
return result.trimmed(); return result.trimmed();
} }
void CMakeBuildSystem::writeConfigurationIntoBuildDirectory()
{
const Utils::MacroExpander *expander = cmakeBuildConfiguration()->macroExpander();
const FilePath buildDir = workDirectory(m_parameters);
QTC_ASSERT(buildDir.exists(), return );
const FilePath settingsFile = buildDir.pathAppended("qtcsettings.cmake");
QByteArray contents;
contents.append("# This file is managed by Qt Creator, do not edit!\n\n");
contents.append(
transform(cmakeBuildConfiguration()->configurationChanges(),
[expander](const CMakeConfigItem &item) { return item.toCMakeSetLine(expander); })
.join('\n')
.toUtf8());
QFile file(settingsFile.toString());
QTC_ASSERT(file.open(QFile::WriteOnly | QFile::Truncate), return );
file.write(contents);
}
void CMakeBuildSystem::setParametersAndRequestParse(const BuildDirParameters &parameters, void CMakeBuildSystem::setParametersAndRequestParse(const BuildDirParameters &parameters,
const int reparseParameters) const int reparseParameters)
{ {
@@ -405,6 +426,8 @@ void CMakeBuildSystem::setParametersAndRequestParse(const BuildDirParameters &pa
m_reader.setParameters(m_parameters); m_reader.setParameters(m_parameters);
writeConfigurationIntoBuildDirectory();
if (reparseParameters & REPARSE_URGENT) { if (reparseParameters & REPARSE_URGENT) {
qCDebug(cmakeBuildSystemLog) << "calling requestReparse"; qCDebug(cmakeBuildSystemLog) << "calling requestReparse";
requestParse(); requestParse();
@@ -414,15 +437,15 @@ void CMakeBuildSystem::setParametersAndRequestParse(const BuildDirParameters &pa
} }
} }
bool CMakeBuildSystem::mustApplyExtraArguments() const bool CMakeBuildSystem::mustApplyExtraArguments(const BuildDirParameters &parameters) const
{ {
if (m_parameters.extraCMakeArguments.isEmpty()) if (parameters.extraCMakeArguments.isEmpty())
return false; return false;
auto answer = QMessageBox::question(Core::ICore::mainWindow(), auto answer = QMessageBox::question(Core::ICore::mainWindow(),
tr("Apply configuration changes?"), tr("Apply configuration changes?"),
tr("Run CMake with \"%1\"?") tr("Run CMake with \"%1\"?")
.arg(m_parameters.extraCMakeArguments.join(" ")), .arg(parameters.extraCMakeArguments.join(" ")),
QMessageBox::Apply | QMessageBox::Discard, QMessageBox::Apply | QMessageBox::Discard,
QMessageBox::Apply); QMessageBox::Apply);
return answer == QMessageBox::Apply; return answer == QMessageBox::Apply;
@@ -482,12 +505,10 @@ bool CMakeBuildSystem::persistCMakeState()
qCDebug(cmakeBuildSystemLog) << "Checking whether build system needs to be persisted:" qCDebug(cmakeBuildSystemLog) << "Checking whether build system needs to be persisted:"
<< "workdir:" << parameters.workDirectory << "workdir:" << parameters.workDirectory
<< "buildDir:" << parameters.buildDirectory << "buildDir:" << parameters.buildDirectory
<< "Has extraargs:" << !parameters.extraCMakeArguments.isEmpty() << "Has extraargs:" << !parameters.extraCMakeArguments.isEmpty();
<< "must apply extra Args:"
<< mustApplyExtraArguments();
if (parameters.workDirectory == parameters.buildDirectory if (parameters.workDirectory == parameters.buildDirectory
&& !parameters.extraCMakeArguments.isEmpty() && mustApplyExtraArguments()) { && mustApplyExtraArguments(parameters)) {
reparseFlags = REPARSE_FORCE_EXTRA_CONFIGURATION; reparseFlags = REPARSE_FORCE_EXTRA_CONFIGURATION;
qCDebug(cmakeBuildSystemLog) << " -> must run CMake with extra arguments."; qCDebug(cmakeBuildSystemLog) << " -> must run CMake with extra arguments.";
} }

View File

@@ -29,7 +29,6 @@
#include "cmakebuildtarget.h" #include "cmakebuildtarget.h"
#include "cmakeprojectnodes.h" #include "cmakeprojectnodes.h"
#include "fileapireader.h" #include "fileapireader.h"
#include "utils/macroexpander.h"
#include <projectexplorer/buildsystem.h> #include <projectexplorer/buildsystem.h>
@@ -117,7 +116,7 @@ private:
void setParametersAndRequestParse(const BuildDirParameters &parameters, void setParametersAndRequestParse(const BuildDirParameters &parameters,
const int reparseParameters); const int reparseParameters);
bool mustApplyExtraArguments() const; bool mustApplyExtraArguments(const BuildDirParameters &parameters) const;
// State handling: // State handling:
// Parser states: // Parser states:
@@ -155,6 +154,8 @@ private:
void runCTest(); void runCTest();
void writeConfigurationIntoBuildDirectory();
ProjectExplorer::TreeScanner m_treeScanner; ProjectExplorer::TreeScanner m_treeScanner;
QHash<QString, bool> m_mimeBinaryCache; QHash<QString, bool> m_mimeBinaryCache;
QList<const ProjectExplorer::FileNode *> m_allFiles; QList<const ProjectExplorer::FileNode *> m_allFiles;

View File

@@ -145,9 +145,11 @@ CMakeConfigItem::Type CMakeConfigItem::typeStringToType(const QByteArray &type)
return CMakeConfigItem::PATH; return CMakeConfigItem::PATH;
if (type == "STATIC") if (type == "STATIC")
return CMakeConfigItem::STATIC; return CMakeConfigItem::STATIC;
if (type == "INTERNAL")
return CMakeConfigItem::INTERNAL;
QTC_CHECK(type == "INTERNAL" || type == "UNINITIALIZED"); QTC_CHECK(type == "UNINITIALIZED");
return CMakeConfigItem::INTERNAL; return CMakeConfigItem::UNINITIALIZED;
} }
QString CMakeConfigItem::typeToTypeString(const CMakeConfigItem::Type t) QString CMakeConfigItem::typeToTypeString(const CMakeConfigItem::Type t)
@@ -163,8 +165,10 @@ QString CMakeConfigItem::typeToTypeString(const CMakeConfigItem::Type t)
return {"INTERNAL"}; return {"INTERNAL"};
case CMakeProjectManager::CMakeConfigItem::STATIC: case CMakeProjectManager::CMakeConfigItem::STATIC:
return {"STATIC"}; return {"STATIC"};
case CMakeConfigItem::BOOL: case CMakeProjectManager::CMakeConfigItem::BOOL:
return {"BOOL"}; return {"BOOL"};
case CMakeProjectManager::CMakeConfigItem::UNINITIALIZED:
return {"UNINITIALIZED"};
} }
QTC_CHECK(false); QTC_CHECK(false);
return {}; return {};
@@ -418,6 +422,9 @@ QString CMakeConfigItem::toString(const Utils::MacroExpander *expander) const
case CMakeProjectManager::CMakeConfigItem::INTERNAL: case CMakeProjectManager::CMakeConfigItem::INTERNAL:
typeStr = QLatin1String("INTERNAL"); typeStr = QLatin1String("INTERNAL");
break; break;
case CMakeProjectManager::CMakeConfigItem::UNINITIALIZED:
typeStr = QLatin1String("UNINITIALIZED");
break;
case CMakeProjectManager::CMakeConfigItem::STRING: case CMakeProjectManager::CMakeConfigItem::STRING:
default: default:
typeStr = QLatin1String("STRING"); typeStr = QLatin1String("STRING");

View File

@@ -45,7 +45,7 @@ namespace CMakeProjectManager {
class CMAKE_EXPORT CMakeConfigItem { class CMAKE_EXPORT CMakeConfigItem {
public: public:
enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC }; enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC, UNINITIALIZED };
CMakeConfigItem(); CMakeConfigItem();
CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v, const QStringList &s = {}); CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v, const QStringList &s = {});
CMakeConfigItem(const QByteArray &k, const QByteArray &v); CMakeConfigItem(const QByteArray &k, const QByteArray &v);

View File

@@ -46,7 +46,9 @@ CMakeInputsNode::CMakeInputsNode(const Utils::FilePath &cmakeLists) :
{ {
setPriority(Node::DefaultPriority - 10); // Bottom most! setPriority(Node::DefaultPriority - 10); // Bottom most!
setDisplayName(QCoreApplication::translate("CMakeFilesProjectNode", "CMake Modules")); setDisplayName(QCoreApplication::translate("CMakeFilesProjectNode", "CMake Modules"));
setIcon(QIcon(":/projectexplorer/images/session.png")); // TODO: Use a better icon! static const QIcon modulesIcon = Core::FileIconProvider::directoryIcon(
ProjectExplorer::Constants::FILEOVERLAY_MODULES);
setIcon(modulesIcon);
setListInProject(false); setListInProject(false);
} }

View File

@@ -123,11 +123,6 @@ bool ConfigModel::hasChanges() const
}); });
} }
bool ConfigModel::hasCMakeChanges() const
{
return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isCMakeChanged; });
}
bool ConfigModel::canForceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type) const bool ConfigModel::canForceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type) const
{ {
if (idx.model() != const_cast<ConfigModel *>(this) || idx.column() != 1) if (idx.model() != const_cast<ConfigModel *>(this) || idx.column() != 1)
@@ -264,7 +259,6 @@ void ConfigModel::setConfiguration(const QList<ConfigModel::InternalDataItem> &c
// merge old/new entry: // merge old/new entry:
InternalDataItem item(*newIt); InternalDataItem item(*newIt);
item.newValue = (newIt->value != oldIt->newValue) ? oldIt->newValue : QString(); item.newValue = (newIt->value != oldIt->newValue) ? oldIt->newValue : QString();
item.isCMakeChanged = (oldIt->value != newIt->value);
item.isUserChanged = !item.newValue.isEmpty() && (item.newValue != item.value); item.isUserChanged = !item.newValue.isEmpty() && (item.newValue != item.value);
result << item; result << item;
++newIt; ++newIt;
@@ -390,7 +384,6 @@ QVariant ConfigModelTreeItem::data(int column, int role) const
return toolTip(); return toolTip();
case Qt::FontRole: { case Qt::FontRole: {
QFont font; QFont font;
font.setItalic(dataItem->isCMakeChanged);
font.setBold(dataItem->isUserNew); font.setBold(dataItem->isUserNew);
font.setStrikeOut((!dataItem->inCMakeCache && !dataItem->isUserNew) || dataItem->isUnset); font.setStrikeOut((!dataItem->inCMakeCache && !dataItem->isUserNew) || dataItem->isUnset);
return font; return font;
@@ -414,7 +407,6 @@ QVariant ConfigModelTreeItem::data(int column, int role) const
case Qt::FontRole: { case Qt::FontRole: {
QFont font; QFont font;
font.setBold((dataItem->isUserChanged || dataItem->isUserNew) && !dataItem->isUnset); font.setBold((dataItem->isUserChanged || dataItem->isUserNew) && !dataItem->isUnset);
font.setItalic(dataItem->isCMakeChanged);
font.setStrikeOut((!dataItem->inCMakeCache && !dataItem->isUserNew) || dataItem->isUnset); font.setStrikeOut((!dataItem->inCMakeCache && !dataItem->isUserNew) || dataItem->isUnset);
return font; return font;
} }

View File

@@ -101,7 +101,7 @@ public:
cmi.type = CMakeConfigItem::STRING; cmi.type = CMakeConfigItem::STRING;
break; break;
case DataItem::UNKNOWN: case DataItem::UNKNOWN:
cmi.type = CMakeConfigItem::INTERNAL; cmi.type = CMakeConfigItem::UNINITIALIZED;
break; break;
} }
cmi.isUnset = isUnset; cmi.isUnset = isUnset;
@@ -144,7 +144,6 @@ public:
void resetAllChanges(); void resetAllChanges();
bool hasChanges() const; bool hasChanges() const;
bool hasCMakeChanges() const;
bool canForceTo(const QModelIndex &idx, const DataItem::Type type) const; bool canForceTo(const QModelIndex &idx, const DataItem::Type type) const;
void forceTo(const QModelIndex &idx, const DataItem::Type type); void forceTo(const QModelIndex &idx, const DataItem::Type type);
@@ -168,7 +167,6 @@ private:
bool isUserChanged = false; bool isUserChanged = false;
bool isUserNew = false; bool isUserNew = false;
bool isCMakeChanged = false;
QString newValue; QString newValue;
QString kitValue; QString kitValue;
}; };

View File

@@ -179,6 +179,14 @@ QVector<FolderNode::LocationInfo> extractBacktraceInformation(const BacktraceInf
return info; return info;
} }
static bool isChildOf(const FilePath &path, const QStringList &prefixes)
{
for (const QString &prefix : prefixes)
if (path.isChildOf(FilePath::fromString(prefix)))
return true;
return false;
}
QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input, QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
const FilePath &sourceDirectory, const FilePath &sourceDirectory,
const FilePath &buildDirectory) const FilePath &buildDirectory)
@@ -269,16 +277,28 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
if (f.role == "libraries") if (f.role == "libraries")
tmp = tmp.parentDir(); tmp = tmp.parentDir();
if (!tmp.isEmpty() if (!tmp.isEmpty() && tmp.isDir()) {
&& tmp.isDir()) { // f.role is libraryPath or frameworkPath // f.role is libraryPath or frameworkPath
librarySeachPaths.append(tmp); // On Linux, exclude sub-paths from "/lib(64)", "/usr/lib(64)" and
// Libraries often have their import libs in ../lib and the // "/usr/local/lib" since these are usually in the standard search
// actual dll files in ../bin on windows. Qt is one example of that. // paths. There probably are more, but the naming schemes are arbitrary
if (tmp.fileName() == "lib" && HostOsInfo::isWindowsHost()) { // so we'd need to ask the linker ("ld --verbose | grep SEARCH_DIR").
const FilePath path = tmp.parentDir().pathAppended("bin"); if (!HostOsInfo::isLinuxHost()
|| !isChildOf(tmp,
{"/lib",
"/lib64",
"/usr/lib",
"/usr/lib64",
"/usr/local/lib"})) {
librarySeachPaths.append(tmp);
// Libraries often have their import libs in ../lib and the
// actual dll files in ../bin on windows. Qt is one example of that.
if (tmp.fileName() == "lib" && HostOsInfo::isWindowsHost()) {
const FilePath path = tmp.parentDir().pathAppended("bin");
if (path.isDir()) if (path.isDir())
librarySeachPaths.append(path); librarySeachPaths.append(path);
}
} }
} }
} }

View File

@@ -892,7 +892,9 @@ FileApiData FileApiParser::parseData(const QFileInfo &replyFileInfo, const QStri
} }
auto it = std::find_if(codeModels.cbegin(), codeModels.cend(), auto it = std::find_if(codeModels.cbegin(), codeModels.cend(),
[cmakeBuildType](const Configuration& cfg) { return cfg.name == cmakeBuildType; }); [cmakeBuildType](const Configuration& cfg) {
return QString::compare(cfg.name, cmakeBuildType, Qt::CaseInsensitive) == 0;
});
if (it == codeModels.cend()) { if (it == codeModels.cend()) {
errorMessage = QString("No '%1' CMake configuration found!").arg(cmakeBuildType); errorMessage = QString("No '%1' CMake configuration found!").arg(cmakeBuildType);
qWarning() << errorMessage; qWarning() << errorMessage;

View File

@@ -321,9 +321,10 @@ void FileApiReader::makeBackupConfiguration(bool store)
if (!store) if (!store)
std::swap(cmakeCacheTxt, cmakeCacheTxtPrev); std::swap(cmakeCacheTxt, cmakeCacheTxtPrev);
if (!FileUtils::copyIfDifferent(cmakeCacheTxt, cmakeCacheTxtPrev)) if (cmakeCacheTxt.exists())
Core::MessageManager::writeFlashing(tr("Failed to copy %1 to %2.") if (!FileUtils::copyIfDifferent(cmakeCacheTxt, cmakeCacheTxtPrev))
.arg(cmakeCacheTxt.toString(), cmakeCacheTxtPrev.toString())); Core::MessageManager::writeFlashing(tr("Failed to copy %1 to %2.")
.arg(cmakeCacheTxt.toString(), cmakeCacheTxtPrev.toString()));
} }

View File

@@ -57,7 +57,7 @@ IWelcomePage::~IWelcomePage()
g_welcomePages.removeOne(this); g_welcomePages.removeOne(this);
} }
static QPalette buttonPalette(bool isActive, bool isCursorInside, bool forText) QPalette WelcomePageFrame::buttonPalette(bool isActive, bool isCursorInside, bool forText)
{ {
QPalette pal; QPalette pal;
Theme *theme = Utils::creatorTheme(); Theme *theme = Utils::creatorTheme();
@@ -174,8 +174,8 @@ bool WelcomePageButtonPrivate::isActive() const
void WelcomePageButtonPrivate::doUpdate(bool cursorInside) void WelcomePageButtonPrivate::doUpdate(bool cursorInside)
{ {
const bool active = isActive(); const bool active = isActive();
q->setPalette(buttonPalette(active, cursorInside, false)); q->setPalette(WelcomePageFrame::buttonPalette(active, cursorInside, false));
const QPalette lpal = buttonPalette(active, cursorInside, true); const QPalette lpal = WelcomePageFrame::buttonPalette(active, cursorInside, true);
m_label->setPalette(lpal); m_label->setPalette(lpal);
if (m_icon) if (m_icon)
m_icon->setPalette(lpal); m_icon->setPalette(lpal);

View File

@@ -68,6 +68,8 @@ public:
WelcomePageFrame(QWidget *parent); WelcomePageFrame(QWidget *parent);
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
static QPalette buttonPalette(bool isActive, bool isCursorInside, bool forText);
}; };
class CORE_EXPORT WelcomePageButton : public WelcomePageFrame class CORE_EXPORT WelcomePageButton : public WelcomePageFrame

View File

@@ -171,6 +171,12 @@ ThemeChooser::~ThemeChooser()
delete d; delete d;
} }
static QString defaultThemeId()
{
return Theme::systemUsesDarkMode() ? QString(Constants::DEFAULT_DARK_THEME)
: QString(Constants::DEFAULT_THEME);
}
void ThemeChooser::apply() void ThemeChooser::apply()
{ {
const int index = d->m_themeComboBox->currentIndex(); const int index = d->m_themeComboBox->currentIndex();
@@ -181,9 +187,7 @@ void ThemeChooser::apply()
const QString currentThemeId = ThemeEntry::themeSetting().toString(); const QString currentThemeId = ThemeEntry::themeSetting().toString();
if (currentThemeId != themeId) { if (currentThemeId != themeId) {
// save filename of selected theme in global config // save filename of selected theme in global config
settings->setValueWithDefault(Constants::SETTINGS_THEME, settings->setValueWithDefault(Constants::SETTINGS_THEME, themeId, defaultThemeId());
themeId,
QString(Constants::DEFAULT_THEME));
RestartDialog restartDialog(ICore::dialogParent(), RestartDialog restartDialog(ICore::dialogParent(),
tr("The theme change will take effect after restart.")); tr("The theme change will take effect after restart."));
restartDialog.exec(); restartDialog.exec();
@@ -225,10 +229,8 @@ QList<ThemeEntry> ThemeEntry::availableThemes()
Id ThemeEntry::themeSetting() Id ThemeEntry::themeSetting()
{ {
auto defaultId = Theme::systemUsesDarkMode() ? Constants::DEFAULT_DARK_THEME
: Constants::DEFAULT_THEME;
const Id setting = Id::fromSetting( const Id setting = Id::fromSetting(
ICore::settings()->value(Constants::SETTINGS_THEME, defaultId)); ICore::settings()->value(Constants::SETTINGS_THEME, defaultThemeId()));
const QList<ThemeEntry> themes = availableThemes(); const QList<ThemeEntry> themes = availableThemes();
if (themes.empty()) if (themes.empty())

View File

@@ -57,15 +57,17 @@ static QFont sizedFont(int size, const QWidget *widget)
SearchBox::SearchBox(QWidget *parent) SearchBox::SearchBox(QWidget *parent)
: WelcomePageFrame(parent) : WelcomePageFrame(parent)
{ {
QPalette pal; QPalette pal = buttonPalette(false, false, true);
pal.setColor(QPalette::Base, themeColor(Theme::Welcome_BackgroundColor)); pal.setColor(QPalette::Base, themeColor(Theme::Welcome_BackgroundColor));
// for macOS dark mode
pal.setColor(QPalette::Text, themeColor(Theme::Welcome_TextColor));
setPalette(pal);
m_lineEdit = new FancyLineEdit; m_lineEdit = new FancyLineEdit;
m_lineEdit->setFiltering(true); m_lineEdit->setFiltering(true);
m_lineEdit->setFrame(false); m_lineEdit->setFrame(false);
m_lineEdit->setFont(sizedFont(14, this)); m_lineEdit->setFont(sizedFont(14, this));
m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false); m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
m_lineEdit->setPalette(pal);
auto box = new QHBoxLayout(this); auto box = new QHBoxLayout(this);
box->setContentsMargins(10, 3, 3, 3); box->setContentsMargins(10, 3, 3, 3);
@@ -84,6 +86,7 @@ GridView::GridView(QWidget *parent)
setSelectionMode(QAbstractItemView::NoSelection); setSelectionMode(QAbstractItemView::NoSelection);
setFrameShape(QFrame::NoFrame); setFrameShape(QFrame::NoFrame);
setGridStyle(Qt::NoPen); setGridStyle(Qt::NoPen);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QPalette pal; QPalette pal;
pal.setColor(QPalette::Base, themeColor(Theme::Welcome_BackgroundColor)); pal.setColor(QPalette::Base, themeColor(Theme::Welcome_BackgroundColor));

View File

@@ -421,6 +421,7 @@ static void addSearchResults(CppTools::Usages usages, SearchResult &search, cons
item.setFilePath(FilePath::fromString(usage.path)); item.setFilePath(FilePath::fromString(usage.path));
item.setLineText(lineContent); item.setLineText(lineContent);
item.setMainRange(range); item.setMainRange(range);
item.setUseTextEditorFont(true);
search.addResult(item); search.addResult(item);
} }
} }

View File

@@ -636,6 +636,7 @@ static void displayResults(SearchResult *search, QFutureWatcher<CPlusPlus::Usage
item.setLineText(result.lineText); item.setLineText(result.lineText);
item.setUserData(int(result.type)); item.setUserData(int(result.type));
item.setStyle(colorStyleForUsageType(result.type)); item.setStyle(colorStyleForUsageType(result.type));
item.setUseTextEditorFont(true);
search->addResult(item); search->addResult(item);
if (parameters.prettySymbolName.isEmpty()) if (parameters.prettySymbolName.isEmpty())
@@ -831,6 +832,7 @@ void CppFindReferences::findMacroUses(const CPlusPlus::Macro &macro, const QStri
item.setFilePath(Utils::FilePath::fromString(macro.fileName())); item.setFilePath(Utils::FilePath::fromString(macro.fileName()));
item.setLineText(line); item.setLineText(line);
item.setMainRange(macro.line(), column, macro.nameToQString().length()); item.setMainRange(macro.line(), column, macro.nameToQString().length());
item.setUseTextEditorFont(true);
search->addResult(item); search->addResult(item);
} }

View File

@@ -31,6 +31,7 @@
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
#include <texteditor/textdocumentlayout.h> #include <texteditor/textdocumentlayout.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QLoggingCategory> #include <QLoggingCategory>
@@ -45,6 +46,8 @@ static Q_LOGGING_CATEGORY(log, "qtc.cpptools.semantichighlighter", QtWarningMsg)
namespace CppTools { namespace CppTools {
static Utils::Id parenSource() { return "CppTools"; }
static const QList<std::pair<HighlightingResult, QTextBlock>> static const QList<std::pair<HighlightingResult, QTextBlock>>
splitRawStringLiteral(const HighlightingResult &result, const QTextBlock &startBlock) splitRawStringLiteral(const HighlightingResult &result, const QTextBlock &startBlock)
{ {
@@ -147,6 +150,13 @@ void SemanticHighlighter::run()
m_watcher->setFuture(m_highlightingRunner()); m_watcher->setFuture(m_highlightingRunner());
} }
static Parentheses getClearedParentheses(const QTextBlock &block)
{
return Utils::filtered(TextDocumentLayout::parentheses(block), [](const Parenthesis &p) {
return p.source != parenSource();
});
}
void SemanticHighlighter::onHighlighterResultAvailable(int from, int to) void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
{ {
if (documentRevision() != m_revision) if (documentRevision() != m_revision)
@@ -169,6 +179,9 @@ void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
const HighlightingResult &result = m_watcher->future().resultAt(i); const HighlightingResult &result = m_watcher->future().resultAt(i);
if (result.kind != AngleBracketOpen && result.kind != AngleBracketClose if (result.kind != AngleBracketOpen && result.kind != AngleBracketClose
&& result.kind != TernaryIf && result.kind != TernaryElse) { && result.kind != TernaryIf && result.kind != TernaryElse) {
const QTextBlock block =
m_baseTextDocument->document()->findBlockByNumber(result.line - 1);
TextDocumentLayout::setParentheses(block, getClearedParentheses(block));
continue; continue;
} }
if (parentheses.first.isValid() && result.line - 1 > parentheses.first.blockNumber()) { if (parentheses.first.isValid() && result.line - 1 > parentheses.first.blockNumber()) {
@@ -177,16 +190,20 @@ void SemanticHighlighter::onHighlighterResultAvailable(int from, int to)
} }
if (!parentheses.first.isValid()) { if (!parentheses.first.isValid()) {
parentheses.first = m_baseTextDocument->document()->findBlockByNumber(result.line - 1); parentheses.first = m_baseTextDocument->document()->findBlockByNumber(result.line - 1);
parentheses.second = TextDocumentLayout::parentheses(parentheses.first); parentheses.second = getClearedParentheses(parentheses.first);
} }
Parenthesis paren;
if (result.kind == AngleBracketOpen) if (result.kind == AngleBracketOpen)
parentheses.second << Parenthesis(Parenthesis::Opened, '<', result.column - 1); paren = {Parenthesis::Opened, '<', result.column - 1};
else if (result.kind == AngleBracketClose) else if (result.kind == AngleBracketClose)
parentheses.second << Parenthesis(Parenthesis::Closed, '>', result.column - 1); paren = {Parenthesis::Closed, '>', result.column - 1};
else if (result.kind == TernaryIf) else if (result.kind == TernaryIf)
parentheses.second << Parenthesis(Parenthesis::Opened, '?', result.column - 1); paren = {Parenthesis::Opened, '?', result.column - 1};
else if (result.kind == TernaryElse) else if (result.kind == TernaryElse)
parentheses.second << Parenthesis(Parenthesis::Closed, ':', result.column - 1); paren = {Parenthesis::Closed, ':', result.column - 1};
QTC_ASSERT(paren.pos != -1, continue);
paren.source = parenSource();
parentheses.second << paren;
} }
if (parentheses.first.isValid()) if (parentheses.first.isValid())
TextDocumentLayout::setParentheses(parentheses.first, parentheses.second); TextDocumentLayout::setParentheses(parentheses.first, parentheses.second);
@@ -202,6 +219,27 @@ void SemanticHighlighter::onHighlighterFinished()
clearExtraAdditionalFormatsUntilEnd(highlighter, m_watcher->future()); clearExtraAdditionalFormatsUntilEnd(highlighter, m_watcher->future());
} }
} }
// Clear out previous "semantic parentheses".
QTextBlock firstResultBlock;
QTextBlock lastResultBlock;
if (m_watcher->future().resultCount() == 0) {
firstResultBlock = lastResultBlock = m_baseTextDocument->document()->lastBlock();
} else {
firstResultBlock = m_baseTextDocument->document()->findBlockByNumber(
m_watcher->resultAt(0).line - 1);
lastResultBlock = m_baseTextDocument->document()->findBlockByNumber(
m_watcher->future().resultAt(m_watcher->future().resultCount() - 1).line - 1);
}
for (QTextBlock currentBlock = m_baseTextDocument->document()->firstBlock();
currentBlock != firstResultBlock; currentBlock = currentBlock.next()) {
TextDocumentLayout::setParentheses(currentBlock, getClearedParentheses(currentBlock));
}
for (QTextBlock currentBlock = lastResultBlock.next(); currentBlock.isValid();
currentBlock = currentBlock.next()) {
TextDocumentLayout::setParentheses(currentBlock, getClearedParentheses(currentBlock));
}
m_watcher.reset(); m_watcher.reset();
} }

View File

@@ -1,4 +1,5 @@
add_qtc_plugin(CtfVisualizer add_qtc_plugin(CtfVisualizer
CONDITION TARGET Tracing
DEPENDS Tracing Qt5::QuickWidgets DEPENDS Tracing Qt5::QuickWidgets
INCLUDES ${PROJECT_SOURCE_DIR}/src INCLUDES ${PROJECT_SOURCE_DIR}/src
PLUGIN_DEPENDS Core Debugger ProjectExplorer PLUGIN_DEPENDS Core Debugger ProjectExplorer

View File

@@ -79,6 +79,7 @@ constexpr char executableKey[] = "executable";
constexpr char argumentsKey[] = "arguments"; constexpr char argumentsKey[] = "arguments";
constexpr char settingsGroupKey[] = "LanguageClient"; constexpr char settingsGroupKey[] = "LanguageClient";
constexpr char clientsKey[] = "clients"; constexpr char clientsKey[] = "clients";
constexpr char typedClientsKey[] = "typedClients";
constexpr char mimeType[] = "application/language.client.setting"; constexpr char mimeType[] = "application/language.client.setting";
namespace LanguageClient { namespace LanguageClient {
@@ -615,16 +616,21 @@ QList<BaseSettings *> LanguageClientSettings::fromSettings(QSettings *settingsIn
{ {
settingsIn->beginGroup(settingsGroupKey); settingsIn->beginGroup(settingsGroupKey);
QList<BaseSettings *> result; QList<BaseSettings *> result;
for (const QVariant& var : settingsIn->value(clientsKey).toList()) {
const QMap<QString, QVariant> &map = var.toMap(); for (auto varList :
Utils::Id typeId = Utils::Id::fromSetting(map.value(typeIdKey)); {settingsIn->value(clientsKey).toList(), settingsIn->value(typedClientsKey).toList()}) {
if (!typeId.isValid()) for (const QVariant &var : varList) {
typeId = Constants::LANGUAGECLIENT_STDIO_SETTINGS_ID; const QMap<QString, QVariant> &map = var.toMap();
if (BaseSettings *settings = generateSettings(typeId)) { Utils::Id typeId = Utils::Id::fromSetting(map.value(typeIdKey));
settings->fromMap(var.toMap()); if (!typeId.isValid())
result << settings; typeId = Constants::LANGUAGECLIENT_STDIO_SETTINGS_ID;
if (BaseSettings *settings = generateSettings(typeId)) {
settings->fromMap(map);
result << settings;
}
} }
} }
settingsIn->endGroup(); settingsIn->endGroup();
return result; return result;
} }
@@ -659,10 +665,16 @@ void LanguageClientSettings::toSettings(QSettings *settings,
const QList<BaseSettings *> &languageClientSettings) const QList<BaseSettings *> &languageClientSettings)
{ {
settings->beginGroup(settingsGroupKey); settings->beginGroup(settingsGroupKey);
settings->setValue(clientsKey, Utils::transform(languageClientSettings, auto transform = [](const QList<BaseSettings *> &settings) {
[](const BaseSettings *setting){ return Utils::transform(settings, [](const BaseSettings *setting) {
return QVariant(setting->toMap()); return QVariant(setting->toMap());
})); });
};
auto isStdioSetting = Utils::equal(&BaseSettings::m_settingsTypeId,
Utils::Id(Constants::LANGUAGECLIENT_STDIO_SETTINGS_ID));
auto [stdioSettings, typedSettings] = Utils::partition(languageClientSettings, isStdioSetting);
settings->setValue(clientsKey, transform(stdioSettings));
settings->setValue(typedClientsKey, transform(typedSettings));
settings->endGroup(); settings->endGroup();
} }

View File

@@ -1,4 +1,5 @@
add_qtc_plugin(PerfProfiler add_qtc_plugin(PerfProfiler
CONDITION TARGET Tracing
DEPENDS Tracing Qt5::QuickWidgets DEPENDS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport
SOURCES SOURCES

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 583 B

View File

@@ -24,7 +24,6 @@
<file>images/debugger_overlay_small@2x.png</file> <file>images/debugger_overlay_small@2x.png</file>
<file>images/analyzer_overlay_small.png</file> <file>images/analyzer_overlay_small.png</file>
<file>images/analyzer_overlay_small@2x.png</file> <file>images/analyzer_overlay_small@2x.png</file>
<file>images/session.png</file>
<file>images/BuildSettings.png</file> <file>images/BuildSettings.png</file>
<file>images/CodeStyleSettings.png</file> <file>images/CodeStyleSettings.png</file>
<file>images/RunSettings.png</file> <file>images/RunSettings.png</file>
@@ -67,6 +66,8 @@
<file>images/fileoverlay_product@2x.png</file> <file>images/fileoverlay_product@2x.png</file>
<file>images/fileoverlay_group.png</file> <file>images/fileoverlay_group.png</file>
<file>images/fileoverlay_group@2x.png</file> <file>images/fileoverlay_group@2x.png</file>
<file>images/fileoverlay_modules.png</file>
<file>images/fileoverlay_modules@2x.png</file>
<file>images/fileoverlay_ui.png</file> <file>images/fileoverlay_ui.png</file>
<file>images/fileoverlay_ui@2x.png</file> <file>images/fileoverlay_ui@2x.png</file>
<file>images/fileoverlay_scxml.png</file> <file>images/fileoverlay_scxml.png</file>

View File

@@ -215,6 +215,7 @@ const char PROJECTTREE_ID[] = "Projects";
const char FILEOVERLAY_QT[]=":/projectexplorer/images/fileoverlay_qt.png"; const char FILEOVERLAY_QT[]=":/projectexplorer/images/fileoverlay_qt.png";
const char FILEOVERLAY_GROUP[] = ":/projectexplorer/images/fileoverlay_group.png"; const char FILEOVERLAY_GROUP[] = ":/projectexplorer/images/fileoverlay_group.png";
const char FILEOVERLAY_PRODUCT[] = ":/projectexplorer/images/fileoverlay_product.png"; const char FILEOVERLAY_PRODUCT[] = ":/projectexplorer/images/fileoverlay_product.png";
const char FILEOVERLAY_MODULES[] = ":/projectexplorer/images/fileoverlay_modules.png";
const char FILEOVERLAY_QML[]=":/projectexplorer/images/fileoverlay_qml.png"; const char FILEOVERLAY_QML[]=":/projectexplorer/images/fileoverlay_qml.png";
const char FILEOVERLAY_UI[]=":/projectexplorer/images/fileoverlay_ui.png"; const char FILEOVERLAY_UI[]=":/projectexplorer/images/fileoverlay_ui.png";
const char FILEOVERLAY_QRC[]=":/projectexplorer/images/fileoverlay_qrc.png"; const char FILEOVERLAY_QRC[]=":/projectexplorer/images/fileoverlay_qrc.png";

View File

@@ -6,7 +6,7 @@ endif()
add_qtc_plugin(QmlDesigner add_qtc_plugin(QmlDesigner
DEPENDS DEPENDS
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
Qt5::QuickWidgets Qt5::CorePrivate Sqlite Qt5::QuickWidgets Qt5::CorePrivate Sqlite Threads::Threads
DEFINES DEFINES
DESIGNER_CORE_LIBRARY DESIGNER_CORE_LIBRARY
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\" IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"

View File

@@ -100,7 +100,9 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
auto setLinearInterpolation = [this]() { auto setLinearInterpolation = [this]() {
m_view->setInterpolation(Keyframe::Interpolation::Linear); m_view->setInterpolation(Keyframe::Interpolation::Linear);
}; };
auto setStepInterpolation = [this]() { m_view->setInterpolation(Keyframe::Interpolation::Step); }; auto setStepInterpolation = [this]() {
m_view->setInterpolation(Keyframe::Interpolation::Step);
};
auto setSplineInterpolation = [this]() { auto setSplineInterpolation = [this]() {
m_view->setInterpolation(Keyframe::Interpolation::Bezier); m_view->setInterpolation(Keyframe::Interpolation::Bezier);
}; };

View File

@@ -338,7 +338,8 @@ void CurveEditorView::commitKeyframes(TreeItem *item)
group.setValue(QVariant(pos.y()), pos.x()); group.setValue(QVariant(pos.y()), pos.x());
if (previous.isValid()) { if (previous.isValid()) {
if (frame.interpolation() == Keyframe::Interpolation::Bezier) { if (frame.interpolation() == Keyframe::Interpolation::Bezier ||
frame.interpolation() == Keyframe::Interpolation::Step ) {
CurveSegment segment(previous, frame); CurveSegment segment(previous, frame);
if (segment.isValid()) if (segment.isValid())
attachEasingCurve(group, pos.x(), segment.easingCurve()); attachEasingCurve(group, pos.x(), segment.easingCurve());
@@ -346,8 +347,6 @@ void CurveEditorView::commitKeyframes(TreeItem *item)
QVariant data = frame.data(); QVariant data = frame.data();
if (data.type() == static_cast<int>(QMetaType::QEasingCurve)) if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
attachEasingCurve(group, pos.x(), data.value<QEasingCurve>()); attachEasingCurve(group, pos.x(), data.value<QEasingCurve>());
} else if (frame.interpolation() == Keyframe::Interpolation::Step) {
// Warning: Keyframe::Interpolation::Step not yet implemented
} }
} }

View File

@@ -294,6 +294,13 @@ void CurveSegment::extend(QPainterPath &path) const
QEasingCurve CurveSegment::easingCurve() const QEasingCurve CurveSegment::easingCurve() const
{ {
if (interpolation() == Keyframe::Interpolation::Step) {
QEasingCurve curve;
curve.addCubicBezierSegment(QPointF(0.1, 0.0), QPointF(0.9, 0.0), QPointF(1.0, 0.0));
curve.addCubicBezierSegment(QPointF(1.0, 0.1), QPointF(1.0, 0.9), QPointF(1.0, 1.0));
return curve;
}
auto mapPosition = [this](const QPointF &position) { auto mapPosition = [this](const QPointF &position) {
QPointF min = m_left.position(); QPointF min = m_left.position();
QPointF max = m_right.position(); QPointF max = m_right.position();

View File

@@ -370,7 +370,8 @@ void DesignDocument::close()
void DesignDocument::updateSubcomponentManager() void DesignDocument::updateSubcomponentManager()
{ {
Q_ASSERT(m_subComponentManager); Q_ASSERT(m_subComponentManager);
m_subComponentManager->update(QUrl::fromLocalFile(fileName().toString()), currentModel()->imports()); m_subComponentManager->update(QUrl::fromLocalFile(fileName().toString()),
currentModel()->imports() + currentModel()->possibleImports());
} }
void DesignDocument::deleteSelected() void DesignDocument::deleteSelected()

View File

@@ -40,6 +40,7 @@ ItemLibraryAddImportModel::ItemLibraryAddImportModel(QObject *parent)
// add role names // add role names
m_roleNames.insert(Qt::UserRole + 1, "importUrl"); m_roleNames.insert(Qt::UserRole + 1, "importUrl");
m_roleNames.insert(Qt::UserRole + 2, "importVisible"); m_roleNames.insert(Qt::UserRole + 2, "importVisible");
m_roleNames.insert(Qt::UserRole + 3, "isSeparator");
} }
ItemLibraryAddImportModel::~ItemLibraryAddImportModel() ItemLibraryAddImportModel::~ItemLibraryAddImportModel()
@@ -63,7 +64,10 @@ QVariant ItemLibraryAddImportModel::data(const QModelIndex &index, int role) con
return importUrl; return importUrl;
if (m_roleNames[role] == "importVisible") if (m_roleNames[role] == "importVisible")
return m_searchText.isEmpty() || m_importFilterList.contains(importUrl); return m_searchText.isEmpty() || importUrl.isEmpty() || m_importFilterList.contains(importUrl);
if (m_roleNames[role] == "isSeparator")
return importUrl.isEmpty();
qWarning() << Q_FUNC_INFO << "invalid role requested"; qWarning() << Q_FUNC_INFO << "invalid role requested";
@@ -83,9 +87,9 @@ void ItemLibraryAddImportModel::update(const QList<Import> &possibleImports)
const DesignerMcuManager &mcuManager = DesignerMcuManager::instance(); const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
const bool isQtForMCUs = mcuManager.isMCUProject(); const bool isQtForMCUs = mcuManager.isMCUProject();
QList<Import> filteredImports; QList<Import> filteredImports;
const QStringList mcuAllowedList = mcuManager.allowedImports();
const QStringList mcuBannedList = mcuManager.bannedImports();
if (isQtForMCUs) { if (isQtForMCUs) {
const QStringList mcuAllowedList = mcuManager.allowedImports();
const QStringList mcuBannedList = mcuManager.bannedImports();
filteredImports = Utils::filtered(possibleImports, filteredImports = Utils::filtered(possibleImports,
[&](const Import &import) { [&](const Import &import) {
return (mcuAllowedList.contains(import.url()) return (mcuAllowedList.contains(import.url())
@@ -96,7 +100,7 @@ void ItemLibraryAddImportModel::update(const QList<Import> &possibleImports)
filteredImports = possibleImports; filteredImports = possibleImports;
} }
Utils::sort(filteredImports, [](const Import &firstImport, const Import &secondImport) { Utils::sort(filteredImports, [this](const Import &firstImport, const Import &secondImport) {
if (firstImport.url() == secondImport.url()) if (firstImport.url() == secondImport.url())
return firstImport.toString() < secondImport.toString(); return firstImport.toString() < secondImport.toString();
@@ -106,6 +110,10 @@ void ItemLibraryAddImportModel::update(const QList<Import> &possibleImports)
if (secondImport.url() == "QtQuick") if (secondImport.url() == "QtQuick")
return false; return false;
const bool firstPriority = m_priorityImports.contains(firstImport.url());
if (firstPriority != m_priorityImports.contains(secondImport.url()))
return firstPriority;
if (firstImport.isLibraryImport() && secondImport.isFileImport()) if (firstImport.isLibraryImport() && secondImport.isFileImport())
return false; return false;
@@ -122,9 +130,15 @@ void ItemLibraryAddImportModel::update(const QList<Import> &possibleImports)
}); });
// create import sections // create import sections
bool previousIsPriority = false;
for (const Import &import : std::as_const(filteredImports)) { for (const Import &import : std::as_const(filteredImports)) {
if (import.isLibraryImport()) if (import.isLibraryImport()) {
bool currentIsPriority = m_priorityImports.contains(import.url());
if (previousIsPriority && !currentIsPriority)
m_importList.append(Import::empty()); // empty import acts as a separator
m_importList.append(import); m_importList.append(import);
previousIsPriority = currentIsPriority;
}
} }
endResetModel(); endResetModel();
@@ -153,4 +167,9 @@ Import ItemLibraryAddImportModel::getImportAt(int index) const
return m_importList.at(index); return m_importList.at(index);
} }
void ItemLibraryAddImportModel::setPriorityImports(const QSet<QString> &priorityImports)
{
m_priorityImports = priorityImports;
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -50,11 +50,14 @@ public:
void setSearchText(const QString &searchText); void setSearchText(const QString &searchText);
Import getImportAt(int index) const; Import getImportAt(int index) const;
void setPriorityImports(const QSet<QString> &priorityImports);
private: private:
QString m_searchText; QString m_searchText;
QList<Import> m_importList; QList<Import> m_importList;
QSet<QString> m_importFilterList; QSet<QString> m_importFilterList;
QHash<int, QByteArray> m_roleNames; QHash<int, QByteArray> m_roleNames;
QSet<QString> m_priorityImports;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -664,7 +664,12 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
timer->callOnTimeout([this, timer, progressTitle, model, doc]() { timer->callOnTimeout([this, timer, progressTitle, model, doc]() {
if (!isCancelled()) { if (!isCancelled()) {
notifyProgress(++counter * 5, progressTitle); notifyProgress(++counter * 5, progressTitle);
if (counter == 10) { if (counter < 10) {
// Do not proceed while application isn't active as the filesystem
// watcher qmljs uses won't trigger unless application is active
if (QApplication::applicationState() != Qt::ApplicationActive)
--counter;
} else if (counter == 10) {
model->rewriterView()->textModifier()->replace(0, 0, {}); model->rewriterView()->textModifier()->replace(0, 0, {});
} else if (counter == 19) { } else if (counter == 19) {
try { try {

View File

@@ -127,6 +127,9 @@ void ItemLibraryCategoriesModel::sortCategorySections()
}; };
std::sort(m_categoryList.begin(), m_categoryList.end(), categorySort); std::sort(m_categoryList.begin(), m_categoryList.end(), categorySort);
for (const auto &category : qAsConst(m_categoryList))
category->sortItems();
} }
void ItemLibraryCategoriesModel::resetModel() void ItemLibraryCategoriesModel::resetModel()

View File

@@ -70,6 +70,8 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
bool itemVisible = item->itemName().toLower().contains(searchText) bool itemVisible = item->itemName().toLower().contains(searchText)
|| item->typeName().toLower().contains(searchText); || item->typeName().toLower().contains(searchText);
if (searchText.isEmpty() && !item->isUsable())
itemVisible = false;
bool itemChanged = item->setVisible(itemVisible); bool itemChanged = item->setVisible(itemVisible);
*changed |= itemChanged; *changed |= itemChanged;

View File

@@ -28,18 +28,22 @@
namespace QmlDesigner { namespace QmlDesigner {
ItemLibraryImport::ItemLibraryImport(const Import &import, QObject *parent, bool isUserSection) ItemLibraryImport::ItemLibraryImport(const Import &import, QObject *parent, SectionType sectionType)
: QObject(parent), : QObject(parent),
m_import(import), m_import(import),
m_isUserSection(isUserSection) m_sectionType(sectionType)
{ {
updateRemovable();
} }
QString ItemLibraryImport::importName() const QString ItemLibraryImport::importName() const
{ {
if (m_isUserSection) if (m_sectionType == SectionType::User)
return userComponentsTitle(); return userComponentsTitle();
if (m_sectionType == SectionType::Unimported)
return unimportedComponentsTitle();
if (importUrl() == "QtQuick") if (importUrl() == "QtQuick")
return tr("Default Components"); return tr("Default Components");
@@ -48,9 +52,12 @@ QString ItemLibraryImport::importName() const
QString ItemLibraryImport::importUrl() const QString ItemLibraryImport::importUrl() const
{ {
if (m_isUserSection) if (m_sectionType == SectionType::User)
return userComponentsTitle(); return userComponentsTitle();
if (m_sectionType == SectionType::Unimported)
return unimportedComponentsTitle();
return m_import.url(); return m_import.url();
} }
@@ -61,11 +68,14 @@ bool ItemLibraryImport::importExpanded() const
QString ItemLibraryImport::sortingName() const QString ItemLibraryImport::sortingName() const
{ {
if (m_isUserSection) // user components always come first if (m_sectionType == SectionType::User)
return "_"; return "_"; // user components always come first
if (m_sectionType == SectionType::Unimported)
return "zzzzzz"; // Unimported components always come last
if (!hasCategories()) // imports with no categories are at the bottom of the list if (!hasCategories()) // imports with no categories are at the bottom of the list
return "zzzzz" + importName(); return "zzzzz_" + importName();
return importName(); return importName();
} }
@@ -113,6 +123,7 @@ bool ItemLibraryImport::setVisible(bool isVisible)
{ {
if (isVisible != m_isVisible) { if (isVisible != m_isVisible) {
m_isVisible = isVisible; m_isVisible = isVisible;
emit importVisibleChanged();
return true; return true;
} }
@@ -126,7 +137,11 @@ bool ItemLibraryImport::importVisible() const
void ItemLibraryImport::setImportUsed(bool importUsed) void ItemLibraryImport::setImportUsed(bool importUsed)
{ {
m_importUsed = importUsed; if (importUsed != m_importUsed) {
m_importUsed = importUsed;
updateRemovable();
emit importUsedChanged();
}
} }
bool ItemLibraryImport::importUsed() const bool ItemLibraryImport::importUsed() const
@@ -134,6 +149,11 @@ bool ItemLibraryImport::importUsed() const
return m_importUsed; return m_importUsed;
} }
bool ItemLibraryImport::importRemovable() const
{
return m_importRemovable;
}
bool ItemLibraryImport::hasCategories() const bool ItemLibraryImport::hasCategories() const
{ {
return m_categoryModel.rowCount() > 0; return m_categoryModel.rowCount() > 0;
@@ -146,7 +166,10 @@ void ItemLibraryImport::sortCategorySections()
void ItemLibraryImport::setImportExpanded(bool expanded) void ItemLibraryImport::setImportExpanded(bool expanded)
{ {
m_importExpanded = expanded; if (expanded != m_importExpanded) {
m_importExpanded = expanded;
emit importExpandChanged();
}
} }
ItemLibraryCategory *ItemLibraryImport::getCategorySection(const QString &categoryName) const ItemLibraryCategory *ItemLibraryImport::getCategorySection(const QString &categoryName) const
@@ -159,15 +182,30 @@ ItemLibraryCategory *ItemLibraryImport::getCategorySection(const QString &catego
return nullptr; return nullptr;
} }
bool ItemLibraryImport::isUserSection() const
{
return m_isUserSection;
}
// static // static
QString ItemLibraryImport::userComponentsTitle() QString ItemLibraryImport::userComponentsTitle()
{ {
return tr("My Components"); return tr("My Components");
} }
QString ItemLibraryImport::unimportedComponentsTitle()
{
return tr("All Other Components");
}
ItemLibraryImport::SectionType ItemLibraryImport::sectionType() const
{
return m_sectionType;
}
void ItemLibraryImport::updateRemovable()
{
bool importRemovable = !m_importUsed && m_sectionType == SectionType::Default
&& m_import.url() != "QtQuick";
if (importRemovable != m_importRemovable) {
m_importRemovable = importRemovable;
emit importRemovableChanged();
}
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -41,10 +41,18 @@ class ItemLibraryImport : public QObject
Q_PROPERTY(bool importVisible READ importVisible NOTIFY importVisibleChanged FINAL) Q_PROPERTY(bool importVisible READ importVisible NOTIFY importVisibleChanged FINAL)
Q_PROPERTY(bool importUsed READ importUsed NOTIFY importUsedChanged FINAL) Q_PROPERTY(bool importUsed READ importUsed NOTIFY importUsedChanged FINAL)
Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL) Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL)
Q_PROPERTY(bool importRemovable READ importRemovable NOTIFY importRemovableChanged FINAL)
Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL) Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL)
public: public:
ItemLibraryImport(const Import &import, QObject *parent = nullptr, bool isUserSection = false); enum class SectionType {
Default,
User,
Unimported
};
ItemLibraryImport(const Import &import, QObject *parent = nullptr,
SectionType sectionType = SectionType::Default);
QString importName() const; QString importName() const;
QString importUrl() const; QString importUrl() const;
@@ -53,6 +61,7 @@ public:
Import importEntry() const; Import importEntry() const;
bool importVisible() const; bool importVisible() const;
bool importUsed() const; bool importUsed() const;
bool importRemovable() const;
bool hasCategories() const; bool hasCategories() const;
ItemLibraryCategory *getCategorySection(const QString &categoryName) const; ItemLibraryCategory *getCategorySection(const QString &categoryName) const;
@@ -66,21 +75,26 @@ public:
void expandCategories(bool expand = true); void expandCategories(bool expand = true);
static QString userComponentsTitle(); static QString userComponentsTitle();
static QString unimportedComponentsTitle();
bool isUserSection() const; SectionType sectionType() const;
signals: signals:
void categoryModelChanged(); void categoryModelChanged();
void importVisibleChanged(); void importVisibleChanged();
void importUsedChanged(); void importUsedChanged();
void importExpandChanged(); void importExpandChanged();
void importRemovableChanged();
private: private:
void updateRemovable();
Import m_import; Import m_import;
bool m_importExpanded = true; bool m_importExpanded = true;
bool m_isVisible = true; bool m_isVisible = true;
bool m_importUsed = false; bool m_importUsed = false;
bool m_isUserSection = false; // user components import section bool m_importRemovable = false;
SectionType m_sectionType = SectionType::Default;
ItemLibraryCategoriesModel m_categoryModel; ItemLibraryCategoriesModel m_categoryModel;
}; };

View File

@@ -27,9 +27,10 @@
namespace QmlDesigner { namespace QmlDesigner {
ItemLibraryItem::ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, QObject *parent) ItemLibraryItem::ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isUsable, QObject *parent)
: QObject(parent), : QObject(parent)
m_itemLibraryEntry(itemLibraryEntry) , m_itemLibraryEntry(itemLibraryEntry)
, m_isUsable(isUsable)
{ {
} }
@@ -61,6 +62,11 @@ QString ItemLibraryItem::componentPath() const
return m_itemLibraryEntry.customComponentSource(); return m_itemLibraryEntry.customComponentSource();
} }
QString ItemLibraryItem::requiredImport() const
{
return m_itemLibraryEntry.requiredImport();
}
bool ItemLibraryItem::setVisible(bool isVisible) bool ItemLibraryItem::setVisible(bool isVisible)
{ {
if (isVisible != m_isVisible) { if (isVisible != m_isVisible) {
@@ -77,6 +83,11 @@ bool ItemLibraryItem::isVisible() const
return m_isVisible; return m_isVisible;
} }
bool ItemLibraryItem::isUsable() const
{
return m_isUsable;
}
QVariant ItemLibraryItem::itemLibraryEntry() const QVariant ItemLibraryItem::itemLibraryEntry() const
{ {
return QVariant::fromValue(m_itemLibraryEntry); return QVariant::fromValue(m_itemLibraryEntry);

View File

@@ -43,18 +43,22 @@ class ItemLibraryItem: public QObject
Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL) Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL)
Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL) Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL)
Q_PROPERTY(QString componentPath READ componentPath FINAL) Q_PROPERTY(QString componentPath READ componentPath FINAL)
Q_PROPERTY(bool itemUsable READ isUsable FINAL)
Q_PROPERTY(QString itemRequiredImport READ requiredImport FINAL)
public: public:
ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, QObject *parent); ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isImported, QObject *parent);
~ItemLibraryItem() override; ~ItemLibraryItem() override;
QString itemName() const; QString itemName() const;
QString typeName() const; QString typeName() const;
QString itemLibraryIconPath() const; QString itemLibraryIconPath() const;
QString componentPath() const; QString componentPath() const;
QString requiredImport() const;
bool setVisible(bool isVisible); bool setVisible(bool isVisible);
bool isVisible() const; bool isVisible() const;
bool isUsable() const;
QVariant itemLibraryEntry() const; QVariant itemLibraryEntry() const;
@@ -64,6 +68,7 @@ signals:
private: private:
ItemLibraryEntry m_itemLibraryEntry; ItemLibraryEntry m_itemLibraryEntry;
bool m_isVisible = true; bool m_isVisible = true;
bool m_isUsable = false;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -70,7 +70,7 @@ void ItemLibraryItemsModel::addItem(ItemLibraryItem *element)
{ {
m_itemList.append(element); m_itemList.append(element);
element->setVisible(true); element->setVisible(element->isUsable());
} }
const QList<QPointer<ItemLibraryItem>> &ItemLibraryItemsModel::items() const const QList<QPointer<ItemLibraryItem>> &ItemLibraryItemsModel::items() const

View File

@@ -167,7 +167,7 @@ void ItemLibraryModel::setSearchText(const QString &searchText)
} }
} }
Import entryToImport(const ItemLibraryEntry &entry) Import ItemLibraryModel::entryToImport(const ItemLibraryEntry &entry)
{ {
if (entry.majorVersion() == -1 && entry.minorVersion() == -1) if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
return Import::createFileImport(entry.requiredImport()); return Import::createFileImport(entry.requiredImport());
@@ -177,6 +177,28 @@ Import entryToImport(const ItemLibraryEntry &entry)
} }
// Returns true if first import version is higher or equal to second import version
static bool compareVersions(const QString &version1, const QString &version2)
{
if (version2.isEmpty() || version1 == version2)
return true;
const QStringList version1List = version1.split(QLatin1Char('.'));
const QStringList version2List = version2.split(QLatin1Char('.'));
if (version1List.count() == 2 && version2List.count() == 2) {
int major1 = version1List.constFirst().toInt();
int major2 = version2List.constFirst().toInt();
if (major1 > major2) {
return true;
} else if (major1 == major2) {
int minor1 = version1List.constLast().toInt();
int minor2 = version2List.constLast().toInt();
if (minor1 >= minor2)
return true;
}
}
return false;
}
void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
{ {
if (!model) if (!model)
@@ -190,60 +212,91 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
QString projectName = project ? project->displayName() : ""; QString projectName = project ? project->displayName() : "";
// create import sections // create import sections
QHash<QString, ItemLibraryImport *> importHash;
for (const Import &import : model->imports()) { for (const Import &import : model->imports()) {
if (import.isLibraryImport() && import.url() != projectName) { if (import.isLibraryImport() && import.url() != projectName) {
ItemLibraryImport *itemLibImport = new ItemLibraryImport(import, this); bool addNew = true;
m_importList.append(itemLibImport); ItemLibraryImport *oldImport = importHash.value(import.url());
itemLibImport->setImportExpanded(loadExpandedState(import.url())); if (oldImport && oldImport->importEntry().url() == import.url()) {
// Retain the higher version if multiples exist
if (compareVersions(oldImport->importEntry().version(), import.version()))
addNew = false;
else
delete oldImport;
}
if (addNew) {
ItemLibraryImport *itemLibImport = new ItemLibraryImport(import, this);
importHash.insert(import.url(), itemLibImport);
}
} }
} }
for (const auto itemLibImport : qAsConst(importHash)) {
m_importList.append(itemLibImport);
itemLibImport->setImportExpanded(loadExpandedState(itemLibImport->importEntry().url()));
}
const QList<ItemLibraryEntry> itemLibEntries = itemLibraryInfo->entries(); const QList<ItemLibraryEntry> itemLibEntries = itemLibraryInfo->entries();
for (const ItemLibraryEntry &entry : itemLibEntries) { for (const ItemLibraryEntry &entry : itemLibEntries) {
NodeMetaInfo metaInfo = model->metaInfo(entry.typeName()); NodeMetaInfo metaInfo = model->metaInfo(entry.typeName());
bool valid = metaInfo.isValid() && metaInfo.majorVersion() == entry.majorVersion(); bool valid = metaInfo.isValid() && metaInfo.majorVersion() == entry.majorVersion();
bool isItem = valid && metaInfo.isSubclassOf("QtQuick.Item"); bool isItem = valid && metaInfo.isSubclassOf("QtQuick.Item");
bool forceVisiblity = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary(); bool forceVisibility = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary();
if (m_flowMode && metaInfo.isValid()) { if (m_flowMode && metaInfo.isValid()) {
isItem = metaInfo.isSubclassOf("FlowView.FlowItem") isItem = metaInfo.isSubclassOf("FlowView.FlowItem")
|| metaInfo.isSubclassOf("FlowView.FlowWildcard") || metaInfo.isSubclassOf("FlowView.FlowWildcard")
|| metaInfo.isSubclassOf("FlowView.FlowDecision"); || metaInfo.isSubclassOf("FlowView.FlowDecision");
forceVisiblity = isItem; forceVisibility = isItem;
} }
bool blocked = false;
const DesignerMcuManager &mcuManager = DesignerMcuManager::instance(); const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
if (mcuManager.isMCUProject()) { if (mcuManager.isMCUProject()) {
const QSet<QString> blockTypes = mcuManager.bannedItems(); const QSet<QString> blockTypes = mcuManager.bannedItems();
if (blockTypes.contains(QString::fromUtf8(entry.typeName()))) if (blockTypes.contains(QString::fromUtf8(entry.typeName())))
valid = false; blocked = true;
} }
if (valid && (isItem || forceVisiblity) // We can change if the navigator does support pure QObjects Import import = entryToImport(entry);
&& (entry.requiredImport().isEmpty() bool hasImport = model->hasImport(import, true, true);
|| model->hasImport(entryToImport(entry), true, true))) { bool isImportPossible = false;
if (!hasImport)
isImportPossible = model->isImportPossible(import, true, true);
bool isUsable = (valid && (isItem || forceVisibility))
&& (entry.requiredImport().isEmpty() || hasImport);
if (!blocked && (isUsable || isImportPossible)) {
ItemLibraryImport *importSection = nullptr; ItemLibraryImport *importSection = nullptr;
QString catName = entry.category(); QString catName = entry.category();
if (catName == ItemLibraryImport::userComponentsTitle()) { if (isUsable) {
// create an import section for user components if (catName == ItemLibraryImport::userComponentsTitle()) {
importSection = importByUrl(ItemLibraryImport::userComponentsTitle()); // create an import section for user components
importSection = importByUrl(ItemLibraryImport::userComponentsTitle());
if (!importSection) {
importSection = new ItemLibraryImport(
{}, this, ItemLibraryImport::SectionType::User);
m_importList.append(importSection);
importSection->setImportExpanded(loadExpandedState(catName));
}
} else {
if (catName.startsWith("Qt Quick - "))
catName = catName.mid(11); // remove "Qt Quick - "
importSection = importByUrl(entry.requiredImport());
}
} else {
catName = ItemLibraryImport::unimportedComponentsTitle();
importSection = importByUrl(catName);
if (!importSection) { if (!importSection) {
importSection = new ItemLibraryImport({}, this, true); importSection = new ItemLibraryImport(
{}, this, ItemLibraryImport::SectionType::Unimported);
m_importList.append(importSection); m_importList.append(importSection);
importSection->setImportExpanded(loadExpandedState(catName)); importSection->setImportExpanded(loadExpandedState(catName));
} }
} else {
if (catName.startsWith("Qt Quick - "))
catName = catName.mid(11); // remove "Qt Quick - "
importSection = importByUrl(entry.requiredImport());
} }
if (!importSection) { // should not happen, but just in case if (!importSection) {
qWarning() << __FUNCTION__ << "No import section found! skipping entry: " << entry.name(); qWarning() << __FUNCTION__ << "No import section found! skipping entry: " << entry.name();
continue; continue;
} }
@@ -253,12 +306,12 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
if (!categorySection) { if (!categorySection) {
categorySection = new ItemLibraryCategory(catName, importSection); categorySection = new ItemLibraryCategory(catName, importSection);
importSection->addCategory(categorySection); importSection->addCategory(categorySection);
if (!importSection->isUserSection()) if (importSection->sectionType() == ItemLibraryImport::SectionType::Default)
categorySection->setExpanded(loadExpandedState(categorySection->categoryName())); categorySection->setExpanded(loadExpandedState(categorySection->categoryName()));
} }
// create item // create item
auto item = new ItemLibraryItem(entry, categorySection); auto item = new ItemLibraryItem(entry, isUsable, categorySection);
categorySection->addItem(item); categorySection->addItem(item);
} }
} }
@@ -300,7 +353,9 @@ ItemLibraryImport *ItemLibraryModel::importByUrl(const QString &importUrl) const
if (itemLibraryImport->importUrl() == importUrl if (itemLibraryImport->importUrl() == importUrl
|| (importUrl.isEmpty() && itemLibraryImport->importUrl() == "QtQuick") || (importUrl.isEmpty() && itemLibraryImport->importUrl() == "QtQuick")
|| (importUrl == ItemLibraryImport::userComponentsTitle() || (importUrl == ItemLibraryImport::userComponentsTitle()
&& itemLibraryImport->isUserSection())) { && itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::User)
|| (importUrl == ItemLibraryImport::unimportedComponentsTitle()
&& itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::Unimported)) {
return itemLibraryImport; return itemLibraryImport;
} }
} }
@@ -324,9 +379,11 @@ void ItemLibraryModel::updateVisibility(bool *changed)
for (ItemLibraryImport *import : std::as_const(m_importList)) { for (ItemLibraryImport *import : std::as_const(m_importList)) {
bool categoryChanged = false; bool categoryChanged = false;
bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged); bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged);
*changed |= categoryChanged; *changed |= categoryChanged;
if (import->sectionType() == ItemLibraryImport::SectionType::Unimported)
*changed |= import->setVisible(!m_searchText.isEmpty());
// expand import if it has an item matching search criteria // expand import if it has an item matching search criteria
if (hasVisibleItems && !import->importExpanded()) if (hasVisibleItems && !import->importExpanded())
import->setImportExpanded(); import->setImportExpanded();

View File

@@ -69,6 +69,8 @@ public:
Q_INVOKABLE void expandAll(); Q_INVOKABLE void expandAll();
Q_INVOKABLE void collapseAll(); Q_INVOKABLE void collapseAll();
Import entryToImport(const ItemLibraryEntry &entry);
private: private:
void updateVisibility(bool *changed); void updateVisibility(bool *changed);
void addRoleNames(); void addRoleNames();

View File

@@ -86,15 +86,35 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
QMetaObject::invokeMethod(m_itemViewQuickWidget->rootObject(), "closeContextMenu"); QMetaObject::invokeMethod(m_itemViewQuickWidget->rootObject(), "closeContextMenu");
} else if (event->type() == QMouseEvent::MouseMove) { } else if (event->type() == QMouseEvent::MouseMove) {
if (m_itemToDrag.isValid()) { if (m_itemToDrag.isValid()) {
ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>(); QMouseEvent *me = static_cast<QMouseEvent *>(event);
auto drag = new QDrag(this); if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) {
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath())); ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>();
drag->setMimeData(m_itemLibraryModel->getMimeData(entry)); // For drag to be handled correctly, we must have the component properly imported
drag->exec(); // beforehand, so we import the module immediately when the drag starts
drag->deleteLater(); if (!entry.requiredImport().isEmpty()) {
Import import = Import::createLibraryImport(entry.requiredImport());
if (!m_model->hasImport(import, true, true)) {
const QList<Import> possImports = m_model->possibleImports();
for (const auto &possImport : possImports) {
if (possImport.url() == import.url()) {
m_model->changeImports({possImport}, {});
break;
}
}
}
}
m_itemToDrag = {}; auto drag = new QDrag(this);
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
drag->setMimeData(m_itemLibraryModel->getMimeData(entry));
drag->exec();
drag->deleteLater();
m_itemToDrag = {};
}
} }
} else if (event->type() == QMouseEvent::MouseButtonRelease) {
m_itemToDrag = {};
} }
return QObject::eventFilter(obj, event); return QObject::eventFilter(obj, event);
@@ -229,11 +249,16 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
if (m_itemLibraryInfo) { if (m_itemLibraryInfo) {
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged, disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
this, &ItemLibraryWidget::delayedUpdateModel); this, &ItemLibraryWidget::delayedUpdateModel);
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::priorityImportsChanged,
this, &ItemLibraryWidget::handlePriorityImportsChanged);
} }
m_itemLibraryInfo = itemLibraryInfo; m_itemLibraryInfo = itemLibraryInfo;
if (itemLibraryInfo) { if (itemLibraryInfo) {
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged, connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
this, &ItemLibraryWidget::delayedUpdateModel); this, &ItemLibraryWidget::delayedUpdateModel);
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::priorityImportsChanged,
this, &ItemLibraryWidget::handlePriorityImportsChanged);
m_itemLibraryAddImportModel->setPriorityImports(m_itemLibraryInfo->priorityImports());
} }
delayedUpdateModel(); delayedUpdateModel();
} }
@@ -344,6 +369,7 @@ void ItemLibraryWidget::updateModel()
void ItemLibraryWidget::updatePossibleImports(const QList<Import> &possibleImports) void ItemLibraryWidget::updatePossibleImports(const QList<Import> &possibleImports)
{ {
m_itemLibraryAddImportModel->update(possibleImports); m_itemLibraryAddImportModel->update(possibleImports);
delayedUpdateModel();
} }
void ItemLibraryWidget::updateUsedImports(const QList<Import> &usedImports) void ItemLibraryWidget::updateUsedImports(const QList<Import> &usedImports)
@@ -365,6 +391,14 @@ void ItemLibraryWidget::updateSearch()
} }
} }
void ItemLibraryWidget::handlePriorityImportsChanged()
{
if (!m_itemLibraryInfo.isNull()) {
m_itemLibraryAddImportModel->setPriorityImports(m_itemLibraryInfo->priorityImports());
m_itemLibraryAddImportModel->update(m_model->possibleImports());
}
}
void ItemLibraryWidget::setResourcePath(const QString &resourcePath) void ItemLibraryWidget::setResourcePath(const QString &resourcePath)
{ {
if (m_resourcesView->model() == m_resourcesFileSystemModel.data()) { if (m_resourcesView->model() == m_resourcesFileSystemModel.data()) {
@@ -374,12 +408,13 @@ void ItemLibraryWidget::setResourcePath(const QString &resourcePath)
updateSearch(); updateSearch();
} }
void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry) void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos)
{ {
// Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay // Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay
// active (and blocks mouse release) if mouse is released at the same spot of the drag start. // active (and blocks mouse release) if mouse is released at the same spot of the drag start.
// This doesn't completely eliminate the bug but makes it significantly harder to produce. // This doesn't completely eliminate the bug but makes it significantly harder to produce.
m_itemToDrag = itemLibEntry; m_itemToDrag = itemLibEntry;
m_dragStartPoint = mousePos.toPoint();
} }
void ItemLibraryWidget::setFlowMode(bool b) void ItemLibraryWidget::setFlowMode(bool b)
@@ -396,6 +431,15 @@ void ItemLibraryWidget::removeImport(const QString &importUrl)
m_model->changeImports({}, {importSection->importEntry()}); m_model->changeImports({}, {importSection->importEntry()});
} }
void ItemLibraryWidget::addImportForItem(const QVariant &entry)
{
QTC_ASSERT(m_itemLibraryModel, return);
QTC_ASSERT(m_model, return);
Import import = m_itemLibraryModel->entryToImport(entry.value<ItemLibraryEntry>());
m_model->changeImports({import}, {});
}
void ItemLibraryWidget::addResources(const QStringList &files) void ItemLibraryWidget::addResources(const QStringList &files)
{ {
auto document = QmlDesignerPlugin::instance()->currentDesignDocument(); auto document = QmlDesignerPlugin::instance()->currentDesignDocument();

View File

@@ -39,6 +39,7 @@
#include <QQuickWidget> #include <QQuickWidget>
#include <QQmlPropertyMap> #include <QQmlPropertyMap>
#include <QTimer> #include <QTimer>
#include <QPointF>
#include <memory> #include <memory>
@@ -87,8 +88,9 @@ public:
void setModel(Model *model); void setModel(Model *model);
void setFlowMode(bool b); void setFlowMode(bool b);
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry); Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos);
Q_INVOKABLE void removeImport(const QString &importUrl); Q_INVOKABLE void removeImport(const QString &importUrl);
Q_INVOKABLE void addImportForItem(const QVariant &entry);
signals: signals:
void itemActivated(const QString& itemName); void itemActivated(const QString& itemName);
@@ -102,6 +104,7 @@ private:
void addResources(const QStringList &files); void addResources(const QStringList &files);
void importDroppedFiles(const QList<Utils::DropSupport::FileSpec> &files); void importDroppedFiles(const QList<Utils::DropSupport::FileSpec> &files);
void updateSearch(); void updateSearch();
void handlePriorityImportsChanged();
QTimer m_compressionTimer; QTimer m_compressionTimer;
QSize m_itemIconSize; QSize m_itemIconSize;
@@ -126,6 +129,7 @@ private:
QVariant m_itemToDrag; QVariant m_itemToDrag;
bool m_updateRetry = false; bool m_updateRetry = false;
QString m_filterText; QString m_filterText;
QPoint m_dragStartPoint;
private slots: private slots:
void handleTabChanged(int index); void handleTabChanged(int index);

View File

@@ -57,9 +57,11 @@ Column {
delegate: Rectangle { delegate: Rectangle {
width: listView.width width: listView.width
height: 25 height: isSeparator ? 4 : 25
color: mouseArea.containsMouse ? Qt.lighter(Theme.qmlDesignerButtonColor(), 1.3) color: isSeparator ? Theme.color(Theme.BackgroundColorNormal)
: Theme.qmlDesignerButtonColor() : mouseArea.containsMouse
? Qt.lighter(Theme.qmlDesignerButtonColor(), 1.3)
: Theme.qmlDesignerButtonColor()
visible: importVisible visible: importVisible
Text { Text {
@@ -77,6 +79,7 @@ Column {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: addImport(index) onClicked: addImport(index)
enabled: !isSeparator
} }
} }
} }

View File

@@ -24,23 +24,25 @@
****************************************************************************/ ****************************************************************************/
#include "richtexteditorproxy.h" #include "richtexteditorproxy.h"
#include "richtexteditor.h"
#include <qmldesignerplugin.h> #include <qmldesignerplugin.h>
#include <qmldesignerconstants.h> #include <qmldesignerconstants.h>
#include <coreplugin/icore.h>
#include <QDialog> #include <QDialog>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QGridLayout> #include <QGridLayout>
#include "richtexteditor.h"
namespace QmlDesigner { namespace QmlDesigner {
RichTextEditorProxy::RichTextEditorProxy(QObject *parent) RichTextEditorProxy::RichTextEditorProxy(QObject *parent)
: QObject(parent) : QObject(parent)
, m_dialog(new QDialog{}) , m_dialog(new QDialog(Core::ICore::dialogParent()))
, m_widget(new RichTextEditor{}) , m_widget(new RichTextEditor{})
{ {
m_dialog->setModal(true);
QGridLayout *layout = new QGridLayout{}; QGridLayout *layout = new QGridLayout{};
layout->addWidget(m_widget); layout->addWidget(m_widget);

View File

@@ -110,7 +110,7 @@ void TransitionEditorView::nodeReparented(const ModelNode &node,
const ModelNode parent = newPropertyParent.parentModelNode(); const ModelNode parent = newPropertyParent.parentModelNode();
qDebug() << Q_FUNC_INFO << parent; // qDebug() << Q_FUNC_INFO << parent;
if (parent.isValid() && parent.metaInfo().isValid() if (parent.isValid() && parent.metaInfo().isValid()
&& parent.metaInfo().isSubclassOf("QtQuick.Transition")) { && parent.metaInfo().isSubclassOf("QtQuick.Transition")) {
asyncUpdate(parent); asyncUpdate(parent);

View File

@@ -29,6 +29,7 @@
#include "propertycontainer.h" #include "propertycontainer.h"
#include <QPointer> #include <QPointer>
#include <QSet>
#include <memory> #include <memory>
namespace QmlDesigner { namespace QmlDesigner {
@@ -108,11 +109,14 @@ public:
void clearEntries(); void clearEntries();
QStringList blacklistImports() const; QStringList blacklistImports() const;
QSet<QString> priorityImports() const;
void addBlacklistImports(const QStringList &list); void addBlacklistImports(const QStringList &list);
void addPriorityImports(const QSet<QString> &set);
signals: signals:
void entriesChanged(); void entriesChanged();
void priorityImportsChanged();
private: // functions private: // functions
ItemLibraryInfo(QObject *parent = nullptr); ItemLibraryInfo(QObject *parent = nullptr);
@@ -123,6 +127,7 @@ private: // variables
QPointer<ItemLibraryInfo> m_baseInfo; QPointer<ItemLibraryInfo> m_baseInfo;
QStringList m_blacklistImports; QStringList m_blacklistImports;
QSet<QString> m_priorityImports;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -344,11 +344,27 @@ QStringList ItemLibraryInfo::blacklistImports() const
return list; return list;
} }
QSet<QString> ItemLibraryInfo::priorityImports() const
{
QSet<QString> set = m_priorityImports;
if (m_baseInfo)
set.unite(m_baseInfo->m_priorityImports);
return set;
}
void ItemLibraryInfo::addBlacklistImports(const QStringList &list) void ItemLibraryInfo::addBlacklistImports(const QStringList &list)
{ {
m_blacklistImports.append(list); m_blacklistImports.append(list);
} }
void ItemLibraryInfo::addPriorityImports(const QSet<QString> &set)
{
if (!set.isEmpty()) {
m_priorityImports.unite(set);
emit priorityImportsChanged();
}
}
void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo) void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo)
{ {
m_baseInfo = baseInfo; m_baseInfo = baseInfo;

View File

@@ -26,6 +26,8 @@
#include "metainforeader.h" #include "metainforeader.h"
#include "metainfo.h" #include "metainfo.h"
#include <utils/algorithm.h>
#include <QString> #include <QString>
#include <QFileInfo> #include <QFileInfo>
#include <QDebug> #include <QDebug>
@@ -230,8 +232,10 @@ void MetaInfoReader::readImportsProperty(const QString &name, const QVariant &va
if (name == "blacklistImports" && !values.isEmpty()) { if (name == "blacklistImports" && !values.isEmpty()) {
m_metaInfo.itemLibraryInfo()->addBlacklistImports(values); m_metaInfo.itemLibraryInfo()->addBlacklistImports(values);
} else if (name == "showTagsForImports" && !values.isEmpty()) { } else if ((name == "priorityImports" || name == "showTagsForImports") && !values.isEmpty()) {
// Flow tags removed, but keeping this for now to avoid errors parsing old metadata files // Flow tags are no longer shown, but the old property is still supported for prioritizing
// imports to keep compatibility with old metainfo files.
m_metaInfo.itemLibraryInfo()->addPriorityImports(Utils::toSet(values));
} else { } else {
addError(tr("Unknown property for Imports %1").arg(name), currentSourceLocation()); addError(tr("Unknown property for Imports %1").arg(name), currentSourceLocation());
setParserState(Error); setParserState(Error);

View File

@@ -45,8 +45,6 @@
#include <transitioneditor/transitioneditorview.h> #include <transitioneditor/transitioneditorview.h>
#include <pathtool/pathtool.h> #include <pathtool/pathtool.h>
#include <app/app_version.h>
#include <qmljseditor/qmljseditor.h> #include <qmljseditor/qmljseditor.h>
#include <qmljseditor/qmljseditorconstants.h> #include <qmljseditor/qmljseditorconstants.h>
#include <qmljseditor/qmljseditordocument.h> #include <qmljseditor/qmljseditordocument.h>
@@ -62,6 +60,7 @@
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
#include <coreplugin/modemanager.h> #include <coreplugin/modemanager.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h> #include <extensionsystem/pluginspec.h>
#include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsmodelmanagerinterface.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
@@ -71,6 +70,7 @@
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <QAction> #include <QAction>
#include <QTimer> #include <QTimer>
@@ -232,12 +232,13 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e
bool QmlDesignerPlugin::delayedInitialize() bool QmlDesignerPlugin::delayedInitialize()
{ {
// adding default path to item library plugins // adding default path to item library plugins
const QString pluginPath = Utils::HostOsInfo::isMacHost() const QString postfix = Utils::HostOsInfo::isMacHost() ? QString("/QmlDesigner")
? QString(QCoreApplication::applicationDirPath() + "/../PlugIns/QmlDesigner") : QString("/qmldesigner");
: QString(QCoreApplication::applicationDirPath() + "/../" const QStringList pluginPaths =
+ QLatin1String(IDE_LIBRARY_BASENAME) + "/" + Core::Constants::IDE_ID Utils::transform(ExtensionSystem::PluginManager::pluginPaths(), [postfix](const QString &p) {
+ "/plugins/qmldesigner"); return QString(p + postfix);
MetaInfo::setPluginPaths(QStringList(pluginPath)); });
MetaInfo::setPluginPaths(pluginPaths);
d->settings.fromSettings(Core::ICore::settings()); d->settings.fromSettings(Core::ICore::settings());

View File

@@ -1012,6 +1012,7 @@ void FindReferences::displayResults(int first, int last)
item.setFilePath(Utils::FilePath::fromString(result.path)); item.setFilePath(Utils::FilePath::fromString(result.path));
item.setLineText(result.lineText); item.setLineText(result.lineText);
item.setMainRange(result.line, result.col, result.len); item.setMainRange(result.line, result.col, result.len);
item.setUseTextEditorFont(true);
m_currentSearch->addResult(item); m_currentSearch->addResult(item);
} }
} }

View File

@@ -1,4 +1,5 @@
add_qtc_plugin(QmlProfiler add_qtc_plugin(QmlProfiler
CONDITION TARGET Tracing
DEPENDS QmlDebug QmlJS Tracing Qt5::QuickWidgets DEPENDS QmlDebug QmlJS Tracing Qt5::QuickWidgets
PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport TextEditor PLUGIN_DEPENDS Core Debugger ProjectExplorer QtSupport TextEditor
SOURCES SOURCES

View File

@@ -287,6 +287,10 @@ public:
m_searcher->setPlaceholderText(ExamplesWelcomePage::tr("Search in Examples...")); m_searcher->setPlaceholderText(ExamplesWelcomePage::tr("Search in Examples..."));
auto exampleSetSelector = new QComboBox(this); auto exampleSetSelector = new QComboBox(this);
QPalette pal = exampleSetSelector->palette();
// for macOS dark mode
pal.setColor(QPalette::Text, Utils::creatorTheme()->color(Theme::Welcome_TextColor));
exampleSetSelector->setPalette(pal);
exampleSetSelector->setMinimumWidth(GridProxyModel::GridItemWidth); exampleSetSelector->setMinimumWidth(GridProxyModel::GridItemWidth);
exampleSetSelector->setMaximumWidth(GridProxyModel::GridItemWidth); exampleSetSelector->setMaximumWidth(GridProxyModel::GridItemWidth);
ExampleSetModel *exampleSetModel = m_examplesModel->exampleSetModel(); ExampleSetModel *exampleSetModel = m_examplesModel->exampleSetModel();

View File

@@ -159,8 +159,19 @@ void RsyncDeployService::deployNextFile()
} }
const DeployableFile file = m_deployableFiles.takeFirst(); const DeployableFile file = m_deployableFiles.takeFirst();
const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*connection(), m_flags); const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*connection(), m_flags);
QString localFilePath = file.localFilePath().toString();
// On Windows, rsync is either from msys or cygwin. Neither work with the other's ssh.exe.
if (HostOsInfo::isWindowsHost()) {
localFilePath = '/' + localFilePath.at(0) + localFilePath.mid(2);
if (anyOf(cmdLine.options, [](const QString &opt) {
return opt.contains("cygwin", Qt::CaseInsensitive); })) {
localFilePath.prepend("/cygdrive");
}
}
const QStringList args = QStringList(cmdLine.options) const QStringList args = QStringList(cmdLine.options)
<< (file.localFilePath().toString() + (file.localFilePath().isDir() ? "/" : QString())) << (localFilePath + (file.localFilePath().isDir() ? "/" : QString()))
<< (cmdLine.remoteHostSpec + ':' + file.remoteFilePath()); << (cmdLine.remoteHostSpec + ':' + file.remoteFilePath());
m_rsync.start("rsync", args); // TODO: Get rsync location from settings? m_rsync.start("rsync", args); // TODO: Get rsync location from settings?
} }
@@ -228,7 +239,7 @@ RsyncCommandLine RsyncDeployStep::rsyncCommand(const SshConnection &sshConnectio
{ {
const QString sshCmdLine = QtcProcess::joinArgs( const QString sshCmdLine = QtcProcess::joinArgs(
QStringList{SshSettings::sshFilePath().toUserOutput()} QStringList{SshSettings::sshFilePath().toUserOutput()}
<< sshConnection.connectionOptions(SshSettings::sshFilePath())); << sshConnection.connectionOptions(SshSettings::sshFilePath()), OsTypeLinux);
const SshConnectionParameters sshParams = sshConnection.connectionParameters(); const SshConnectionParameters sshParams = sshConnection.connectionParameters();
return RsyncCommandLine(QStringList{"-e", sshCmdLine, flags}, return RsyncCommandLine(QStringList{"-e", sshCmdLine, flags},
sshParams.userName() + '@' + sshParams.host()); sshParams.userName() + '@' + sshParams.host());

View File

@@ -4,6 +4,7 @@ add_qtc_plugin(StudioWelcome
DEFINES STUDIO_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/qml/" DEFINES STUDIO_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/qml/"
SOURCES SOURCES
studiowelcomeplugin.cpp studiowelcomeplugin.h studiowelcomeplugin.cpp studiowelcomeplugin.h
examplecheckout.cpp examplecheckout.h
studiowelcome_global.h studiowelcome_global.h
studiowelcome.qrc studiowelcome.qrc
"${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc" "${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc"

View File

@@ -0,0 +1,347 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "examplecheckout.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
#include <utils/archive.h>
#include <utils/networkaccessmanager.h>
#include <utils/qtcassert.h>
#include <QDialog>
#include <QFileDialog>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QQuickItem>
#include <QQuickWidget>
ExampleCheckout::ExampleCheckout(QObject *) {}
void ExampleCheckout::checkoutExample(const QUrl &url)
{
FileDownloader::registerQmlType();
static bool once = []() {
FileDownloader::registerQmlType();
FileExtractor::registerQmlType();
return true;
}();
QTC_ASSERT(once, ;);
m_dialog.reset(new QDialog(Core::ICore::dialogParent()));
m_dialog->setModal(true);
m_dialog->setFixedSize(620, 300);
QHBoxLayout *layout = new QHBoxLayout(m_dialog.get());
layout->setContentsMargins(2, 2, 2, 2);
auto widget = new QQuickWidget(m_dialog.get());
layout->addWidget(widget);
widget->engine()->addImportPath("qrc:/studiofonts");
widget->engine()->addImportPath(Core::ICore::resourcePath()
+ "/qmldesigner/propertyEditorQmlSources/imports");
widget->setSource(QUrl("qrc:/qml/downloaddialog/main.qml"));
m_dialog->setWindowFlag(Qt::Tool, true);
widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
rootObject = widget->rootObject();
QTC_ASSERT(rootObject, qWarning() << "QML error"; return );
rootObject->setProperty("url", url);
m_dialog->show();
rootObject = widget->rootObject();
connect(rootObject, SIGNAL(canceled()), this, SLOT(handleCancel()));
connect(rootObject, SIGNAL(accepted()), this, SLOT(handleAccepted()));
}
QString ExampleCheckout::extractionFolder() const
{
return m_extrationFolder;
}
ExampleCheckout::~ExampleCheckout() {}
void ExampleCheckout::handleCancel()
{
m_dialog->close();
m_dialog.release()->deleteLater();
deleteLater();
}
void ExampleCheckout::handleAccepted()
{
QQmlProperty property(rootObject, "path");
m_extrationFolder = property.read().toString();
m_dialog->close();
emit finishedSucessfully();
m_dialog.release()->deleteLater();
deleteLater();
}
void FileDownloader::registerQmlType()
{
qmlRegisterType<FileDownloader>("ExampleCheckout", 1, 0, "FileDownloader");
}
FileDownloader::FileDownloader(QObject *parent)
: QObject(parent)
{}
FileDownloader::~FileDownloader()
{
m_tempFile.remove();
}
void FileDownloader::start()
{
m_tempFile.setFileName(QDir::tempPath() + "/" + name() + ".XXXXXX" + ".zip");
m_tempFile.open(QIODevice::WriteOnly);
auto request = QNetworkRequest(m_url);
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, true);
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
m_tempFile.write(reply->readAll());
});
QNetworkReply::connect(reply,
&QNetworkReply::downloadProgress,
this,
[this](qint64 current, qint64 max) {
if (max == 0)
return;
m_progress = current * 100 / max;
emit progressChanged();
});
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
if (reply->error()) {
m_tempFile.remove();
if (m_url != reply->url()) {
m_url = reply->url();
start();
} else {
emit downloadFailed();
}
} else {
m_tempFile.flush();
m_tempFile.close();
m_finished = true;
emit finishedChanged();
}
});
}
void FileDownloader::setUrl(const QUrl &url)
{
m_url = url;
emit nameChanged();
}
QUrl FileDownloader::url() const
{
return m_url;
}
bool FileDownloader::finished() const
{
return m_finished;
}
bool FileDownloader::error() const
{
return m_error;
}
QString FileDownloader::name() const
{
const QFileInfo fileInfo(m_url.path());
return fileInfo.baseName();
}
QString FileDownloader::completeBaseName() const
{
const QFileInfo fileInfo(m_url.path());
return fileInfo.completeBaseName();
}
int FileDownloader::progress() const
{
return m_progress;
}
QString FileDownloader::tempFile() const
{
return QFileInfo(m_tempFile).canonicalFilePath();
}
FileExtractor::FileExtractor(QObject *parent)
: QObject(parent)
{
if (Core::DocumentManager::instance())
m_targetPath = Core::DocumentManager::projectsDirectory();
else
m_targetPath = Utils::FilePath::fromString("/temp/");
m_timer.setInterval(500);
m_timer.setSingleShot(false);
}
FileExtractor::~FileExtractor() {}
void FileExtractor::registerQmlType()
{
qmlRegisterType<FileExtractor>("ExampleCheckout", 1, 0, "FileExtractor");
}
QString FileExtractor::targetPath() const
{
return m_targetPath.toUserOutput();
}
void FileExtractor::browse()
{
const QString path = QFileDialog::getExistingDirectory(Core::ICore::dialogParent(),
(tr("Choose Directory")),
m_targetPath.toString());
if (!path.isEmpty())
m_targetPath = Utils::FilePath::fromString(path);
emit targetPathChanged();
emit targetFolderExistsChanged();
}
void FileExtractor::setSourceFile(QString &sourceFilePath)
{
m_sourceFile = Utils::FilePath::fromString(sourceFilePath);
emit targetFolderExistsChanged();
}
void FileExtractor::setArchiveName(QString &filePath)
{
m_archiveName = filePath;
}
const QString FileExtractor::detailedText()
{
return m_detailedText;
}
bool FileExtractor::finished() const
{
return m_finished;
}
QString FileExtractor::currentFile() const
{
return m_currentFile;
}
QString FileExtractor::size() const
{
return m_size;
}
QString FileExtractor::count() const
{
return m_count;
}
bool FileExtractor::targetFolderExists() const
{
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
return QFileInfo(targetFolder).exists();
}
QString FileExtractor::archiveName() const
{
return m_archiveName;
}
QString FileExtractor::sourceFile() const
{
return m_sourceFile.toString();
}
void FileExtractor::extract()
{
Utils::Archive *archive = Utils::Archive::unarchive(m_sourceFile, m_targetPath);
archive->setParent(this);
QTC_ASSERT(archive, return );
m_timer.start();
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder]() {
static QHash<QString, int> hash;
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
int count = 0;
while (it.hasNext()) {
if (!hash.contains(it.fileName())) {
m_currentFile = it.fileName();
hash.insert(m_currentFile, 0);
emit currentFileChanged();
}
it.next();
count++;
}
m_size = QString::number(bytesBefore
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable());
m_count = QString::number(count);
emit sizeChanged();
});
QObject::connect(archive, &Utils::Archive::outputReceived, this, [this](const QString &output) {
m_detailedText += output;
emit detailedTextChanged();
});
QObject::connect(archive, &Utils::Archive::finished, [this](bool ret) {
m_finished = ret;
m_timer.stop();
emit finishedChanged();
QTC_ASSERT(ret, ;);
});
}

View File

@@ -0,0 +1,163 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <utils/fileutils.h>
#include <QObject>
#include <QTimer>
#include <QtQml>
#include <memory>
QT_BEGIN_NAMESPACE
class QDialog;
QT_END_NAMESPACE
class ExampleCheckout : public QObject
{
Q_OBJECT
public:
explicit ExampleCheckout(QObject *parent = nullptr);
Q_INVOKABLE void checkoutExample(const QUrl &url);
QString extractionFolder() const;
~ExampleCheckout();
public slots:
void handleCancel();
void handleAccepted();
signals:
void finishedSucessfully();
private:
std::unique_ptr<QDialog> m_dialog;
QObject *rootObject = nullptr;
QString m_extrationFolder;
};
class FileExtractor : public QObject
{
Q_OBJECT
Q_PROPERTY(QString targetPath READ targetPath NOTIFY targetPathChanged)
Q_PROPERTY(QString archiveName READ archiveName WRITE setArchiveName)
Q_PROPERTY(QString detailedText READ detailedText NOTIFY detailedTextChanged)
Q_PROPERTY(QString currentFile READ currentFile NOTIFY currentFileChanged)
Q_PROPERTY(QString size READ size NOTIFY sizeChanged)
Q_PROPERTY(QString count READ count NOTIFY sizeChanged)
Q_PROPERTY(QString sourceFile READ sourceFile WRITE setSourceFile)
Q_PROPERTY(bool finished READ finished NOTIFY finishedChanged)
Q_PROPERTY(bool targetFolderExists READ targetFolderExists NOTIFY targetFolderExistsChanged)
public:
explicit FileExtractor(QObject *parent = nullptr);
~FileExtractor();
static void registerQmlType();
QString targetPath() const;
void setSourceFile(QString &sourceFilePath);
void setArchiveName(QString &filePath);
const QString detailedText();
bool finished() const;
QString currentFile() const;
QString size() const;
QString count() const;
bool targetFolderExists() const;
QString sourceFile() const;
QString archiveName() const;
Q_INVOKABLE void browse();
Q_INVOKABLE void extract();
signals:
void targetPathChanged();
void detailedTextChanged();
void finishedChanged();
void currentFileChanged();
void sizeChanged();
void targetFolderExistsChanged();
private:
Utils::FilePath m_targetPath;
Utils::FilePath m_sourceFile;
QString m_detailedText;
bool m_finished = false;
QTimer m_timer;
QString m_currentFile;
QString m_size;
QString m_count;
QString m_archiveName;
};
class FileDownloader : public QObject
{
Q_OBJECT
Q_PROPERTY(QUrl url READ url WRITE setUrl)
Q_PROPERTY(bool finished READ finished NOTIFY finishedChanged)
Q_PROPERTY(bool error READ error NOTIFY errorChanged)
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(QString completeBaseName READ completeBaseName NOTIFY nameChanged)
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
Q_PROPERTY(QString tempFile READ tempFile NOTIFY finishedChanged)
public:
explicit FileDownloader(QObject *parent = nullptr);
~FileDownloader();
void setUrl(const QUrl &url);
QUrl url() const;
bool finished() const;
bool error() const;
static void registerQmlType();
QString name() const;
QString completeBaseName() const;
int progress() const;
QString tempFile() const;
Q_INVOKABLE void start();
signals:
void finishedChanged();
void errorChanged();
void nameChanged();
void progressChanged();
void downloadFailed();
private:
QUrl m_url;
bool m_finished = false;
bool m_error = false;
int m_progress = 0;
QFile m_tempFile;
};

View File

@@ -0,0 +1,249 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.9
import QtQuick.Shapes 1.0
Shape {
id: root
implicitWidth: 100
implicitHeight: 100
property alias gradient: path.fillGradient
property alias strokeStyle: path.strokeStyle
property alias strokeWidth: path.strokeWidth
property alias strokeColor: path.strokeColor
property alias dashPattern: path.dashPattern
property alias joinStyle: path.joinStyle
property alias fillColor: path.fillColor
property alias capStyle: path.capStyle
property alias dashOffset: path.dashOffset
property real begin: 0
property real end: 90
property real arcWidth: 10
property real arcWidthBegin: arcWidth
property real arcWidthEnd: arcWidth
property real radiusInnerAdjust: 0
property real radiusOuterAdjust: 0
property real alpha: clamp(sortedEnd() - sortedBegin(),0, 359.9)
layer.enabled: antialiasing
layer.smooth: antialiasing
layer.textureSize: Qt.size(width * 2, height * 2)
property bool outlineArc: false
property bool round: false
property bool roundEnd: round
property bool roundBegin: round
function clamp(num, min, max) {
return num <= min ? min : num >= max ? max : num;
}
function myCos(angleInDegrees) {
var angleInRadians = angleInDegrees * Math.PI / 180.0;
return Math.cos(angleInRadians)
}
function mySin(angleInDegrees) {
var angleInRadians = angleInDegrees * Math.PI / 180.0;
return Math.sin(angleInRadians)
}
function polarToCartesianX(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = angleInDegrees * Math.PI / 180.0;
var x = centerX + radius * Math.cos(angleInRadians)
return x
}
function polarToCartesianY(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = angleInDegrees * Math.PI / 180.0;
var y = centerY + radius * Math.sin(angleInRadians);
return y
}
function calc()
{
path.__xRadius = root.width / 2 - root.strokeWidth / 2
path.__yRadius = root.height / 2 - root.strokeWidth / 2
path.__Xcenter = root.width / 2
path.__Ycenter = root.height / 2
path.startX = root.polarToCartesianX(path.__Xcenter, path.__Ycenter, path.__xRadius, root.sortedBegin() - 90) + root.__beginOff * myCos(root.sortedBegin() + 90)
path.startY = root.polarToCartesianY(path.__Xcenter, path.__Ycenter, path.__yRadius, root.sortedBegin() - 90) + root.__beginOff * mySin(root.sortedBegin() + 90)
arc1.x = root.polarToCartesianX(path.__Xcenter, path.__Ycenter, path.__xRadius, root.sortedEnd() - 90) + root.__endOff * myCos(root.sortedEnd() + 90)
arc1.y = root.polarToCartesianY(path.__Xcenter, path.__Ycenter, path.__yRadius, root.sortedEnd() - 90) + root.__endOff * mySin(root.sortedEnd() + 90)
arc1.radiusX = path.__xRadius - root.__endOff / 2 -root.__beginOff / 2 + root.radiusOuterAdjust
arc1.radiusY = path.__yRadius - root.__endOff / 2 -root.__beginOff / 2 + root.radiusOuterAdjust
arc1.useLargeArc = root.alpha > 180
}
function sortedBegin()
{
return(Math.min(root.begin, root.end))
}
function sortedEnd()
{
return(Math.max(root.begin, root.end))
}
onWidthChanged: calc()
onHeightChanged: calc()
onBeginChanged: calc()
onEndChanged: calc()
onAlphaChanged: calc()
ShapePath {
id: path
property real __xRadius
property real __yRadius
property real __Xcenter
property real __Ycenter
strokeColor: "red"
strokeWidth: 4
capStyle: ShapePath.FlatCap
}
property real __beginOff: {
if (root.arcWidthEnd > root.arcWidthBegin)
return (root.arcWidthEnd - root.arcWidthBegin) / 2
return 0;
}
property real __endOff: {
if (root.arcWidthBegin > root.arcWidthEnd)
return (root.arcWidthBegin - root.arcWidthEnd) / 2
return 0;
}
property real __startP: root.arcWidthBegin + __beginOff
property real __endP: root.arcWidthEnd + __endOff
Item {
id: shapes
PathArc {
id: arc1
property bool add: true
}
PathLine {
relativeX: root.arcWidthEnd * myCos(root.sortedEnd())
relativeY: root.arcWidthEnd * mySin(root.sortedEnd())
property bool add: !root.roundEnd && (root.outlineArc && root.alpha < 359.8)
}
PathArc {
relativeX: root.arcWidthEnd * myCos(root.sortedEnd())
relativeY: root.arcWidthEnd * mySin(root.sortedEnd())
radiusX: root.arcWidthEnd /2
radiusY: root.arcWidthEnd /2
property bool add: root.roundEnd && (root.outlineArc && root.alpha < 359.8)
}
PathMove {
relativeX: root.arcWidthEnd * myCos(root.sortedEnd())
relativeY: root.arcWidthEnd * mySin(root.sortedEnd())
property bool add: root.outlineArc && root.alpha > 359.7
}
PathArc {
id: arc2
useLargeArc: arc1.useLargeArc
radiusX: path.__xRadius - root.arcWidthBegin + root.__beginOff / 2 + root.__endOff / 2 + root.radiusInnerAdjust
radiusY:path.__yRadius - root.arcWidthBegin + root.__beginOff / 2 + root.__endOff / 2 + root.radiusInnerAdjust
x: path.startX + root.arcWidthBegin * myCos(root.sortedBegin())
y: path.startY + root.arcWidthBegin * mySin(root.sortedBegin())
direction: PathArc.Counterclockwise
property bool add: root.outlineArc
}
PathLine {
x: path.startX
y: path.startY
property bool add: !root.roundBegin && root.outlineArc && root.alpha < 359.8
}
PathArc {
x: path.startX
y: path.startY
radiusX: root.arcWidthEnd /2
radiusY: root.arcWidthEnd /2
property bool add: root.roundBegin && root.outlineArc && root.alpha < 359.8
}
PathMove {
x: path.startX
y: path.startY
property bool add: root.outlineArc && root.alpha == 360
}
}
function invalidatePaths() {
if (!root.__completed)
return
for (var i = 0; i < shapes.resources.length; i++) {
var s = shapes.resources[i];
if (s.add)
path.pathElements.push(s)
}
}
property bool __completed: false
Component.onCompleted: {
root.__completed = true
invalidatePaths()
calc()
}
}

View File

@@ -0,0 +1,129 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.12
import QtQuick.Timeline 1.0
Rectangle {
id: rectangle
width: 60
height: 60
color: "#8c8c8c"
radius: 50
property alias inputMax: rangeMapper.inputMax
property alias inputMin: rangeMapper.inputMin
property alias value: minMaxMapper.input
ArcItem {
id: arc
x: -1
y: -1
width: 62
height: 62
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
end: rangeMapper.value
antialiasing: true
strokeWidth: 8
strokeColor: "#ffffff"
capStyle: 32
fillColor: "#00000000"
}
RangeMapper {
id: rangeMapper
outputMax: 358
input: minMaxMapper.value
}
MinMaxMapper {
id: minMaxMapper
input: 95
max: rangeMapper.inputMax
min: rangeMapper.inputMin
}
Rectangle {
id: rectangle1
width: 60
height: 60
color: "#ffffff"
radius: 40
anchors.verticalCenter: parent.verticalCenter
scale: 1
anchors.horizontalCenter: parent.horizontalCenter
}
Timeline {
id: timeline
currentFrame: rangeMapper.value
enabled: true
endFrame: 360
startFrame: 0
KeyframeGroup {
target: rectangle1
property: "opacity"
Keyframe {
frame: 0
value: 0
}
Keyframe {
frame: 360
value: 1
}
}
KeyframeGroup {
target: rectangle1
property: "scale"
Keyframe {
frame: 360
value: 1
}
Keyframe {
frame: 0
value: 0.1
}
}
KeyframeGroup {
target: arc
property: "opacity"
Keyframe {
value: 0
frame: 0
}
Keyframe {
value: 1
frame: 40
}
}
}
}

View File

@@ -0,0 +1,193 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.12
import QtQuick.Timeline 1.0
Item {
id: coolProgressBar
width: 605
height: 16
property alias value: timeline.currentFrame
clip: true
Timeline {
id: timeline
enabled: true
endFrame: 100
startFrame: 0
KeyframeGroup {
target: rectangle
property: "width"
Keyframe {
value: 0
frame: 0
}
Keyframe {
value: 150
frame: 25
}
Keyframe {
value: 300
frame: 50
}
Keyframe {
value: 450
frame: 75
}
Keyframe {
value: 600
frame: 100
}
}
KeyframeGroup {
target: rectangle1
property: "width"
Keyframe {
value: 0
frame: 0
}
Keyframe {
value: 300
frame: 25
}
Keyframe {
value: 450
frame: 50
}
Keyframe {
value: 600
frame: 75
}
}
KeyframeGroup {
target: rectangle2
property: "width"
Keyframe {
value: 0
frame: 0
}
Keyframe {
value: 450
frame: 25
}
Keyframe {
value: 600
frame: 50
}
}
KeyframeGroup {
target: rectangle3
property: "width"
Keyframe {
value: 0
frame: 0
}
Keyframe {
value: 600
frame: 25
}
}
KeyframeGroup {
target: content
property: "opacity"
Keyframe {
value: 0
frame: 0
}
Keyframe {
value: 1
frame: 50
}
}
}
Item {
id: content
anchors.fill: parent
Rectangle {
id: rectangle
y: 0
width: 80
height: 16
color: "#ffffff"
radius: 12
}
Rectangle {
id: rectangle1
y: 0
width: 80
height: 16
opacity: 0.6
color: "#ffffff"
radius: 12
}
Rectangle {
id: rectangle2
y: 0
width: 80
height: 16
opacity: 0.4
color: "#ffffff"
radius: 12
}
Rectangle {
id: rectangle3
y: 0
width: 80
height: 16
opacity: 0.2
color: "#ffffff"
radius: 12
}
}
}
/*##^##
Designer {
D{i:0;height:16;width:590}D{i:1}
}
##^##*/

View File

@@ -0,0 +1,91 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.10
import QtQuick.Templates 2.1 as T
T.Button {
id: control
implicitWidth: Math.max(buttonBackground ? buttonBackground.implicitWidth : 0,
textItem.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(buttonBackground ? buttonBackground.implicitHeight : 0,
textItem.implicitHeight + topPadding + bottomPadding)
leftPadding: 4
rightPadding: 4
text: "My Button"
property color defaultColor: "#b9b9ba"
property color checkedColor: "#ffffff"
background: buttonBackground
Rectangle {
id: buttonBackground
color: control.defaultColor
implicitWidth: 100
implicitHeight: 40
opacity: enabled ? 1 : 0.3
radius: 0
border.width: 1
}
contentItem: textItem
Text {
id: textItem
text: control.text
opacity: enabled ? 1.0 : 0.3
color: "#bababa"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
states: [
State {
name: "normal"
when: !control.down && !control.checked
PropertyChanges {
target: buttonBackground
color: "#2d2e30"
}
},
State {
name: "down"
when: control.down || control.checked
PropertyChanges {
target: textItem
color: control.checkedColor
}
PropertyChanges {
target: buttonBackground
color: "#545456"
border.color: "#70a2f5"
border.width: 2
}
}
]
}

View File

@@ -0,0 +1,37 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick.Controls 2.15
import ExampleCheckout 1.0
import QtQuick.Layouts 1.11
import StudioFonts 1.0
Text {
font.family: StudioFonts.titilliumWeb_light
color: root.textColor
}

View File

@@ -0,0 +1,54 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick Designer Components.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.10
QtObject {
id: object
property real input
property bool minClipped: object.input < object.min
property bool maxClipped: object.input > object.max
property bool outOfRage: object.maxClipped ||object.minClipped
property real value: {
if (object.maxClipped)
return object.max
if (object.minClipped)
return object.min
return object.input
}
property real min: 0
property real max: 100
}

View File

@@ -0,0 +1,48 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick Designer Components.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.10
QtObject {
id: object
property real input
property real value: {
var slope = (object.outputMax - object.outputMin) / (object.inputMax - object.inputMin)
return object.outputMin + slope * (object.input - object.inputMin)
}
property real inputMin: 0
property real inputMax: 100
property real outputMin: 0
property real outputMax: 100
}

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QmlProject 1.1
Project {
mainFile: "main.qml"
/* Include .qml, .js, and image files from current directory and subdirectories */
QmlFiles {
directory: "."
}
JavaScriptFiles {
directory: "."
}
ImageFiles {
directory: "."
}
/* List of plugin directories passed to QML runtime */
importPaths: [ "mockData", "../../../../share/3rdparty/studiofonts", "../../../../../share/qtcreator/qmldesigner/propertyEditorQmlSources/imports" ]
Environment {
QT_AUTO_SCREEN_SCALE_FACTOR: "1"
}
}

View File

@@ -0,0 +1,312 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
import QtQuick.Controls 2.15
import ExampleCheckout 1.0
import QtQuick.Layouts 1.11
import StudioFonts 1.0
Rectangle {
id: root
property alias url: downloader.url
property string path: fileExtractor.targetPath
width: 620
height: 300
color: "#2d2e30"
property color textColor: "#b9b9ba"
signal canceled
signal accepted
StackLayout {
id: stackLayout
anchors.fill: parent
currentIndex: 0
FileExtractor {
id: fileExtractor
sourceFile: downloader.tempFile
archiveName: downloader.completeBaseName
}
FileDownloader {
id: downloader
//onNameChanged: start()
onFinishedChanged: {
button.enabled = downloader.finished
if (!downloader.finished)
stackLayout.currentIndex = 3
}
onDownloadFailed: stackLayout.currentIndex = 3
}
Item {
id: download
Layout.fillHeight: true
Layout.fillWidth: true
DialogButton {
id: button
x: 532
y: 432
text: qsTr("Continue")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.rightMargin: 20
enabled: false
onClicked: stackLayout.currentIndex = 1
}
CoolProgressBar {
id: coolProgressBar
width: 605
anchors.top: parent.top
value: downloader.progress
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 69
}
DialogLabel {
x: 201
text: "Downloading Example " + downloader.completeBaseName
anchors.top: parent.top
anchors.topMargin: 22
anchors.horizontalCenter: parent.horizontalCenter
}
DialogButton {
id: downloadbutton
y: 420
enabled: !button.enabled
text: qsTr("Start Download")
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 20
anchors.bottomMargin: 20
onClicked: {
downloadbutton.enabled = false
downloader.start()
}
}
CircularIndicator {
id: circularIndicator
x: 304
anchors.top: parent.top
anchors.horizontalCenterOffset: 0
value: downloader.progress
anchors.topMargin: 120
anchors.horizontalCenter: parent.horizontalCenter
}
}
Item {
id: destiationfolder
Layout.fillHeight: true
Layout.fillWidth: true
DialogButton {
id: nextPageDestination
x: 532
y: 432
text: qsTr("Continue")
anchors.right: parent.right
anchors.bottom: parent.bottom
enabled: !fileExtractor.targetFolderExists
anchors.bottomMargin: 20
anchors.rightMargin: 20
onClicked: {
stackLayout.currentIndex = 2
fileExtractor.extract()
}
}
RowLayout {
y: 114
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 104
anchors.leftMargin: 67
TextField {
id: textField
text: fileExtractor.targetPath
Layout.fillWidth: true
font.family: StudioFonts.titilliumWeb_light
wrapMode: Text.WordWrap
selectByMouse: true
readOnly: true
}
DialogButton {
id: browse
text: qsTr("Browse")
onClicked: fileExtractor.browse()
}
}
DialogLabel {
id: label
y: 436
text: qsTr("Folder ") + downloader.completeBaseName + (" already exists")
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 20
anchors.bottomMargin: 20
visible: !nextPageDestination.enabled
}
DialogButton {
id: button5
x: 400
y: 420
text: qsTr("Cancel")
anchors.right: nextPageDestination.left
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.rightMargin: 20
onClicked: root.canceled()
}
DialogLabel {
text: "Choose installation folder"
anchors.top: parent.top
anchors.topMargin: 22
anchors.horizontalCenter: parent.horizontalCenter
x: 8
}
}
Item {
id: extraction
Layout.fillHeight: true
Layout.fillWidth: true
DialogButton {
id: done
x: 532
y: 432
text: qsTr("Open")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.rightMargin: 20
enabled: fileExtractor.finished
onClicked: root.accepted()
}
DialogLabel {
id: text2
text: fileExtractor.count + " files " + (fileExtractor.size / 1024 / 1024).toFixed(2) + " MB "+ fileExtractor.currentFile
anchors.left: parent.left
anchors.bottom: parent.bottom
font.pixelSize: 12
wrapMode: Text.WrapAnywhere
anchors.leftMargin: 20
anchors.bottomMargin: 20
}
DialogButton {
id: details
x: 8
text: qsTr("Details")
anchors.top: parent.top
anchors.topMargin: 66
anchors.horizontalCenter: parent.horizontalCenter
checkable: true
}
DialogLabel {
x: 8
text: "Extracting Example " + downloader.completeBaseName
anchors.top: parent.top
anchors.topMargin: 22
anchors.horizontalCenter: parent.horizontalCenter
}
Flickable {
visible: details.checked
clip: true
anchors.bottomMargin: 60
anchors.rightMargin: 20
anchors.leftMargin: 20
anchors.topMargin: 120
anchors.fill: parent
id: flickable
interactive: false
DialogLabel {
onHeightChanged: flickable.contentY = text1.implicitHeight - flickable.height
id: text1
text: fileExtractor.detailedText
font.pixelSize: 12
wrapMode: Text.WrapAnywhere
width: flickable.width
}
}
}
Item {
id: failed
Layout.fillHeight: true
Layout.fillWidth: true
DialogButton {
id: finish
x: 532
y: 432
text: qsTr("Finish")
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.rightMargin: 20
onClicked: root.canceled()
}
DialogLabel {
x: 8
text: qsTr("Download failed")
anchors.top: parent.top
anchors.topMargin: 22
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
QtObject {
id: root
signal downloadFailed
property bool finished: false
property bool url
property int progress: 55
Behavior on progress { PropertyAnimation {
duration: 2000
}
}
function start() {
timer.start()
root.progress = 100
}
property Timer timer: Timer {
interval: 2000
repeat: false
onTriggered: {
root.finished
root.progress = 1000
finished = true
}
}
}

View File

@@ -0,0 +1,41 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.0
QtObject {
signal finished
property string sourceFile: "SomeExample.zip"
property string archiveName: "SomeExample"
property string targetPath: "/extract/here"
property string detailedText: "Start" +
"\n1 Some detailed info about extraction\nSome detailed info about extraction\nSome detailed info about extractionSome detailed info about extractionSome detailed info about extraction" +
"\n2 Some detailed info about extraction\nSome detailed info about extraction\nSome detailed info about extractionSome detailed info about extractionSome detailed info about extraction" +
"\n3 Some detailed info about extraction\nSome detailed info about extraction\nSome detailed info about extractionSome detailed info about extractionSome detailed info about extraction" +
"\nend"
}

View File

@@ -0,0 +1,2 @@
FileDownloader 1.0 FileDownloader.qml
FileExtractor 1.0 FileExtractor.qml

View File

@@ -74,4 +74,13 @@ ListModel {
thumbnail: "images/washingmachinedemo_thumbnail.png" thumbnail: "images/washingmachinedemo_thumbnail.png"
displayName: "Washing Machine" displayName: "Washing Machine"
} }
ListElement {
projectName: "highendivisystem"
qmlFileName: "Screen01.ui.qml"
thumbnail: "images/highendivi_thumbnail.png"
displayName: "Highend IVI System"
url: "https://download.qt.io/learning/examples/qtdesignstudio/highendivisystem.zip"
showDownload: true
}
} }

View File

@@ -35,6 +35,8 @@ Item {
property alias imageSource: image.source property alias imageSource: image.source
property alias labelText: label.text property alias labelText: label.text
property alias downloadIcon: downloadCloud.visible
onVisibleChanged: { onVisibleChanged: {
animateOpacity.start() animateOpacity.start()
animateScale.start() animateScale.start()
@@ -89,6 +91,19 @@ Item {
rectangle.color = "#262728" rectangle.color = "#262728"
label.color = "#686868" label.color = "#686868"
} }
Image {
id: downloadCloud
x: 210
y: 118
width: 60
height: 60
source: "images/downloadCloud.svg"
sourceSize.height: 60
sourceSize.width: 60
fillMode: Image.PreserveAspectFit
visible: false
}
} }
} }
@@ -187,3 +202,9 @@ Item {
font.family: StudioFonts.titilliumWeb_regular font.family: StudioFonts.titilliumWeb_regular
} }
} }
/*##^##
Designer {
D{i:0;formeditorZoom:1.3300000429153442}D{i:8}
}
##^##*/

View File

@@ -39,6 +39,7 @@ GridView {
id: hoverOverDesaturate id: hoverOverDesaturate
imageSource: typeof(thumbnail) === "undefined" ? "images/thumbnail_test.png" : thumbnail; imageSource: typeof(thumbnail) === "undefined" ? "images/thumbnail_test.png" : thumbnail;
labelText: displayName labelText: displayName
downloadIcon: typeof(showDownload) === "undefined" ? false : showDownload;
SequentialAnimation { SequentialAnimation {
id: animation id: animation

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 128 128" overflow="visible" xml:space="preserve">
<g transform="translate(0.000000,2000.000000) scale(0.100000,-0.100000)">
<path fill="#686868" d="M764,19815.1c-12.5-0.6-28.9-2.1-38.4-3.5c-30-4.3-73-22.5-107.4-45.4c-19.9-13.2-34.6-25.2-51.1-41.6
c-18.6-18.6-30.1-33.4-43.2-55.8l-5.8-9.9l-6.7,3.2c-44.8,21.1-105.6,27.1-154.5,15.3c-35.4-8.5-75.1-30-104.5-56.5
c-3.4-3.1-6.8-6-7.5-6.5c-2.2-1.6-17.1-17.9-22.3-24.5c-7.4-9.3-16.5-23.4-21.7-33.8c-13.5-26.7-25.2-66.5-26.7-91l-0.4-7
l-15.9-7.9c-26.7-13.3-44.8-26.6-66.8-49.2c-18.9-19.3-31.4-36.4-41.9-57c-22.4-44.3-29.9-95.3-20.8-142.8
c8.4-44.1,29.1-83.5,61.5-117.1c35.2-36.5,62.1-52.4,108.2-64c24-6,47.3-7.8,115.4-8.9c12.4-0.2,29.7-0.4,38.4-0.6
c78.9-1.6,573.8-2.5,615.8-1.1c54,1.7,79,3.6,101.9,7.4c21.4,3.6,36.6,8.4,59.7,18.8c31.7,14.3,49.3,26.2,71,48
c22.6,22.7,38,46.4,49.6,76.8c14.6,38.2,19.8,83.7,13.7,121.3c-5.2,31.9-19.8,67.7-38.7,94.4c-10.5,14.7-28.8,34.7-42.7,46.2
c-28.8,24.1-58.1,39.7-90.8,48.4c-7.5,2-9.1,2.7-9.1,3.6c0,0.6,0.8,6.8,1.7,13.7c1.6,11.5,1.7,14.2,1.7,32.8
c0,21.9-0.9,31.7-4.4,49.8c-9.2,46.3-30,91.8-59.8,130.6c-21.3,27.8-49.5,53.4-77,69.9c-31.4,18.8-83.2,39.1-108.8,42.6
C819.9,19815.7,790.2,19816.3,764,19815.1z M828,19778.4c13-1.8,27.2-6.1,48.6-14.6c24-9.6,42.8-19,56.8-28.3
c57.9-38.7,101.4-106.8,113.6-178c3.9-22.6,4.1-43.6,0.6-69.7c-1.1-8.4-2.2-19-2.3-23.5c-0.3-7.6-0.3-8.5,1.1-11.6
c0.9-2.1,2.6-4.4,4.6-6.1c3.6-3.2,4.9-3.7,23.6-8.6c19.7-5.2,28.8-8.4,42.2-15.2c32.3-16.2,62.4-42.8,82-72.5
c14.5-22,26.1-52.4,29.9-78.6c0.8-5.6,1.1-11.6,1.1-22.8c-0.1-55-19.5-104.3-55.1-140.1c-18.5-18.6-39.9-32.1-71-44.9
c-32.4-13.4-63.1-16.9-162.9-18.8c-36.3-0.7-402.6-0.4-440.8,0.4c-8.2,0.2-43.7,0.4-78.9,0.6c-93.9,0.5-151.4,1.6-178.1,3.5
c-14.9,1.1-24.2,2.5-36.8,5.7c-39,9.9-59.1,21.9-89.9,53.6c-26,26.7-44.1,60-51.4,94.6c-8.9,42.1-3.2,84.4,16.8,124.7
c11.5,23.2,33.3,48.7,58.8,69c10.2,8.2,20.3,14.4,34.3,21.2c21.2,10.4,27.7,15.3,32,24.5c2.4,5,3.5,10.5,3.5,17.2
c0,12.4,5.9,37,14,59.1c4.4,11.9,12.1,27.5,18.3,36.7c18.9,28.3,49.9,55,83.7,71.9c29.5,14.8,54.5,20.2,89.4,19.4
c15-0.3,24.8-1.4,38-4c18.7-3.7,30.7-8,51.1-18.1c17-8.6,19.2-9.1,25.8-7.2c6.1,1.8,8.7,4.9,18.6,22.2c10.8,19,14.4,24.8,20.7,33.2
c28.7,38.1,74.9,72.8,121.8,91.3c23.8,9.4,36.1,12.1,62.8,13.9c5.6,0.4,11.6,0.8,13.3,0.9C774.9,19779.8,823.3,19779.1,828,19778.4
z"/>
</g>
<path fill="#686868" d="M82.4,65.7L70.2,78.7c0,0-0.1,0-0.1,0l0-33.5c0-1.6-1.2-3.1-2.9-3.2c-1.7-0.1-3.1,1.3-3.1,3v33.7c0,0,0,0-0.1,0L52,65.7
c-0.9-1-2.5-1.1-3.6-0.1h0c-1,0.9-1.1,2.5-0.1,3.6l16.7,18c1.2,1.3,3.2,1.3,4.3,0l16.7-18c0.9-1,0.9-2.6-0.1-3.6h0
C84.9,64.6,83.3,64.6,82.4,65.7z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -60,7 +60,7 @@ Item {
ScrollView { ScrollView {
ProjectsGrid { ProjectsGrid {
model: ExamplesModel {} model: ExamplesModel {}
onItemSelected: projectModel.openExample(item.projectName, item.qmlFileName) onItemSelected: projectModel.openExample(item.projectName, item.qmlFileName, item.url)
} }
} }

Some files were not shown because too many files have changed in this diff Show More