Merge remote-tracking branch 'origin/6.0' into qds-2.3

Change-Id: I67a01bae763ef723a88bf4cb94ef29c713eaa743
This commit is contained in:
Tim Jenssen
2021-12-01 17:56:12 +01:00
32 changed files with 702 additions and 526 deletions

View File

@@ -55,10 +55,12 @@
\image qtcreator-build-environment.png "Build Environment" \image qtcreator-build-environment.png "Build Environment"
\note The changes are stored in the local project specific \c{.pro.user} The changes are stored in the local project specific \c{CMakeLists.txt.user}
file. Therefore, they are not suitable for sharing between developers or or \c{.pro.user} file, depending on the build system you use. Therefore,
development PCs. To share settings, incorporate them into the build system. they are not suitable for sharing between developers or development PCs. To
For example, if you use qmake, make the changes in the \c{.pro} file. share settings, incorporate them into the build system. For example, if you
use CMake, make the changes in the \c {CMakeLists.txt} file, and if you use
qmake, make the changes in the \c{.pro} file.
\section1 Batch Editing \section1 Batch Editing

View File

@@ -32,7 +32,7 @@
/*! /*!
\page creator-quick-tour.html \page creator-quick-tour.html
\if defined(qtdesignstudio) \if defined(qtdesignstudio)
\previouspage {Your First UI} \previouspage {Tutorials}
\else \else
\previouspage creator-overview.html \previouspage creator-overview.html
\endif \endif

View File

@@ -25,7 +25,6 @@
/*! /*!
\example loginui1 \example loginui1
\ingroup studioexamples
\ingroup gstutorials \ingroup gstutorials
\nextpage {Log In UI - Positioning} \nextpage {Log In UI - Positioning}

View File

@@ -25,7 +25,6 @@
/*! /*!
\example loginui2 \example loginui2
\ingroup studioexamples
\ingroup gstutorials \ingroup gstutorials
\previouspage {Log In UI - Components} \previouspage {Log In UI - Components}
\nextpage {Log In UI - States} \nextpage {Log In UI - States}

View File

@@ -25,7 +25,6 @@
/*! /*!
\example loginui3 \example loginui3
\ingroup studioexamples
\ingroup gstutorials \ingroup gstutorials
\title Log In UI - States \title Log In UI - States

View File

@@ -25,7 +25,6 @@
/*! /*!
\example loginui4 \example loginui4
\ingroup studioexamples
\ingroup gstutorials \ingroup gstutorials
\title Log In UI - Timeline \title Log In UI - Timeline
@@ -324,5 +323,5 @@
\section1 Next Steps \section1 Next Steps
For more examples about using timelines, see \l{Examples and Tutorials}. For more examples about using timelines, see \l{Examples}.
*/ */

View File

@@ -26,7 +26,7 @@
/*! /*!
\page quick-uis.html \page quick-uis.html
\if defined(qtdesignstudio) \if defined(qtdesignstudio)
\previouspage {Examples and Tutorials} \previouspage {Examples}
\nextpage studio-app-flows.html \nextpage studio-app-flows.html
\else \else
\previouspage qtquick-text-editor.html \previouspage qtquick-text-editor.html

View File

@@ -27,43 +27,29 @@
\previouspage studio-terms.html \previouspage studio-terms.html
\group studioexamples \group studioexamples
\nextpage quick-uis.html \nextpage quick-uis.html
\title Examples and Tutorials \title Examples
In the \uicontrol Welcome mode, you can open examples and tutorials that \QDS comes with a set of example projects. To see these, select \uicontrol
illustrate how to use \QDS. Some examples are delivered together with Examples on the \uicontrol Welcome page when you run \QDS.
\QDS and have been documented, while you can download and install others
for previewing them on the desktop.
\section1 Video Tutorials
The \uicontrol Tutorials tab contains links to video tutorials that provide
more information about \QDS. To watch a tutorial on YouTube, select it in
the tab.
\include qtbridge-tutorial-links.qdocinc qtsketchbridge tutorials
\section1 Examples for Downloading
The \uicontrol Examples tab lists complex example applications for
downloading that demonstrate what you can accomplish with \QDS.
\image studio-examples-download.png "Examples for download in Welcome mode" \image studio-examples-download.png "Examples for download in Welcome mode"
To download the examples and open them in \QDS: To run an example project:
\list 1 \list 1
\li Select an example. \li Select the example.
\li Select \uicontrol {Start Download} to download the example source \li Select the \inlineimage live_preview.png
files. (\uicontrol {Show Live Preview}) button to preview the example.
\li Select the folder where the source files will be installed.
\li Select \uicontrol Continue to install the files.
\li Select \uicontrol Open to open the example in \QDS.
\li Select the \inlineimage live_preview.png
(\uicontrol {Show Live Preview}) button to preview the example.
\endlist \endlist
\section1 Documented Examples Some of the example projects require that you download them before you can run them, to do this:
\list 1
\li Select an example.
\li Select \uicontrol {Start Download}.
\li Select the folder where the source files will be installed.
\li Select \uicontrol Continue to install the files.
\li Select \uicontrol Open to open the example in \QDS.
\endlist
\section1 Example Documentation
The \uicontrol Examples tab lists documented examples of using \QDS. To
open an example in \QDS, select it in the tab.
*/ */

View File

@@ -34,7 +34,7 @@
grouped by categories. You might also find answers to your questions in the grouped by categories. You might also find answers to your questions in the
product documentation by searching or browsing the index in the product documentation by searching or browsing the index in the
\l{Using the Help Mode}{Help mode}. Many questions are also answered by the \l{Using the Help Mode}{Help mode}. Many questions are also answered by the
\l{Examples and Tutorials}{examples and video tutorials}. \l{Examples}{examples} and \l{Tutorials}{video tutorials}.
\list \list
\li \l {FAQ - \QB}{\QB} \li \l {FAQ - \QB}{\QB}

View File

@@ -47,10 +47,10 @@
\QDS is available either as a standalone installation package or \QDS is available either as a standalone installation package or
as an option in the Qt online installer. as an option in the Qt online installer.
\li \l {Your First UI} \li \l {Tutorials}
Follow a set of hands-on tutorials that build on each other to Follow a set of hands-on tutorials that illustrate how to use the
design your first animated UI using preset and custom components. features of \QDS.
\li \l {User Interface} \li \l {User Interface}
Describes the parts and basic features of \QDS. Describes the parts and basic features of \QDS.
@@ -71,7 +71,7 @@
\li \l{Concepts and Terms} \li \l{Concepts and Terms}
Describes main \QDS concepts and terms. Describes main \QDS concepts and terms.
\li \l{Examples and Tutorials} \li \l{Examples}
A set of examples available in the \uicontrol Welcome mode A set of examples available in the \uicontrol Welcome mode
illustrates how to use \QDS features such as the timeline. illustrates how to use \QDS features such as the timeline.

View File

