forked from qt-creator/qt-creator
QmlDesigner: Add functionality to welcome plugin
* Add extraction progress and birth time * Add URL probing in downloader * Add last modified and available information * Overload openExample() function Task-number: QDS-6174 Change-Id: I68782629da3ec4da5aab95d00510b7bc7085aa66 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
committed by
Henning Gründl
parent
fba9a3514f
commit
c2cd524cdb
@@ -41,6 +41,8 @@
|
|||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QQuickWidget>
|
#include <QQuickWidget>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
ExampleCheckout::ExampleCheckout(QObject *) {}
|
ExampleCheckout::ExampleCheckout(QObject *) {}
|
||||||
@@ -137,11 +139,11 @@ FileDownloader::~FileDownloader()
|
|||||||
void FileDownloader::start()
|
void FileDownloader::start()
|
||||||
{
|
{
|
||||||
m_tempFile.setFileName(QDir::tempPath() + "/" + name() + ".XXXXXX" + ".zip");
|
m_tempFile.setFileName(QDir::tempPath() + "/" + name() + ".XXXXXX" + ".zip");
|
||||||
|
|
||||||
m_tempFile.open(QIODevice::WriteOnly);
|
m_tempFile.open(QIODevice::WriteOnly);
|
||||||
|
|
||||||
auto request = QNetworkRequest(m_url);
|
auto request = QNetworkRequest(m_url);
|
||||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, true);
|
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
|
||||||
|
QNetworkRequest::UserVerifiedRedirectPolicy);
|
||||||
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
|
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
|
||||||
|
|
||||||
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
|
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
|
||||||
@@ -159,20 +161,20 @@ void FileDownloader::start()
|
|||||||
emit progressChanged();
|
emit progressChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QNetworkReply::connect(reply, &QNetworkReply::redirected, [reply](const QUrl &url) {
|
||||||
|
emit reply->redirectAllowed();
|
||||||
|
});
|
||||||
|
|
||||||
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
||||||
if (reply->error()) {
|
if (reply->error()) {
|
||||||
m_tempFile.remove();
|
m_tempFile.remove();
|
||||||
if (m_url != reply->url()) {
|
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
|
||||||
m_url = reply->url();
|
emit downloadFailed();
|
||||||
start();
|
|
||||||
} else {
|
|
||||||
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
|
|
||||||
emit downloadFailed();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
m_tempFile.flush();
|
m_tempFile.flush();
|
||||||
m_tempFile.close();
|
m_tempFile.close();
|
||||||
m_finished = true;
|
m_finished = true;
|
||||||
|
emit tempFileChanged();
|
||||||
emit finishedChanged();
|
emit finishedChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -181,8 +183,9 @@ void FileDownloader::start()
|
|||||||
void FileDownloader::setUrl(const QUrl &url)
|
void FileDownloader::setUrl(const QUrl &url)
|
||||||
{
|
{
|
||||||
m_url = url;
|
m_url = url;
|
||||||
|
|
||||||
emit nameChanged();
|
emit nameChanged();
|
||||||
|
|
||||||
|
probeUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl FileDownloader::url() const
|
QUrl FileDownloader::url() const
|
||||||
@@ -222,16 +225,71 @@ QString FileDownloader::tempFile() const
|
|||||||
return QFileInfo(m_tempFile).canonicalFilePath();
|
return QFileInfo(m_tempFile).canonicalFilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDateTime FileDownloader::lastModified() const
|
||||||
|
{
|
||||||
|
return m_lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileDownloader::available() const
|
||||||
|
{
|
||||||
|
return m_available;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDownloader::probeUrl()
|
||||||
|
{
|
||||||
|
auto request = QNetworkRequest(m_url);
|
||||||
|
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
|
||||||
|
QNetworkRequest::UserVerifiedRedirectPolicy);
|
||||||
|
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->head(request);
|
||||||
|
|
||||||
|
QNetworkReply::connect(reply, &QNetworkReply::redirected, [reply](const QUrl &url) {
|
||||||
|
emit reply->redirectAllowed();
|
||||||
|
});
|
||||||
|
|
||||||
|
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
|
||||||
|
if (reply->error())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_lastModified = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
|
||||||
|
emit lastModifiedChanged();
|
||||||
|
|
||||||
|
m_available = true;
|
||||||
|
emit availableChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
QNetworkReply::connect(reply,
|
||||||
|
&QNetworkReply::errorOccurred,
|
||||||
|
[this, reply](QNetworkReply::NetworkError code) {
|
||||||
|
// QNetworkReply::HostNotFoundError
|
||||||
|
// QNetworkReply::ContentNotFoundError
|
||||||
|
m_available = false;
|
||||||
|
emit availableChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FileExtractor::FileExtractor(QObject *parent)
|
FileExtractor::FileExtractor(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
if (Core::DocumentManager::instance())
|
m_targetPath = Utils::FilePath::fromString(
|
||||||
m_targetPath = Core::DocumentManager::projectsDirectory();
|
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||||
|
|
||||||
|
if (!m_targetPath.isEmpty())
|
||||||
|
m_targetPath = m_targetPath.pathAppended("QtDesignStudio");
|
||||||
else
|
else
|
||||||
m_targetPath = "/temp/";
|
m_targetPath = "/temp/";
|
||||||
|
|
||||||
m_timer.setInterval(500);
|
m_timer.setInterval(100);
|
||||||
m_timer.setSingleShot(false);
|
m_timer.setSingleShot(false);
|
||||||
|
|
||||||
|
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, [this]() {
|
||||||
|
if (targetFolderExists()) {
|
||||||
|
m_birthTime = QFileInfo(m_targetPath.toString() + "/" + m_archiveName).birthTime();
|
||||||
|
} else
|
||||||
|
m_birthTime = QDateTime();
|
||||||
|
|
||||||
|
emit birthTimeChanged();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
FileExtractor::~FileExtractor() {}
|
FileExtractor::~FileExtractor() {}
|
||||||
@@ -297,8 +355,17 @@ QString FileExtractor::count() const
|
|||||||
|
|
||||||
bool FileExtractor::targetFolderExists() const
|
bool FileExtractor::targetFolderExists() const
|
||||||
{
|
{
|
||||||
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
return QFileInfo::exists(m_targetPath.toString() + "/" + m_archiveName);
|
||||||
return QFileInfo(targetFolder).exists();
|
}
|
||||||
|
|
||||||
|
int FileExtractor::progress() const
|
||||||
|
{
|
||||||
|
return m_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime FileExtractor::birthTime() const
|
||||||
|
{
|
||||||
|
return m_birthTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileExtractor::archiveName() const
|
QString FileExtractor::archiveName() const
|
||||||
@@ -320,8 +387,9 @@ void FileExtractor::extract()
|
|||||||
m_timer.start();
|
m_timer.start();
|
||||||
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName;
|
||||||
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||||
|
qint64 compressedSize = QFileInfo(m_sourceFile.toString()).size();
|
||||||
|
|
||||||
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder]() {
|
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder, compressedSize]() {
|
||||||
static QHash<QString, int> hash;
|
static QHash<QString, int> hash;
|
||||||
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
|
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
|
||||||
|
|
||||||
@@ -336,9 +404,15 @@ void FileExtractor::extract()
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_size = QString::number(bytesBefore
|
qint64 currentSize = bytesBefore
|
||||||
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable());
|
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
|
||||||
|
|
||||||
|
// We can not get the uncompressed size of the archive yet, that is why we use an
|
||||||
|
// approximation. We assume a 50% compression rate.
|
||||||
|
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
|
||||||
|
emit progressChanged();
|
||||||
|
|
||||||
|
m_size = QString::number(currentSize);
|
||||||
m_count = QString::number(count);
|
m_count = QString::number(count);
|
||||||
emit sizeChanged();
|
emit sizeChanged();
|
||||||
});
|
});
|
||||||
@@ -351,6 +425,11 @@ void FileExtractor::extract()
|
|||||||
QObject::connect(archive, &Utils::Archive::finished, [this](bool ret) {
|
QObject::connect(archive, &Utils::Archive::finished, [this](bool ret) {
|
||||||
m_finished = ret;
|
m_finished = ret;
|
||||||
m_timer.stop();
|
m_timer.stop();
|
||||||
|
|
||||||
|
m_progress = 100;
|
||||||
|
emit progressChanged();
|
||||||
|
|
||||||
|
emit targetFolderExistsChanged();
|
||||||
emit finishedChanged();
|
emit finishedChanged();
|
||||||
QTC_ASSERT(ret, ;);
|
QTC_ASSERT(ret, ;);
|
||||||
});
|
});
|
||||||
|
@@ -78,6 +78,8 @@ class FileExtractor : public QObject
|
|||||||
Q_PROPERTY(QString sourceFile READ sourceFile WRITE setSourceFile)
|
Q_PROPERTY(QString sourceFile READ sourceFile WRITE setSourceFile)
|
||||||
Q_PROPERTY(bool finished READ finished NOTIFY finishedChanged)
|
Q_PROPERTY(bool finished READ finished NOTIFY finishedChanged)
|
||||||
Q_PROPERTY(bool targetFolderExists READ targetFolderExists NOTIFY targetFolderExistsChanged)
|
Q_PROPERTY(bool targetFolderExists READ targetFolderExists NOTIFY targetFolderExistsChanged)
|
||||||
|
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
|
||||||
|
Q_PROPERTY(QDateTime birthTime READ birthTime NOTIFY birthTimeChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FileExtractor(QObject *parent = nullptr);
|
explicit FileExtractor(QObject *parent = nullptr);
|
||||||
@@ -94,6 +96,8 @@ public:
|
|||||||
QString size() const;
|
QString size() const;
|
||||||
QString count() const;
|
QString count() const;
|
||||||
bool targetFolderExists() const;
|
bool targetFolderExists() const;
|
||||||
|
int progress() const;
|
||||||
|
QDateTime birthTime() const;
|
||||||
|
|
||||||
QString sourceFile() const;
|
QString sourceFile() const;
|
||||||
QString archiveName() const;
|
QString archiveName() const;
|
||||||
@@ -108,6 +112,8 @@ signals:
|
|||||||
void currentFileChanged();
|
void currentFileChanged();
|
||||||
void sizeChanged();
|
void sizeChanged();
|
||||||
void targetFolderExistsChanged();
|
void targetFolderExistsChanged();
|
||||||
|
void progressChanged();
|
||||||
|
void birthTimeChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::FilePath m_targetPath;
|
Utils::FilePath m_targetPath;
|
||||||
@@ -119,6 +125,8 @@ private:
|
|||||||
QString m_size;
|
QString m_size;
|
||||||
QString m_count;
|
QString m_count;
|
||||||
QString m_archiveName;
|
QString m_archiveName;
|
||||||
|
int m_progress = 0;
|
||||||
|
QDateTime m_birthTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileDownloader : public QObject
|
class FileDownloader : public QObject
|
||||||
@@ -131,7 +139,9 @@ class FileDownloader : public QObject
|
|||||||
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
|
||||||
Q_PROPERTY(QString completeBaseName READ completeBaseName NOTIFY nameChanged)
|
Q_PROPERTY(QString completeBaseName READ completeBaseName NOTIFY nameChanged)
|
||||||
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
|
Q_PROPERTY(int progress READ progress NOTIFY progressChanged)
|
||||||
Q_PROPERTY(QString tempFile READ tempFile NOTIFY finishedChanged)
|
Q_PROPERTY(QString tempFile READ tempFile NOTIFY tempFileChanged)
|
||||||
|
Q_PROPERTY(QDateTime lastModified READ lastModified NOTIFY lastModifiedChanged)
|
||||||
|
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FileDownloader(QObject *parent = nullptr);
|
explicit FileDownloader(QObject *parent = nullptr);
|
||||||
@@ -147,6 +157,8 @@ public:
|
|||||||
QString completeBaseName() const;
|
QString completeBaseName() const;
|
||||||
int progress() const;
|
int progress() const;
|
||||||
QString tempFile() const;
|
QString tempFile() const;
|
||||||
|
QDateTime lastModified() const;
|
||||||
|
bool available() const;
|
||||||
|
|
||||||
Q_INVOKABLE void start();
|
Q_INVOKABLE void start();
|
||||||
|
|
||||||
@@ -155,12 +167,19 @@ signals:
|
|||||||
void errorChanged();
|
void errorChanged();
|
||||||
void nameChanged();
|
void nameChanged();
|
||||||
void progressChanged();
|
void progressChanged();
|
||||||
|
void tempFileChanged();
|
||||||
void downloadFailed();
|
void downloadFailed();
|
||||||
|
void lastModifiedChanged();
|
||||||
|
void availableChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void probeUrl();
|
||||||
|
|
||||||
QUrl m_url;
|
QUrl m_url;
|
||||||
bool m_finished = false;
|
bool m_finished = false;
|
||||||
bool m_error = false;
|
bool m_error = false;
|
||||||
int m_progress = 0;
|
int m_progress = 0;
|
||||||
QFile m_tempFile;
|
QFile m_tempFile;
|
||||||
|
QDateTime m_lastModified;
|
||||||
|
bool m_available;
|
||||||
};
|
};
|
||||||
|
@@ -232,6 +232,28 @@ public:
|
|||||||
QDesktopServices::openUrl(QUrl("qthelp://org.qt-project.qtcreator/doc/index.html"));
|
QDesktopServices::openUrl(QUrl("qthelp://org.qt-project.qtcreator/doc/index.html"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE void openExample(const QString &examplePath,
|
||||||
|
const QString &exampleName,
|
||||||
|
const QString &formFile,
|
||||||
|
const QString &explicitQmlproject)
|
||||||
|
{
|
||||||
|
const QString exampleFolder = examplePath + "/" + exampleName + "/";
|
||||||
|
|
||||||
|
QString projectFile = exampleFolder + exampleName + ".qmlproject";
|
||||||
|
|
||||||
|
if (!explicitQmlproject.isEmpty())
|
||||||
|
projectFile = exampleFolder + explicitQmlproject;
|
||||||
|
|
||||||
|
ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile);
|
||||||
|
|
||||||
|
const QString qmlFile = QFileInfo(projectFile).dir().absolutePath() + "/" + formFile;
|
||||||
|
|
||||||
|
// This timer should be replaced with a signal send from project loading
|
||||||
|
QTimer::singleShot(1000, [qmlFile](){
|
||||||
|
Core::EditorManager::openEditor(Utils::FilePath::fromString(qmlFile));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Q_INVOKABLE void openExample(const QString &example,
|
Q_INVOKABLE void openExample(const QString &example,
|
||||||
const QString &formFile,
|
const QString &formFile,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
@@ -272,6 +294,7 @@ public:
|
|||||||
|
|
||||||
Core::EditorManager::openEditor(qmlFile);
|
Core::EditorManager::openEditor(qmlFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void resetProjects();
|
void resetProjects();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user