diff --git a/src/plugins/studiowelcome/CMakeLists.txt b/src/plugins/studiowelcome/CMakeLists.txt index b04caf2a6d4..fe7f34ca7f4 100644 --- a/src/plugins/studiowelcome/CMakeLists.txt +++ b/src/plugins/studiowelcome/CMakeLists.txt @@ -4,6 +4,7 @@ add_qtc_plugin(StudioWelcome DEFINES STUDIO_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/qml/" SOURCES studiowelcomeplugin.cpp studiowelcomeplugin.h + examplecheckout.cpp examplecheckout.h studiowelcome_global.h studiowelcome.qrc "${PROJECT_SOURCE_DIR}/src/share/3rdparty/studiofonts/studiofonts.qrc" diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp new file mode 100644 index 00000000000..c7180155d85 --- /dev/null +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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("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("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 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, ;); + }); +} diff --git a/src/plugins/studiowelcome/examplecheckout.h b/src/plugins/studiowelcome/examplecheckout.h new file mode 100644 index 00000000000..0038d7f2c0f --- /dev/null +++ b/src/plugins/studiowelcome/examplecheckout.h @@ -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 + +#include +#include +#include + +#include + +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 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; +}; diff --git a/src/plugins/studiowelcome/qml/downloaddialog/ArcItem.qml b/src/plugins/studiowelcome/qml/downloaddialog/ArcItem.qml new file mode 100644 index 00000000000..fa38d302dba --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/ArcItem.qml @@ -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() + } +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/CircularIndicator.ui.qml b/src/plugins/studiowelcome/qml/downloaddialog/CircularIndicator.ui.qml new file mode 100644 index 00000000000..15b2e265527 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/CircularIndicator.ui.qml @@ -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 + } + } + } +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/CoolProgressBar.ui.qml b/src/plugins/studiowelcome/qml/downloaddialog/CoolProgressBar.ui.qml new file mode 100644 index 00000000000..b48880406c5 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/CoolProgressBar.ui.qml @@ -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} +} +##^##*/ diff --git a/src/plugins/studiowelcome/qml/downloaddialog/DialogButton.qml b/src/plugins/studiowelcome/qml/downloaddialog/DialogButton.qml new file mode 100644 index 00000000000..d21acdde359 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/DialogButton.qml @@ -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 + } + } + ] +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/DialogLabel.qml b/src/plugins/studiowelcome/qml/downloaddialog/DialogLabel.qml new file mode 100644 index 00000000000..c5dac79a504 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/DialogLabel.qml @@ -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 +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/MinMaxMapper.qml b/src/plugins/studiowelcome/qml/downloaddialog/MinMaxMapper.qml new file mode 100644 index 00000000000..451c098f9e3 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/MinMaxMapper.qml @@ -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 +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/RangeMapper.qml b/src/plugins/studiowelcome/qml/downloaddialog/RangeMapper.qml new file mode 100644 index 00000000000..dc75325b084 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/RangeMapper.qml @@ -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 + +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/downloaddialog.qmlproject b/src/plugins/studiowelcome/qml/downloaddialog/downloaddialog.qmlproject new file mode 100644 index 00000000000..880c6022a96 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/downloaddialog.qmlproject @@ -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" + } +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/main.qml b/src/plugins/studiowelcome/qml/downloaddialog/main.qml new file mode 100644 index 00000000000..cb7f62a68c4 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/main.qml @@ -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 + } + } + } +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/FileDownloader.qml b/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/FileDownloader.qml new file mode 100644 index 00000000000..bf873ec5631 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/FileDownloader.qml @@ -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 + } + + } +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/FileExtractor.qml b/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/FileExtractor.qml new file mode 100644 index 00000000000..d3ee8e20f6b --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/FileExtractor.qml @@ -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" +} diff --git a/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/qmldir b/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/qmldir new file mode 100644 index 00000000000..7c2bb0bcd49 --- /dev/null +++ b/src/plugins/studiowelcome/qml/downloaddialog/mockData/ExampleCheckout/qmldir @@ -0,0 +1,2 @@ +FileDownloader 1.0 FileDownloader.qml +FileExtractor 1.0 FileExtractor.qml diff --git a/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml b/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml index 5e9fe07985c..3f33f0205e8 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/ExamplesModel.qml @@ -74,4 +74,13 @@ ListModel { thumbnail: "images/washingmachinedemo_thumbnail.png" 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 + } } diff --git a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml index e160a1f70e3..a7d7501a52c 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/HoverOverDesaturate.qml @@ -35,6 +35,8 @@ Item { property alias imageSource: image.source property alias labelText: label.text + property alias downloadIcon: downloadCloud.visible + onVisibleChanged: { animateOpacity.start() animateScale.start() @@ -89,6 +91,19 @@ Item { rectangle.color = "#262728" 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 } } + +/*##^## +Designer { + D{i:0;formeditorZoom:1.3300000429153442}D{i:8} +} +##^##*/ diff --git a/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml b/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml index 6faf3a65547..6a18d10ded3 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/ProjectsGrid.qml @@ -39,6 +39,7 @@ GridView { id: hoverOverDesaturate imageSource: typeof(thumbnail) === "undefined" ? "images/thumbnail_test.png" : thumbnail; labelText: displayName + downloadIcon: typeof(showDownload) === "undefined" ? false : showDownload; SequentialAnimation { id: animation diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/downloadCloud.svg b/src/plugins/studiowelcome/qml/welcomepage/images/downloadCloud.svg new file mode 100644 index 00000000000..3a527c3e54f --- /dev/null +++ b/src/plugins/studiowelcome/qml/welcomepage/images/downloadCloud.svg @@ -0,0 +1,29 @@ + + + + + + + diff --git a/src/plugins/studiowelcome/qml/welcomepage/images/highendivi_thumbnail.png b/src/plugins/studiowelcome/qml/welcomepage/images/highendivi_thumbnail.png new file mode 100644 index 00000000000..5428c80776e Binary files /dev/null and b/src/plugins/studiowelcome/qml/welcomepage/images/highendivi_thumbnail.png differ diff --git a/src/plugins/studiowelcome/qml/welcomepage/main.qml b/src/plugins/studiowelcome/qml/welcomepage/main.qml index 759ac459235..771f4845858 100644 --- a/src/plugins/studiowelcome/qml/welcomepage/main.qml +++ b/src/plugins/studiowelcome/qml/welcomepage/main.qml @@ -60,7 +60,7 @@ Item { ScrollView { ProjectsGrid { model: ExamplesModel {} - onItemSelected: projectModel.openExample(item.projectName, item.qmlFileName) + onItemSelected: projectModel.openExample(item.projectName, item.qmlFileName, item.url) } } diff --git a/src/plugins/studiowelcome/studiowelcome.pro b/src/plugins/studiowelcome/studiowelcome.pro index 183f955a490..e2ccee8576f 100644 --- a/src/plugins/studiowelcome/studiowelcome.pro +++ b/src/plugins/studiowelcome/studiowelcome.pro @@ -12,9 +12,11 @@ DEFINES += STUDIO_QML_PATH=\\\"$$PWD/qml/\\\" HEADERS += \ studiowelcome_global.h \ studiowelcomeplugin.h \ + examplecheckout.h SOURCES += \ - studiowelcomeplugin.cpp + studiowelcomeplugin.cpp \ + examplecheckout.cpp OTHER_FILES += \ StudioWelcome.json.in diff --git a/src/plugins/studiowelcome/studiowelcome.qbs b/src/plugins/studiowelcome/studiowelcome.qbs index b875a35c777..f2bec88af22 100644 --- a/src/plugins/studiowelcome/studiowelcome.qbs +++ b/src/plugins/studiowelcome/studiowelcome.qbs @@ -17,6 +17,8 @@ QtcPlugin { "studiowelcome_global.h", "studiowelcomeplugin.h", "studiowelcomeplugin.cpp", + "examplecheckout.h", + "examplecheckout.cpp", "studiowelcome.qrc", ] diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 5cb362b0998..a2ac354fa01 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "studiowelcomeplugin.h" +#include "examplecheckout.h" #include #include @@ -175,9 +176,29 @@ public: QDesktopServices::openUrl(QUrl("qthelp://org.qt-project.qtcreator/doc/index.html")); } - Q_INVOKABLE void openExample(const QString &example, const QString &formFile) + Q_INVOKABLE void openExample(const QString &example, const QString &formFile, const QString &url) { - const QString projectFile = Core::ICore::resourcePath() + "/examples/" + example + "/" + example + ".qmlproject"; + if (!url.isEmpty()) { + ExampleCheckout *checkout = new ExampleCheckout; + checkout->checkoutExample(QUrl::fromUserInput(url)); + connect(checkout, + &ExampleCheckout::finishedSucessfully, + this, + [checkout, this, formFile, example]() { + const QString projectFile = checkout->extractionFolder() + "/" + example + + "/" + example + ".qmlproject"; + + ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile); + const QString qmlFile = checkout->extractionFolder() + "/" + example + "/" + + formFile; + + Core::EditorManager::openEditor(qmlFile); + }); + return; + } + + const QString projectFile = Core::ICore::resourcePath() + "/examples/" + example + "/" + + example + ".qmlproject"; ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile); const QString qmlFile = Core::ICore::resourcePath() + "/examples/" + example + "/" + formFile; Core::EditorManager::openEditor(qmlFile);