@@ -26,7 +26,7 @@
/*! /*!
\page studio-installation.html \page studio-installation.html
\previouspage studio-getting-started.html \previouspage studio-getting-started.html
\nextpage {Your First UI} \nextpage {Tutorials}
\title Installation \title Installation
@@ -42,8 +42,8 @@
package \l{https://www.qt.io/product/ui-design-tools}{here}. package \l{https://www.qt.io/product/ui-design-tools}{here}.
After the installation, you can start exploring \QDS by following After the installation, you can start exploring \QDS by following
tutorials to \l{Your First UI}{create your first UI}, opening \l{Tutorials}{tutorials}, opening
\l{Examples and Tutorials}{examples}, watching videos, and reading \l{Examples}{examples}, watching videos, and reading
this manual. this manual.
\section1 Stand-Alone Installation \section1 Stand-Alone Installation

View File

@@ -26,7 +26,7 @@
/*! /*!
\page studio-terms.html \page studio-terms.html
\previouspage studio-use-cases.html \previouspage studio-use-cases.html
\nextpage {Examples and Tutorials} \nextpage {Examples}
\title Concepts and Terms \title Concepts and Terms

View File

@@ -31,7 +31,7 @@
\li \l{Getting Started} \li \l{Getting Started}
\list \list
\li \l{Installation} \li \l{Installation}
\li \l{Your First UI} \li \l{Tutorials}
\li \l{User Interface} \li \l{User Interface}
\list \list
\li \l{Selecting Modes} \li \l{Selecting Modes}
@@ -59,7 +59,7 @@
\li \l{Creating Projects} \li \l{Creating Projects}
\li \l{Use Cases} \li \l{Use Cases}
\li \l{Concepts and Terms} \li \l{Concepts and Terms}
\li \l{Examples and Tutorials} \li \l{Examples}
\endlist \endlist
\li \l{Wireframing} \li \l{Wireframing}
\list \list

View File

@@ -28,14 +28,22 @@
\previouspage studio-installation.html \previouspage studio-installation.html
\nextpage creator-quick-tour.html \nextpage creator-quick-tour.html
\title Your First UI \title Tutorials
\image loginui4.gif "Log In UI" \image loginui4.gif "Log In UI"
You can follow a set of hands-on tutorials that build on each other to \section1 Video Tutorials
When you run \QDS, the \uicontrol Tutorials tab in \uicontrol Welcome mode contains links
to video tutorials. To watch a tutorial on YouTube,
select it.
\section1 Written Tutorials
You can follow a set of hands-on tutorials that
illustrate how to use the features of \QDS. Even if you plan to export your illustrate how to use the features of \QDS. Even if you plan to export your
designs from a design tool, it is useful to first create a small UI from designs from a design tool, it is useful to go through tutorials to learn to
scratch to learn to use \QDS. In particular, \e {Log In UI - Components} use \QDS. In particular, \l {Log In UI - Components}
describes the terms and concepts that you will run into when exporting describes the terms and concepts that you will run into when exporting
designs with \QB. designs with \QB.
@@ -43,8 +51,8 @@
yourself with the parts of \QDS in general, and the \uicontrol Design yourself with the parts of \QDS in general, and the \uicontrol Design
mode in particular: \l{User Interface} and \l{Design Views}. mode in particular: \l{User Interface} and \l{Design Views}.
In addition to these entry-level tutorials, \QDS comes with examples In addition to these tutorials, \QDS comes with examples that you can open
and video tutorials that you can open from the \uicontrol Examples and from the \uicontrol Examples and tabs in the \uicontrol Welcome mode. For more
\uicontrol Tutorials tabs in the \uicontrol Welcome mode. For more information, see \l {Examples}.
information, see \l {Examples and Tutorials}.
*/ */

View File

@@ -48,12 +48,12 @@
\li \b {\l{Getting Started}} \li \b {\l{Getting Started}}
\list \list
\li \l{Installation} \li \l{Installation}
\li \l{Your First UI} \li \l{Tutorials}
\li \l{User Interface} \li \l{User Interface}
\li \l{Creating Projects} \li \l{Creating Projects}
\li \l{Use Cases} \li \l{Use Cases}
\li \l{Concepts and Terms} \li \l{Concepts and Terms}
\li \l{Examples and Tutorials} \li \l{Examples}
\endlist \endlist
\li \b {\l{Wireframing}} \li \b {\l{Wireframing}}
\list \list

View File

@@ -34,6 +34,7 @@ import StudioControls as SC
import NewProjectDialog import NewProjectDialog
Item { Item {
id: rootDialog
width: DialogValues.dialogWidth width: DialogValues.dialogWidth
height: DialogValues.dialogHeight height: DialogValues.dialogHeight
@@ -47,38 +48,53 @@ Item {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
spacing: 0 spacing: 0
Item { width: parent.width; height: 20 } // spacer
Item { // Header Item Item { // Header Item
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: 218 implicitHeight: 164
Column { ColumnLayout {
anchors.fill: parent anchors.fill: parent
Item { width: parent.width; height: 74 } // spacer Item { width: parent.width; implicitHeight: 20 } // spacer
Row {
Text {
text: qsTr("Welcome to Qt Design Studio. Let's Create Something Wonderful!")
font.pixelSize: 32
width: parent.width width: parent.width
height: 47 height: DialogValues.dialogTitleTextHeight
lineHeight: 49 Layout.alignment: Qt.AlignHCenter
lineHeightMode: Text.FixedHeight Text {
color: DialogValues.textColor text: qsTr("Welcome to ")
horizontalAlignment: Text.AlignHCenter font.pixelSize: DialogValues.dialogTitlePixelSize
font.family: "Titillium Web"
height: DialogValues.dialogTitleTextHeight
lineHeight: DialogValues.dialogTitleLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
Text {
text: qsTr("Qt Design Studio")
font.pixelSize: DialogValues.dialogTitlePixelSize
font.family: "Titillium Web"
height: DialogValues.dialogTitleTextHeight
lineHeight: DialogValues.dialogTitleLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColorInteraction
}
} }
Item { width: parent.width; height: 11 } // spacer
Text { Text {
width: parent.width width: parent.width
text: qsTr("Get started by selecting from Presets or start from empty screen. You may also include your design file.") text: qsTr("Create new project by selecting a suitable Preset and then adjust details.")
color: DialogValues.textColor color: DialogValues.textColor
font.pixelSize: DialogValues.paneTitlePixelSize font.pixelSize: DialogValues.paneTitlePixelSize
lineHeight: DialogValues.paneTitleLineHeight lineHeight: DialogValues.paneTitleLineHeight
lineHeightMode: Text.FixedHeight lineHeightMode: Text.FixedHeight
horizontalAlignment: Text.AlignHCenter Layout.alignment: Qt.AlignHCenter
} }
}
Item { width: parent.width; Layout.fillHeight: true} // spacer
} // ColumnLayout
} // Header Item } // Header Item
Item { // Content Item Item { // Content Item
@@ -96,7 +112,7 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
Layout.minimumWidth: 379 // figured out this number visually Layout.minimumWidth: 379 // figured out this number visually
Layout.minimumHeight: 326 // figured out this number visually Layout.minimumHeight: 261 // figured out this number visually
Column { Column {
x: DialogValues.defaultPadding // left padding x: DialogValues.defaultPadding // left padding
@@ -106,19 +122,86 @@ Item {
Text { Text {
text: qsTr("Presets") text: qsTr("Presets")
width: parent.width width: parent.width
height: 47
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.pixelSize: DialogValues.paneTitlePixelSize font.pixelSize: DialogValues.paneTitlePixelSize
lineHeight: DialogValues.paneTitleLineHeight lineHeight: DialogValues.paneTitleLineHeight
lineHeightMode: Text.FixedHeight lineHeightMode: Text.FixedHeight
color: DialogValues.textColor color: DialogValues.textColor
verticalAlignment: Qt.AlignVCenter
} }
Rectangle { // TabBar
readonly property int animDur: 500
id: samTabRect
x: 10 // left padding
width: parent.width - 64 // right padding
height: DialogValues.projectViewHeaderHeight
color: DialogValues.lightPaneColor
Row {
id: tabBarRow
spacing: 20
property int currIndex: 0
Repeater {
model: categoryModel
Text {
text: name
font.weight: Font.DemiBold
font.pixelSize: DialogValues.viewHeaderPixelSize
verticalAlignment: Text.AlignVCenter
color: tabBarRow.currIndex === index ? DialogValues.textColorInteraction
: DialogValues.textColor
Behavior on color { ColorAnimation { duration: samTabRect.animDur } }
MouseArea {
anchors.fill: parent
onClicked: {
tabBarRow.currIndex = index
projectModel.setPage(index)
projectViewId.currentIndex = 0
projectViewId.currentIndexChanged()
strip.x = parent.x
strip.width = parent.width
}
}
} // Text
} // Repeater
} // tabBarRow
Rectangle {
id: strip
width: tabBarRow.children[0].width
height: 5
radius: 2
color: DialogValues.textColorInteraction
anchors.bottom: parent.bottom
Behavior on x { SmoothedAnimation { duration: samTabRect.animDur } }
Behavior on width { SmoothedAnimation { duration: strip.width === 0 ? 0 : samTabRect.animDur } } // do not animate initial width
}
} // Rectangle
NewProjectView { NewProjectView {
id: projectViewId id: projectViewId
x: 10 // left padding x: 10 // left padding
width: parent.width - 64 // right padding width: parent.width - 64 // right padding
height: DialogValues.projectViewHeight height: DialogValues.projectViewHeight
loader: projectDetailsLoader loader: projectDetailsLoader
Connections {
target: rootDialog
function onHeightChanged() {
if (rootDialog.height < 700) { // 700 = minimum height big dialog
projectViewId.height = DialogValues.projectViewHeight / 2
} else {
projectViewId.height = DialogValues.projectViewHeight
}
}
}
} }
Item { height: 5; width: parent.width } Item { height: 5; width: parent.width }
@@ -158,32 +241,46 @@ Item {
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
SC.AbstractButton { Item { // Dialog Button Box
implicitWidth: DialogValues.dialogButtonWidth width: DialogValues.stylesPaneWidth
width: DialogValues.dialogButtonWidth height: parent.height
visible: true
buttonIcon: qsTr("Cancel")
iconSize: DialogValues.defaultPixelSize
iconFont: StudioTheme.Constants.font
onClicked: { RowLayout {
dialogBox.reject(); width: DialogValues.stylesPaneWidth
} implicitWidth: DialogValues.stylesPaneWidth
} implicitHeight: parent.height
SC.AbstractButton { SC.AbstractButton {
implicitWidth: DialogValues.dialogButtonWidth implicitWidth: DialogValues.dialogButtonWidth
width: DialogValues.dialogButtonWidth width: DialogValues.dialogButtonWidth
visible: true visible: true
buttonIcon: qsTr("Create") buttonIcon: qsTr("Cancel")
iconSize: DialogValues.defaultPixelSize iconSize: DialogValues.defaultPixelSize
enabled: dialogBox.fieldsValid iconFont: StudioTheme.Constants.font
iconFont: StudioTheme.Constants.font
onClicked: {
dialogBox.reject();
}
}
Item { Layout.fillWidth: true }
SC.AbstractButton {
implicitWidth: DialogValues.dialogButtonWidth
width: DialogValues.dialogButtonWidth
visible: true
buttonIcon: qsTr("Create")
iconSize: DialogValues.defaultPixelSize
enabled: dialogBox.fieldsValid
iconFont: StudioTheme.Constants.font
onClicked: {
dialogBox.accept();
}
}
} // RowLayout
} // Dialog Button Box
onClicked: {
dialogBox.accept();
}
}
Item { implicitWidth: 35 - DialogValues.defaultPadding } Item { implicitWidth: 35 - DialogValues.defaultPadding }
} // RowLayout } // RowLayout
} // Footer } // Footer

View File

@@ -49,358 +49,385 @@ Item {
Item { Item {
x: DialogValues.detailsPanePadding // left padding x: DialogValues.detailsPanePadding // left padding
width: parent.width - DialogValues.detailsPanePadding * 2 // right padding width: parent.width - DialogValues.detailsPanePadding * 2 // right padding
height: parent.height
Column { Column {
anchors.fill: parent anchors.fill: parent
spacing: DialogValues.defaultPadding spacing: DialogValues.defaultPadding
Text { Text {
id: detailsHeading
text: qsTr("Details") text: qsTr("Details")
height: DialogValues.dialogTitleTextHeight
width: parent.width; width: parent.width;
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.pixelSize: DialogValues.paneTitlePixelSize font.pixelSize: DialogValues.paneTitlePixelSize
lineHeight: DialogValues.paneTitleLineHeight lineHeight: DialogValues.paneTitleLineHeight
lineHeightMode: Text.FixedHeight lineHeightMode: Text.FixedHeight
color: DialogValues.textColor color: DialogValues.textColor
verticalAlignment: Qt.AlignVCenter
} }
SC.TextField { Flickable {
id: projectNameTextField
actionIndicatorVisible: false
translationIndicatorVisible: false
text: dialogBox.projectName
width: parent.width width: parent.width
color: DialogValues.textColor height: parent.height - detailsHeading.height - DialogValues.defaultPadding
selectByMouse: true
onEditingFinished: { contentWidth: parent.width
text = text.charAt(0).toUpperCase() + text.slice(1) contentHeight: scrollContent.height
} boundsBehavior: Flickable.StopAtBounds
clip: true
font.pixelSize: DialogValues.paneTitlePixelSize ScrollBar.vertical: ScrollBar {
} implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
Binding { property bool scrollBarVisible: parent.childrenRect.height > parent.height
target: dialogBox
property: "projectName"
value: projectNameTextField.text
}
Item { width: parent.width; height: DialogValues.narrowSpacing(11) } minimumSize: orientation == Qt.Horizontal ? height / width : width / height
RowLayout { // Project location orientation: Qt.Vertical
width: parent.width policy: scrollBarVisible ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
x: parent.width - width
y: 0
height: parent.availableHeight
- (parent.bothVisible ? parent.horizontalThickness : 0)
padding: 0
SC.TextField { background: Rectangle {
Layout.fillWidth: true color: StudioTheme.Values.themeScrollBarTrack
id: projectLocationTextField
actionIndicatorVisible: false
translationIndicatorVisible: false
text: dialogBox.projectLocation
color: DialogValues.textColor
selectByMouse: true
font.pixelSize: DialogValues.defaultPixelSize
}
Binding {
target: dialogBox
property: "projectLocation"
value: projectLocationTextField.text
}
SC.AbstractButton {
implicitWidth: 30
iconSize: 20
visible: true
buttonIcon: "…"
iconFont: StudioTheme.Constants.font
onClicked: {
var newLocation = dialogBox.chooseProjectLocation()
if (newLocation)
projectLocationTextField.text = newLocation
} }
} // SC.AbstractButton
} // Project location RowLayout
Item { width: parent.width; height: DialogValues.narrowSpacing(7) } contentItem: Rectangle {
implicitWidth: StudioTheme.Values.scrollBarThickness
color: StudioTheme.Values.themeScrollBarHandle
}
} // ScrollBar
RowLayout { // StatusMessage Column {
width: parent.width id: scrollContent
spacing: 0 width: parent.width - DialogValues.detailsPanePadding
height: DialogValues.detailsScrollableContentHeight
spacing: DialogValues.defaultPadding
Image { SC.TextField {
id: statusIcon id: projectNameTextField
Layout.alignment: Qt.AlignTop actionIndicatorVisible: false
asynchronous: false translationIndicatorVisible: false
} text: dialogBox.projectName
width: parent.width
color: DialogValues.textColor
selectByMouse: true
Text { onEditingFinished: {
id: statusMessage text = text.charAt(0).toUpperCase() + text.slice(1)
text: dialogBox.statusMessage }
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
wrapMode: Text.Wrap
elide: Text.ElideRight
maximumLineCount: 3
Layout.fillWidth: true
states: [ font.pixelSize: DialogValues.defaultPixelSize
State { }
name: "warning"
when: dialogBox.statusType === "warning" Binding {
PropertyChanges { target: dialogBox
target: statusMessage property: "projectName"
color: DialogValues.textWarning value: projectNameTextField.text
}
Item { width: parent.width; height: DialogValues.narrowSpacing(11) }
RowLayout { // Project location
width: parent.width
SC.TextField {
Layout.fillWidth: true
id: projectLocationTextField
actionIndicatorVisible: false
translationIndicatorVisible: false
text: dialogBox.projectLocation
color: DialogValues.textColor
selectByMouse: true
font.pixelSize: DialogValues.defaultPixelSize
}
Binding {
target: dialogBox
property: "projectLocation"
value: projectLocationTextField.text
}
SC.AbstractButton {
implicitWidth: 30
iconSize: 20
visible: true
buttonIcon: "…"
iconFont: StudioTheme.Constants.font
onClicked: {
var newLocation = dialogBox.chooseProjectLocation()
if (newLocation)
projectLocationTextField.text = newLocation
} }
PropertyChanges { } // SC.AbstractButton
target: statusIcon } // Project location RowLayout
source: "image://newprojectdialog_library/status-warning"
}
},
State { Item { width: parent.width; height: DialogValues.narrowSpacing(7) }
name: "error"
when: dialogBox.statusType === "error" RowLayout { // StatusMessage
PropertyChanges { width: parent.width
target: statusMessage spacing: 0
color: DialogValues.textError
} Image {
PropertyChanges { id: statusIcon
target: statusIcon Layout.alignment: Qt.AlignTop
source: "image://newprojectdialog_library/status-error" asynchronous: false
}
Text {
id: statusMessage
text: dialogBox.statusMessage
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
wrapMode: Text.Wrap
elide: Text.ElideRight
maximumLineCount: 3
Layout.fillWidth: true
states: [
State {
name: "warning"
when: dialogBox.statusType === "warning"
PropertyChanges {
target: statusMessage
color: DialogValues.textWarning
}
PropertyChanges {
target: statusIcon
source: "image://newprojectdialog_library/status-warning"
}
},
State {
name: "error"
when: dialogBox.statusType === "error"
PropertyChanges {
target: statusMessage
color: DialogValues.textError
}
PropertyChanges {
target: statusIcon
source: "image://newprojectdialog_library/status-error"
}
}
]
} // Text
} // RowLayout
SC.CheckBox {
id: defaultLocationCheckbox
actionIndicatorVisible: false
text: qsTr("Use as default project location")
checked: false
font.pixelSize: DialogValues.defaultPixelSize
}
Binding {
target: dialogBox
property: "saveAsDefaultLocation"
value: defaultLocationCheckbox.checked
}
Rectangle { width: parent.width; height: 1; color: DialogValues.dividerlineColor }
SC.ComboBox { // Screen Size ComboBox
id: screenSizeComboBox
actionIndicatorVisible: false
currentIndex: -1
model: screenSizeModel
textRole: "display"
width: parent.width
font.pixelSize: DialogValues.defaultPixelSize
onActivated: (index) => {
dialogBox.setScreenSizeIndex(index);
var size = screenSizeModel.screenSizes(index);
widthField.realValue = size.width;
heightField.realValue = size.height;
}
Connections {
target: screenSizeModel
function onModelReset() {
var newIndex = screenSizeComboBox.currentIndex > -1
? screenSizeComboBox.currentIndex
: dialogBox.screenSizeIndex()
screenSizeComboBox.currentIndex = newIndex
screenSizeComboBox.activated(newIndex)
} }
} }
] } // Screen Size ComboBox
} // Text
} // RowLayout
SC.CheckBox { GridLayout { // orientation + width + height
id: defaultLocationCheckbox
actionIndicatorVisible: false
text: qsTr("Use as default project location")
checked: false
font.pixelSize: DialogValues.defaultPixelSize
}
Binding {
target: dialogBox
property: "saveAsDefaultLocation"
value: defaultLocationCheckbox.checked
}
Rectangle { width: parent.width; height: 1; color: DialogValues.dividerlineColor }
SC.ComboBox { // Screen Size ComboBox
id: screenSizeComboBox
actionIndicatorVisible: false
currentIndex: -1
model: screenSizeModel
textRole: "display"
width: parent.width
font.pixelSize: DialogValues.defaultPixelSize
onActivated: (index) => {
dialogBox.setScreenSizeIndex(index);
var size = screenSizeModel.screenSizes(index);
widthField.realValue = size.width;
heightField.realValue = size.height;
}
Connections {
target: screenSizeModel
function onModelReset() {
var newIndex = screenSizeComboBox.currentIndex > -1
? screenSizeComboBox.currentIndex
: dialogBox.screenSizeIndex()
screenSizeComboBox.currentIndex = newIndex
screenSizeComboBox.activated(newIndex)
}
}
} // Screen Size ComboBox
GridLayout { // orientation + width + height
width: parent.width
height: 85
columns: 4
rows: 2
columnSpacing: 10
rowSpacing: 10
// header items
Text {
text: qsTr("Width")
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
Text {
text: qsTr("Height")
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
Item { Layout.fillWidth: true }
Text {
text: qsTr("Orientation")
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
// content items
SC.RealSpinBox {
id: widthField
actionIndicatorVisible: false
implicitWidth: 70
labelColor: DialogValues.textColor
realFrom: 100
realTo: 100000
realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize
onRealValueChanged: {
var height = heightField.realValue
var width = realValue
if (width >= height)
orientationButton.setHorizontal()
else
orientationButton.setVertical()
}
} // Width Text Field
Binding {
target: dialogBox
property: "customWidth"
value: widthField.realValue
}
SC.RealSpinBox {
id: heightField
actionIndicatorVisible: false
implicitWidth: 70
labelColor: DialogValues.textColor
realFrom: 100
realTo: 100000
realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize
onRealValueChanged: {
var height = realValue
var width = widthField.realValue
if (width >= height)
orientationButton.setHorizontal()
else
orientationButton.setVertical()
}
} // Height Text Field
Binding {
target: dialogBox
property: "customHeight"
value: heightField.realValue
}
Item { Layout.fillWidth: true }
Button {
id: orientationButton
implicitWidth: 100
implicitHeight: 50
checked: false
hoverEnabled: false
background: Rectangle {
width: parent.width width: parent.width
height: parent.height height: 85
color: "transparent"
Row { columns: 4
Item { rows: 2
width: orientationButton.width / 2
height: orientationButton.height columnSpacing: 10
Rectangle { rowSpacing: 10
id: horizontalBar
color: "white" // header items
width: parent.width Text {
height: orientationButton.height / 2 text: qsTr("Width")
anchors.verticalCenter: parent.verticalCenter font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
Text {
text: qsTr("Height")
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
Item { Layout.fillWidth: true }
Text {
text: qsTr("Orientation")
font.pixelSize: DialogValues.defaultPixelSize
lineHeight: DialogValues.defaultLineHeight
lineHeightMode: Text.FixedHeight
color: DialogValues.textColor
}
// content items
SC.RealSpinBox {
id: widthField
actionIndicatorVisible: false
implicitWidth: 70
labelColor: DialogValues.textColor
realFrom: 100
realTo: 100000
realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize
onRealValueChanged: {
var height = heightField.realValue
var width = realValue
if (width >= height)
orientationButton.setHorizontal()
else
orientationButton.setVertical()
}
} // Width Text Field
Binding {
target: dialogBox
property: "customWidth"
value: widthField.realValue
}
SC.RealSpinBox {
id: heightField
actionIndicatorVisible: false
implicitWidth: 70
labelColor: DialogValues.textColor
realFrom: 100
realTo: 100000
realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize
onRealValueChanged: {
var height = realValue
var width = widthField.realValue
if (width >= height)
orientationButton.setHorizontal()
else
orientationButton.setVertical()
}
} // Height Text Field
Binding {
target: dialogBox
property: "customHeight"
value: heightField.realValue
}
Item { Layout.fillWidth: true }
Button {
id: orientationButton
implicitWidth: 100
implicitHeight: 50
checked: false
hoverEnabled: false
background: Rectangle {
width: parent.width
height: parent.height
color: "transparent"
Row {
Item {
width: orientationButton.width / 2
height: orientationButton.height
Rectangle {
id: horizontalBar
color: "white"
width: parent.width
height: orientationButton.height / 2
anchors.verticalCenter: parent.verticalCenter
}
}
Item {
width: orientationButton.width / 4
height: orientationButton.height
}
Rectangle {
id: verticalBar
width: orientationButton.width / 4
height: orientationButton.height
color: "white"
}
} }
} }
Item { onClicked: {
width: orientationButton.width / 4 if (widthField.realValue && heightField.realValue) {
height: orientationButton.height [widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue];
checked = !checked
}
} }
Rectangle { function setHorizontal() {
id: verticalBar checked = false
width: orientationButton.width / 4 horizontalBar.color = DialogValues.textColorInteraction
height: orientationButton.height verticalBar.color = "white"
color: "white"
} }
}
}
onClicked: { function setVertical() {
if (widthField.realValue && heightField.realValue) { checked = true
[widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue]; horizontalBar.color = "white"
checked = !checked verticalBar.color = DialogValues.textColorInteraction
} }
} } // Orientation button
function setHorizontal() { } // GridLayout: orientation + width + height
checked = false
horizontalBar.color = DialogValues.textColorInteraction
verticalBar.color = "white"
}
function setVertical() { Rectangle { width: parent.width; height: 1; color: DialogValues.dividerlineColor }
checked = true
horizontalBar.color = "white"
verticalBar.color = DialogValues.textColorInteraction
}
} // Orientation button
} // GridLayout: orientation + width + height
Rectangle { width: parent.width; height: 1; color: DialogValues.dividerlineColor }
SC.Section {
width: parent.width
caption: qsTr("Advanced")
captionPixelSize: DialogValues.defaultPixelSize
captionColor: DialogValues.darkPaneColor
captionTextColor: DialogValues.textColor
leftPadding: 0
expanded: true
visible: dialogBox.haveVirtualKeyboard || dialogBox.haveTargetQtVersion
Column {
spacing: DialogValues.defaultPadding
width: parent.width
/* We need a spacer of -10 in order to have actual 18px spacing between
* section bottom and the checkbox. Otherwise, with Column spacing set to
* 18, without a spacer, the default space to the first item would be 10,
* for some reason. */
Item { width: parent.width; height: -10 }
SC.CheckBox { SC.CheckBox {
id: useQtVirtualKeyboard id: useQtVirtualKeyboard
@@ -440,22 +467,19 @@ Item {
} }
} }
width: parent.width
onActivated: (index) => { onActivated: (index) => {
dialogBox.setTargetQtVersion(index) dialogBox.setTargetQtVersion(index)
} }
} // Target Qt Version ComboBox } // Target Qt Version ComboBox
} // RowLayout } // RowLayout
} // Column
} // SC.Section
Binding { Binding {
target: dialogBox target: dialogBox
property: "useVirtualKeyboard" property: "useVirtualKeyboard"
value: useQtVirtualKeyboard.checked value: useQtVirtualKeyboard.checked
} }
} // ScrollContent Column
} // ScrollView
} // Column } // Column
} // Item } // Item

View File

@@ -30,12 +30,16 @@ import StudioTheme as StudioTheme
QtObject { QtObject {
readonly property int dialogWidth: 1522 readonly property int dialogWidth: 1522
readonly property int dialogHeight: 994 readonly property int dialogHeight: 940
readonly property int projectViewMinimumWidth: 600 readonly property int projectViewMinimumWidth: 600
readonly property int projectViewMinimumHeight: projectViewHeight readonly property int projectViewMinimumHeight: projectViewHeight
readonly property int dialogContentHeight: projectViewHeight + 300 // i.e. dialog without header and footer readonly property int dialogContentHeight: projectViewHeight + 300 // i.e. dialog without header and footer
readonly property int loadedPanesWidth: detailsPaneWidth + stylesPaneWidth readonly property int loadedPanesWidth: detailsPaneWidth + stylesPaneWidth
readonly property int detailsPaneWidth: 330 + detailsPanePadding * 2 readonly property int detailsPaneWidth: 330 + detailsPanePadding * 2// + 10 // 50
readonly property int dialogTitleTextHeight: 47
/* detailsScrollableContentHeight - the full height that may need to be scrolled to be fully
visible, if the dialog box is too small. */
readonly property int detailsScrollableContentHeight: 428
readonly property int stylesPaneWidth: styleImageWidth + stylesPanePadding * 2 + styleImageBorderWidth * 2 // i.e. 240px readonly property int stylesPaneWidth: styleImageWidth + stylesPanePadding * 2 + styleImageBorderWidth * 2 // i.e. 240px
readonly property int detailsPanePadding: 18 readonly property int detailsPanePadding: 18
readonly property int stylesPanePadding: 18 readonly property int stylesPanePadding: 18
@@ -44,9 +48,9 @@ QtObject {
readonly property int styleImageWidth: 200 readonly property int styleImageWidth: 200
readonly property int styleImageBorderWidth: 2 readonly property int styleImageBorderWidth: 2
readonly property int footerHeight: 73 readonly property int footerHeight: 73
readonly property int projectItemWidth: 144 readonly property int projectItemWidth: 90
readonly property int projectItemHeight: 144 readonly property int projectItemHeight: 144
readonly property int projectViewHeight: projectItemHeight * 2 + projectViewHeaderHeight readonly property int projectViewHeight: projectItemHeight * 2
readonly property int projectViewHeaderHeight: 38 readonly property int projectViewHeaderHeight: 38
readonly property int dialogButtonWidth: 100 readonly property int dialogButtonWidth: 100
@@ -69,6 +73,8 @@ QtObject {
readonly property real viewHeaderLineHeight: 24 readonly property real viewHeaderLineHeight: 24
readonly property real paneTitlePixelSize: 18 readonly property real paneTitlePixelSize: 18
readonly property real paneTitleLineHeight: 27 readonly property real paneTitleLineHeight: 27
readonly property int dialogTitlePixelSize: 32
readonly property int dialogTitleLineHeight: 49
// for a spacer item // for a spacer item
function narrowSpacing(value, layoutSpacing = DialogValues.defaultPadding) { function narrowSpacing(value, layoutSpacing = DialogValues.defaultPadding) {

View File

@@ -35,61 +35,9 @@ GridView {
required property Item loader required property Item loader
readonly property int animDur: 500
header: Rectangle {
width: parent.width
height: DialogValues.projectViewHeaderHeight
color: DialogValues.lightPaneColor
Row {
id: row
spacing: 20
property int currIndex: 0
Repeater {
model: categoryModel
Text {
text: name
font.weight: Font.DemiBold
font.pixelSize: DialogValues.viewHeaderPixelSize
verticalAlignment: Text.AlignVCenter
color: row.currIndex === index ? DialogValues.textColorInteraction
: DialogValues.textColor
Behavior on color { ColorAnimation { duration: animDur } }
MouseArea {
anchors.fill: parent
onClicked: {
row.currIndex = index
projectModel.setPage(index)
projectView.currentIndex = 0
projectView.currentIndexChanged()
strip.x = parent.x
strip.width = parent.width
}
}
} // Text
} // Repeater
} // Row
Rectangle {
id: strip
width: row.children[0].width
height: 5
radius: 2
color: DialogValues.textColorInteraction
anchors.bottom: parent.bottom
Behavior on x { SmoothedAnimation { duration: animDur } }
Behavior on width { SmoothedAnimation { duration: strip.width === 0 ? 0 : animDur } } // do not animate initial width
}
} // Rectangle
cellWidth: DialogValues.projectItemWidth cellWidth: DialogValues.projectItemWidth
cellHeight: DialogValues.projectItemHeight cellHeight: DialogValues.projectItemHeight
clip: true
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds

View File

@@ -65,12 +65,13 @@ Item {
Text { Text {
id: styleTitleText id: styleTitleText
text: qsTr("Style") text: qsTr("Style")
width: parent.width; Layout.minimumHeight: DialogValues.dialogTitleTextHeight
font.weight: Font.DemiBold font.weight: Font.DemiBold
font.pixelSize: DialogValues.paneTitlePixelSize font.pixelSize: DialogValues.paneTitlePixelSize
lineHeight: DialogValues.paneTitleLineHeight lineHeight: DialogValues.paneTitleLineHeight
lineHeightMode: Text.FixedHeight lineHeightMode: Text.FixedHeight
color: DialogValues.textColor color: DialogValues.textColor
verticalAlignment: Qt.AlignVCenter
function refresh() { function refresh() {
text = qsTr("Style") + " (" + styleModel.rowCount() + ")" text = qsTr("Style") + " (" + styleModel.rowCount() + ")"

View File

@@ -203,13 +203,15 @@ T.ComboBox {
| T.Popup.CloseOnReleaseOutsideParent | T.Popup.CloseOnReleaseOutsideParent
contentItem: ListView { contentItem: ListView {
id: listView
clip: true clip: true
implicitHeight: contentHeight implicitHeight: listView.contentHeight
model: myComboBox.popup.visible ? myComboBox.delegateModel : null model: myComboBox.popup.visible ? myComboBox.delegateModel : null
currentIndex: myComboBox.highlightedIndex currentIndex: myComboBox.highlightedIndex
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
id: comboBoxPopupScrollBar id: comboBoxPopupScrollBar
visible: listView.height < listView.contentHeight
} }
} }

View File

@@ -40,12 +40,15 @@ static const QHash<QString, QString> &envVarToCMakeVarMapping()
{"STM32Cube_FW_F4_SDK_PATH","QUL_BOARD_SDK_DIR"}, {"STM32Cube_FW_F4_SDK_PATH","QUL_BOARD_SDK_DIR"},
{"STM32Cube_FW_L4_SDK_PATH","QUL_BOARD_SDK_DIR"}, {"STM32Cube_FW_L4_SDK_PATH","QUL_BOARD_SDK_DIR"},
{"STM32Cube_FW_H7_SDK_PATH","QUL_BOARD_SDK_DIR"}, {"STM32Cube_FW_H7_SDK_PATH","QUL_BOARD_SDK_DIR"},
{"RGL_DIR", "QUL_BOARD_SDK_DIR"},
{"TVII_GRAPHICS_DRIVER_DIR", "QUL_BOARD_SDK_DIR"},
{"EK_RA6M3G_FSP_PATH", "QUL_BOARD_SDK_DIR"},
{"ARMGCC_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, {"ARMGCC_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
{"IAR_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, {"IAR_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
{"GHS_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, {"GHS_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
{"GHS_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, {"GHS_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"},
{"EVK_MIMXRT1170_FREERTOS_PATH","FREERTOS_DIR"}, {"EVK_MIMXRT1170_FREERTOS_PATH","FREERTOS_DIR"},
{"EVK_MIMXRT1170_FREERTOS_PATH","FREERTOS_DIR"}, {"IMXRT1050_FREERTOS_DIR","FREERTOS_DIR"},
{"IMXRT1064_FREERTOS_DIR","FREERTOS_DIR"}, {"IMXRT1064_FREERTOS_DIR","FREERTOS_DIR"},
{"IMXRT595_FREERTOS_DIR","FREERTOS_DIR"}, {"IMXRT595_FREERTOS_DIR","FREERTOS_DIR"},
{"STM32F7_FREERTOS_DIR", "FREERTOS_DIR"}, {"STM32F7_FREERTOS_DIR", "FREERTOS_DIR"},
@@ -53,10 +56,8 @@ static const QHash<QString, QString> &envVarToCMakeVarMapping()
{"RenesasFlashProgrammer_PATH", "RENESAS_FLASH_PROGRAMMER_PATH"}, {"RenesasFlashProgrammer_PATH", "RENESAS_FLASH_PROGRAMMER_PATH"},
{"MCUXpressoIDE_PATH", "MCUXPRESSO_IDE_PATH"}, {"MCUXpressoIDE_PATH", "MCUXPRESSO_IDE_PATH"},
{"JLINK_PATH", "JLINK_PATH"}, {"JLINK_PATH", "JLINK_PATH"},
{"TVII_GRAPHICS_DRIVER_DIR", "TVII_GRAPHICS_DRIVER_DIR"},
{"CYPRESS_AUTO_FLASH_UTILITY_DIR", "CYPRESS_AUTO_FLASH_UTILITY_DIR"}, {"CYPRESS_AUTO_FLASH_UTILITY_DIR", "CYPRESS_AUTO_FLASH_UTILITY_DIR"},
{"EK_RA6M3G_E2_PROJECT_PATH", "EK_RA6M3G_E2_PROJECT_PATH"}, {"EK_RA6M3G_E2_PROJECT_PATH", "EK_RA6M3G_E2_PROJECT_PATH"},
{"EK_RA6M3G_FSP_PATH", "EK_RA6M3G_FSP_PATH"},
}; };
return mapping; return mapping;
} }

View File

@@ -497,8 +497,27 @@ QVariant McuToolChainPackage::debuggerId() const
{ {
using namespace Debugger; using namespace Debugger;
QString sub = QString::fromLatin1(m_type == TypeArmGcc ? "bin/arm-none-eabi-gdb-py" QString sub, displayName;
: m_type == TypeIAR ? "../common/bin/CSpyBat" : "bar/foo-keil-gdb"); DebuggerEngineType engineType;
switch (m_type) {
case TypeArmGcc: {
sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py");
displayName = McuPackage::tr("Arm GDB at %1");
engineType = Debugger::GdbEngineType;
break; }
case TypeIAR: {
sub = QString::fromLatin1("../common/bin/CSpyBat");
displayName = QLatin1String("CSpy");
engineType = Debugger::NoEngineType; // support for IAR missing
break; }
case TypeKEIL: {
sub = QString::fromLatin1("UV4/UV4");
displayName = QLatin1String("KEIL uVision Debugger");
engineType = Debugger::UvscEngineType;
break; }
default: return QVariant();
}
const FilePath command = path().pathAppended(sub).withExecutableSuffix(); const FilePath command = path().pathAppended(sub).withExecutableSuffix();
const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command); const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command);
@@ -506,11 +525,8 @@ QVariant McuToolChainPackage::debuggerId() const
if (!debugger) { if (!debugger) {
DebuggerItem newDebugger; DebuggerItem newDebugger;
newDebugger.setCommand(command); newDebugger.setCommand(command);
const QString displayName = m_type == TypeArmGcc
? McuPackage::tr("Arm GDB at %1")
: m_type == TypeIAR ? QLatin1String("CSpy")
: QLatin1String("/bar/foo-keil-gdb");
newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput())); newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput()));
newDebugger.setEngineType(engineType);
debuggerId = DebuggerItemManager::registerDebugger(newDebugger); debuggerId = DebuggerItemManager::registerDebugger(newDebugger);
} else { } else {
debuggerId = debugger->id(); debuggerId = debugger->id();
@@ -743,7 +759,9 @@ static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage)
|| tcPackage->type() == McuToolChainPackage::TypeIAR) || tcPackage->type() == McuToolChainPackage::TypeIAR)
return; return;
Debugger::DebuggerKitAspect::setDebugger(k, tcPackage->debuggerId()); const QVariant debuggerId = tcPackage->debuggerId();
if (debuggerId.isValid())
Debugger::DebuggerKitAspect::setDebugger(k, debuggerId);
} }
static void setKitDevice(Kit *k, const McuTarget* mcuTarget) static void setKitDevice(Kit *k, const McuTarget* mcuTarget)

View File

@@ -63,13 +63,14 @@ enum ProjectDirectoryError {
NoError = 0, NoError = 0,
MissingContentDir = 1<<1, MissingContentDir = 1<<1,
MissingImportDir = 1<<2, MissingImportDir = 1<<2,
MissingCppDir = 1<<3, MissingAssetImportDir = 1<<3,
MissingMainCMake = 1<<4, MissingCppDir = 1<<4,
MissingMainQml = 1<<5, MissingMainCMake = 1<<5,
MissingAppMainQml = 1<<6, MissingMainQml = 1<<6,
MissingQmlModules = 1<<7, MissingAppMainQml = 1<<7,
MissingMainCpp = 1<<8, MissingQmlModules = 1<<8,
MissingMainCppHeader = 1<<9 MissingMainCpp = 1<<9,
MissingMainCppHeader = 1<<10
}; };
QVector<GeneratableFile> queuedFiles; QVector<GeneratableFile> queuedFiles;
@@ -131,6 +132,8 @@ int isProjectCorrectlyFormed(const FilePath &rootDir)
if (!rootDir.pathAppended(DIRNAME_IMPORT).exists()) if (!rootDir.pathAppended(DIRNAME_IMPORT).exists())
errors |= MissingImportDir; errors |= MissingImportDir;
if (!rootDir.pathAppended(DIRNAME_ASSET).exists())
errors |= MissingAssetImportDir;
if (!rootDir.pathAppended(DIRNAME_CPP).exists()) if (!rootDir.pathAppended(DIRNAME_CPP).exists())
errors |= MissingCppDir; errors |= MissingCppDir;
@@ -159,7 +162,7 @@ void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles)
const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1"); "The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1");
const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"The project is not properly structured for automatically generating CMake files.\n\nThe following files will be created:\n\n%1"); "The project is not properly structured for automatically generating CMake files.\n\nThe following files or directories are missing and may be created:\n\n%1");
const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", const QString WARNING_TITLE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
"Cannot Generate CMake Files"); "Cannot Generate CMake Files");
const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", const QString WARNING_TITLE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake",
@@ -182,6 +185,8 @@ void showProjectDirErrorDialog(int error)
if (error & MissingImportDir) if (error & MissingImportDir)
fatalList.append(QString(DIRNAME_IMPORT) + "\n"); fatalList.append(QString(DIRNAME_IMPORT) + "\n");
if (error & MissingAssetImportDir)
nonFatalList.append(QString(DIRNAME_ASSET) + "\n");
if (error & MissingMainCMake) if (error & MissingMainCMake)
nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n"); nonFatalList.append(QString(FILENAME_CMAKELISTS) + "\n");
if (error & MissingQmlModules) if (error & MissingQmlModules)
@@ -290,16 +295,21 @@ bool generateCmakes(const FilePath &rootDir)
{ {
moduleNames.clear(); moduleNames.clear();
FilePath contentDir = rootDir.pathAppended("content"); FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT);
FilePath importDir = rootDir.pathAppended("imports"); FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT);
FilePath assetDir = rootDir.pathAppended(DIRNAME_ASSET);
generateModuleCmake(contentDir); generateModuleCmake(contentDir);
generateImportCmake(importDir); generateImportCmake(importDir);
generateImportCmake(assetDir);
generateMainCmake(rootDir); generateMainCmake(rootDir);
return true; return true;
} }
const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
void generateMainCmake(const FilePath &rootDir) void generateMainCmake(const FilePath &rootDir)
{ {
//TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all. //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
@@ -309,27 +319,47 @@ void generateMainCmake(const FilePath &rootDir)
QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName); QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName);
queueCmakeFile(rootDir, cmakeFileContent); queueCmakeFile(rootDir, cmakeFileContent);
QString subdirIncludes;
subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT));
subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT));
if (rootDir.pathAppended(DIRNAME_ASSET).exists())
subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSET));
QString modulesAsPlugins; QString modulesAsPlugins;
for (const QString &moduleName : moduleNames) for (const QString &moduleName : moduleNames)
modulesAsPlugins.append(" " + moduleName + "plugin\n"); modulesAsPlugins.append(" " + moduleName + "plugin\n");
QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH).arg(appName).arg(modulesAsPlugins); QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH)
.arg(appName)
.arg(subdirIncludes)
.arg(modulesAsPlugins);
GenerateCmake::queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent); GenerateCmake::queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent);
} }
const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n"; void generateImportCmake(const FilePath &dir, const QString &modulePrefix)
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
void generateImportCmake(const FilePath &dir)
{ {
if (!dir.exists())
return;
QString fileContent; QString fileContent;
fileContent.append(DO_NOT_EDIT_FILE_COMMENT); fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
FilePaths subDirs = dir.dirEntries(DIRS_ONLY); FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirs) { for (FilePath &subDir : subDirs) {
if (isDirBlacklisted(subDir))
continue;
if (getDirectoryTreeQmls(subDir).isEmpty() && getDirectoryTreeResources(subDir).isEmpty())
continue;
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName())); fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
generateModuleCmake(subDir); QString prefix = modulePrefix.isEmpty() ?
modulePrefix % subDir.fileName() :
QString(modulePrefix + '.') + subDir.fileName();
if (getDirectoryQmls(subDir).isEmpty()) {
generateImportCmake(subDir, prefix);
} else {
generateModuleCmake(subDir, prefix);
}
} }
queueCmakeFile(dir, fileContent); queueCmakeFile(dir, fileContent);
@@ -339,13 +369,12 @@ const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n"; const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl"; const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
void generateModuleCmake(const FilePath &dir) void generateModuleCmake(const FilePath &dir, const QString &uri)
{ {
QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH); QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
const QStringList qmldirFilesOnly(FILENAME_QMLDIR);
QString singletonContent; QString singletonContent;
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY); FilePaths qmldirFileList = dir.dirEntries(QStringList(FILENAME_QMLDIR), FILES_ONLY);
if (!qmldirFileList.isEmpty()) { if (!qmldirFileList.isEmpty()) {
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first()); QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
for (QString &singleton : singletons) { for (QString &singleton : singletons) {
@@ -371,12 +400,14 @@ void generateModuleCmake(const FilePath &dir)
moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles)); moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
} }
QString moduleName = dir.fileName(); QString moduleUri = uri.isEmpty() ?
dir.fileName() :
uri;
QString moduleName = QString(moduleUri).remove('.');
moduleNames.append(moduleName); moduleNames.append(moduleName);
QString fileContent; QString fileContent;
fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent)); fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent));
queueCmakeFile(dir, fileContent); queueCmakeFile(dir, fileContent);
} }
@@ -403,6 +434,22 @@ QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
return singletons; return singletons;
} }
FilePaths getDirectoryQmls(const FilePath &dir)
{
const QStringList qmlFilesOnly("*.qml");
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
FilePaths allFiles = dir.dirEntries(qmlFilesOnly, FILES_ONLY);
FilePaths moduleFiles;
for (FilePath &file : allFiles) {
if (!isFileBlacklisted(file.fileName()) &&
project->isKnownFile(file)) {
moduleFiles.append(file);
}
}
return moduleFiles;
}
QStringList getDirectoryTreeQmls(const FilePath &dir) QStringList getDirectoryTreeQmls(const FilePath &dir)
{ {
const QStringList qmlFilesOnly("*.qml"); const QStringList qmlFilesOnly("*.qml");
@@ -419,6 +466,8 @@ QStringList getDirectoryTreeQmls(const FilePath &dir)
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY); FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirsList) { for (FilePath &subDir : subDirsList) {
if (isDirBlacklisted(subDir))
continue;
QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir); QStringList subDirQmlFiles = getDirectoryTreeQmls(subDir);
for (QString &qmlFile : subDirQmlFiles) { for (QString &qmlFile : subDirQmlFiles) {
qmlFileList.append(subDir.fileName().append('/').append(qmlFile)); qmlFileList.append(subDir.fileName().append('/').append(qmlFile));
@@ -444,6 +493,8 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
FilePaths subDirsList = dir.dirEntries(DIRS_ONLY); FilePaths subDirsList = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirsList) { for (FilePath &subDir : subDirsList) {
if (isDirBlacklisted(subDir))
continue;
QStringList subDirResources = getDirectoryTreeResources(subDir); QStringList subDirResources = getDirectoryTreeResources(subDir);
for (QString &resource : subDirResources) { for (QString &resource : subDirResources) {
resourceFileList.append(subDir.fileName().append('/').append(resource)); resourceFileList.append(subDir.fileName().append('/').append(resource));
@@ -466,6 +517,11 @@ bool isFileBlacklisted(const QString &fileName)
!fileName.compare(FILENAME_CMAKELISTS)); !fileName.compare(FILENAME_CMAKELISTS));
} }
bool isDirBlacklisted(const FilePath &dir)
{
return (!dir.fileName().compare(DIRNAME_DESIGNER));
}
} }
namespace GenerateEntryPoints { namespace GenerateEntryPoints {

View File

@@ -54,13 +54,15 @@ QString readTemplate(const QString &templatePath);
namespace GenerateCmakeLists { namespace GenerateCmakeLists {
bool generateCmakes(const Utils::FilePath &rootDir); bool generateCmakes(const Utils::FilePath &rootDir);
void generateMainCmake(const Utils::FilePath &rootDir); void generateMainCmake(const Utils::FilePath &rootDir);
void generateImportCmake(const Utils::FilePath &dir); void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString());
void generateModuleCmake(const Utils::FilePath &dir); void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString());
Utils::FilePaths getDirectoryQmls(const Utils::FilePath &dir);
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath); QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir); QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
QStringList getDirectoryTreeResources(const Utils::FilePath &dir); QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
void queueCmakeFile(const Utils::FilePath &filePath, const QString &content); void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
bool isFileBlacklisted(const QString &fileName); bool isFileBlacklisted(const QString &fileName);
bool isDirBlacklisted(const Utils::FilePath &dir);
} }
namespace GenerateEntryPoints { namespace GenerateEntryPoints {
bool generateEntryPointFiles(const Utils::FilePath &dir); bool generateEntryPointFiles(const Utils::FilePath &dir);

View File

@@ -34,7 +34,9 @@ namespace Constants {
const char DIRNAME_CONTENT[] = "content"; const char DIRNAME_CONTENT[] = "content";
const char DIRNAME_IMPORT[] = "imports"; const char DIRNAME_IMPORT[] = "imports";
const char DIRNAME_ASSET[] = "asset_imports";
const char DIRNAME_CPP[] = "src"; const char DIRNAME_CPP[] = "src";
const char DIRNAME_DESIGNER[] = "designer";
const char FILENAME_CMAKELISTS[] = "CMakeLists.txt"; const char FILENAME_CMAKELISTS[] = "CMakeLists.txt";
const char FILENAME_APPMAINQML[] = "App.qml"; const char FILENAME_APPMAINQML[] = "App.qml";

View File

@@ -5,7 +5,7 @@
qt_add_library(%2 STATIC) qt_add_library(%2 STATIC)
qt6_add_qml_module(%2 qt6_add_qml_module(%2
URI "%2" URI "%3"
VERSION 1.0 VERSION 1.0
%3 %4
) )

View File

@@ -8,9 +8,8 @@ qt6_add_qml_module(%1
QML_FILES main.qml QML_FILES main.qml
) )
add_subdirectory(content) %2
add_subdirectory(imports)
target_link_libraries(%1 PRIVATE target_link_libraries(%1 PRIVATE
%2 %3
) )

View File

@@ -84,6 +84,26 @@ QPixmap NewProjectDialogImageProvider::requestStylePixmap(const QString &id, QSi
return pixmap; return pixmap;
} }
QPixmap NewProjectDialogImageProvider::requestDefaultPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
QString realPath = Core::ICore::resourcePath("qmldesigner/newprojectdialog/image/" + id).toString();
QPixmap pixmap{realPath};
if (size) {
size->setWidth(pixmap.width());
size->setHeight(pixmap.height());
}
if (pixmap.isNull())
return QPixmap{};
if (requestedSize.isValid())
return pixmap.scaled(requestedSize);
return pixmap;
}
QPixmap NewProjectDialogImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) QPixmap NewProjectDialogImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{ {
if (id.startsWith("style-")) if (id.startsWith("style-"))
@@ -92,7 +112,7 @@ QPixmap NewProjectDialogImageProvider::requestPixmap(const QString &id, QSize *s
if (id.startsWith("status-")) if (id.startsWith("status-"))
return requestStatusPixmap(id, size, requestedSize); return requestStatusPixmap(id, size, requestedSize);
return QPixmap{}; return requestDefaultPixmap(id, size, requestedSize);
} }
} // namespace Internal } // namespace Internal

View File

@@ -41,6 +41,7 @@ public:
private: private:
QPixmap requestStatusPixmap(const QString &id, QSize *size, const QSize &requestedSize); QPixmap requestStatusPixmap(const QString &id, QSize *size, const QSize &requestedSize);
QPixmap requestStylePixmap(const QString &id, QSize *size, const QSize &requestedSize); QPixmap requestStylePixmap(const QString &id, QSize *size, const QSize &requestedSize);
QPixmap requestDefaultPixmap(const QString &id, QSize *size, const QSize &requestedSize);
static QPixmap invalidStyleIcon(); static QPixmap invalidStyleIcon();
}; };

View File

@@ -23,9 +23,6 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QQmlContext>
#include <QMessageBox>
#include "qdsnewdialog.h" #include "qdsnewdialog.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -37,6 +34,10 @@
#include "wizardfactories.h" #include "wizardfactories.h"
#include "newprojectdialogimageprovider.h" #include "newprojectdialogimageprovider.h"
#include <QMessageBox>
#include <QQmlContext>
#include <QScreen>
using namespace StudioWelcome; using namespace StudioWelcome;
namespace { namespace {
@@ -93,7 +94,11 @@ QdsNewDialog::QdsNewDialog(QWidget *parent)
m_dialog->setWindowModality(Qt::ApplicationModal); m_dialog->setWindowModality(Qt::ApplicationModal);
m_dialog->setWindowFlags(Qt::Dialog); m_dialog->setWindowFlags(Qt::Dialog);
m_dialog->setAttribute(Qt::WA_DeleteOnClose); m_dialog->setAttribute(Qt::WA_DeleteOnClose);
m_dialog->setMinimumSize(1155, 804); m_dialog->setMinimumSize(1110, 554);
QSize screenSize = m_dialog->screen()->geometry().size();
if (screenSize.height() < 1080)
m_dialog->resize(parent->size());
QObject::connect(&m_wizard, &WizardHandler::deletingWizard, this, &QdsNewDialog::onDeletingWizard); QObject::connect(&m_wizard, &WizardHandler::deletingWizard, this, &QdsNewDialog::onDeletingWizard);
QObject::connect(&m_wizard, &WizardHandler::wizardCreated, this, &QdsNewDialog::onWizardCreated); QObject::connect(&m_wizard, &WizardHandler::wizardCreated, this, &QdsNewDialog::onWizardCreated);

View File

@@ -342,6 +342,7 @@ public:
void checkNext() void checkNext()
{ {
QTC_ASSERT(m_currentHandlerIndex >= 0, return);
QTC_ASSERT(m_currentHandlerIndex < m_handlers.size(), return); QTC_ASSERT(m_currentHandlerIndex < m_handlers.size(), return);
BaseHoverHandler *currentHandler = m_handlers[m_currentHandlerIndex]; BaseHoverHandler *currentHandler = m_handlers[m_currentHandlerIndex];
@@ -352,6 +353,7 @@ public:
void onHandlerFinished(int documentRevision, int position, int priority) void onHandlerFinished(int documentRevision, int position, int priority)
{ {
QTC_ASSERT(m_currentHandlerIndex >= 0, return);
QTC_ASSERT(m_currentHandlerIndex < m_handlers.size(), return); QTC_ASSERT(m_currentHandlerIndex < m_handlers.size(), return);
QTC_ASSERT(documentRevision == m_documentRevision, return); QTC_ASSERT(documentRevision == m_documentRevision, return);
QTC_ASSERT(position == m_position, return); QTC_ASSERT(position == m_position, return);