Skip to content
Snippets Groups Projects
Commit 9a344f35 authored by Burak Hançerli's avatar Burak Hançerli :headphones:
Browse files

QDS-11236 Simple caching method for the demos

parent 82adcd36
No related branches found
Tags v14
1 merge request!19QDS-11236 Simple caching method for the demos
Pipeline #64386 passed
<?xml version="1.0"?> <?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.qtdesignviewer" <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.qtdesignviewer"
android:installLocation="auto" android:versionCode="13" android:versionName="1.2"> android:installLocation="auto" android:versionCode="14" android:versionName="1.2">
<!-- %%INSERT_PERMISSIONS --> <!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES --> <!-- %%INSERT_FEATURES -->
<supports-screens android:anyDensity="true" android:largeScreens="true" <supports-screens android:anyDensity="true" android:largeScreens="true"
......
...@@ -86,34 +86,56 @@ void Backend::showWarning(const QString &message) ...@@ -86,34 +86,56 @@ void Backend::showWarning(const QString &message)
{ {
QMessageBox msg(QMessageBox::Warning, "Warning", message, QMessageBox::Ok); QMessageBox msg(QMessageBox::Warning, "Warning", message, QMessageBox::Ok);
msg.exec(); msg.exec();
qWarning() << message;
} }
void Backend::downloadAndRun(const QString &url) void Backend::updatePopup(const QString &text, bool indeterminate)
{ {
updatePopup("Downloading project...", false); emit popupTextChanged(text);
emit popupProgressIndeterminateChanged(indeterminate);
QEventLoop().processEvents(QEventLoop::AllEvents, 100);
}
void Backend::runDemoProject(const QString &projectName)
{
qDebug() << "Checking if demo project is cached for " << projectName;
emit popupOpen(); emit popupOpen();
qDebug() << "Fetching project from " << url << "..."; const bool cached = m_projectManager.isDemoProjectCached(projectName);
QByteArray project = m_serviceConnector.fetchProject(url);
updatePopup("Unpacking project..."); if (!cached) {
updatePopup("Downloading demo project...", false);
const QString projectPath = m_projectManager.unpackProject(project); const QString url = "https://designviewer.qt.io/qmlprojects/" + projectName + ".qmlrc";
QByteArray project = m_serviceConnector.fetchProject(url);
qDebug() << "Demo project is not cached. Trying to download from " << url << " ...";
updatePopup("Caching demo project...");
if (!m_projectManager.cacheDemoProject(project, projectName)) {
showWarning(
"Could not cache demo project. Please check the logs for more information.");
emit popupClose();
return;
}
} else {
qDebug() << "Demo project is cached. Running cached project...";
}
updatePopup("Running project..."); updatePopup("Running demo project...");
if (!m_projectManager.runProject(projectPath, QFileInfo(url).baseName())) if (!m_projectManager.runDemoProject(projectName))
qCritical("Could not run project"); showWarning("Could not run demo project. Please check the logs for more information.");
else else
m_projectManager.showAppWindow(); m_projectManager.showAppWindow();
emit popupClose(); emit popupClose();
} }
void Backend::updatePopup(const QString &text, bool indeterminate) void Backend::clearDemoCaches()
{ {
emit popupTextChanged(text); emit popupOpen();
emit popupProgressIndeterminateChanged(indeterminate); updatePopup("Clearing demo caches...");
QEventLoop().processEvents(QEventLoop::AllEvents, 100); m_projectManager.clearDemoCaches();
emit popupClose();
} }
void Backend::runUserProject(const QString &url) void Backend::runUserProject(const QString &url)
...@@ -142,14 +164,18 @@ void Backend::runUserProject(const QString &url) ...@@ -142,14 +164,18 @@ void Backend::runUserProject(const QString &url)
QByteArray projectData = m_serviceConnector.fetchProject(url); QByteArray projectData = m_serviceConnector.fetchProject(url);
updatePopup("Caching user project..."); updatePopup("Caching user project...");
m_projectManager.cacheProject(projectData, projectInfo); if (!m_projectManager.cacheProject(projectData, projectInfo)) {
showWarning("Could not cache project. Please check the logs for more information.");
emit popupClose();
return;
}
} else { } else {
qDebug("Project is cached. Running cached project..."); qDebug("Project is cached. Running cached project...");
} }
updatePopup("Running cached project..."); updatePopup("Running cached project...");
if (!m_projectManager.runCachedProject(projectInfo)) if (!m_projectManager.runCachedProject(projectInfo))
qCritical("Could not run project"); showWarning("Could not run project. Please check the logs for more information.");
else else
m_projectManager.showAppWindow(); m_projectManager.showAppWindow();
......
...@@ -77,7 +77,8 @@ signals: ...@@ -77,7 +77,8 @@ signals:
public slots: public slots:
void runUserProject(const QString &url); void runUserProject(const QString &url);
void downloadAndRun(const QString &url); void runDemoProject(const QString &projectName);
void clearDemoCaches();
void registerUser(const QUrl &url); void registerUser(const QUrl &url);
}; };
......
...@@ -29,14 +29,15 @@ ...@@ -29,14 +29,15 @@
#include "backend.h" #include "backend.h"
Backend *backend; static Backend *backend;
static QString appLogs;
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
QByteArray localMsg = msg.toLocal8Bit(); QByteArray localMsg = msg.toLocal8Bit();
const char *file = context.file ? context.file : ""; const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : ""; const char *function = context.function ? context.function : "";
QString logPrefix, logSuffix, applicationLogs; QString logPrefix, logSuffix, newLog;
switch (type) switch (type)
{ {
...@@ -57,11 +58,11 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt ...@@ -57,11 +58,11 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
logSuffix = QStringLiteral(" (%1:%2, %3)").arg(file).arg(context.line).arg(function); logSuffix = QStringLiteral(" (%1:%2, %3)").arg(file).arg(context.line).arg(function);
break; break;
} }
applicationLogs += logPrefix + localMsg + logSuffix + "\n"; newLog += logPrefix + localMsg + logSuffix + "\n";
__android_log_print(ANDROID_LOG_DEBUG, "Qt_Design_Viewer", "%s", qPrintable(applicationLogs)); __android_log_print(ANDROID_LOG_DEBUG, "Qt_Design_Viewer", "%s", qPrintable(newLog));
if (backend) if (backend)
backend->setLogs(applicationLogs); backend->setLogs(appLogs += newLog);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
...@@ -81,7 +82,5 @@ int main(int argc, char *argv[]) ...@@ -81,7 +82,5 @@ int main(int argc, char *argv[])
view.showMaximized(); view.showMaximized();
backend->initialize(); backend->initialize();
backend->registerUser(QUrl("17e8907b3b84b8206d45be4f551f4e25"));
return app.exec(); return app.exec();
} }
...@@ -46,9 +46,22 @@ ...@@ -46,9 +46,22 @@
ProjectManager::ProjectManager(QObject *parent) ProjectManager::ProjectManager(QObject *parent)
: QObject(parent) : QObject(parent)
, m_projectCachePath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))
, m_demoProjectCachePath(m_projectCachePath + "/demoProjects")
{ {
qDebug() << "ProjectManager created."; qDebug() << "ProjectManager created.";
m_projectCachePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); qDebug() << "Project cache path: " << m_projectCachePath;
qDebug() << "Demo project cache path: " << m_demoProjectCachePath;
if (!QDir(m_projectCachePath).exists()) {
qDebug() << "Creating project cache path: " << m_projectCachePath;
QDir().mkpath(m_projectCachePath);
}
if (!QDir(m_demoProjectCachePath).exists()) {
qDebug() << "Creating demo project cache path: " << m_demoProjectCachePath;
QDir().mkpath(m_demoProjectCachePath);
}
} }
QString ProjectManager::unpackProject(const QByteArray &project, bool extractZip) QString ProjectManager::unpackProject(const QByteArray &project, bool extractZip)
...@@ -215,13 +228,17 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje ...@@ -215,13 +228,17 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje
qputenv("QT_QUICK_CONTROLS_CONF", qtquickcontrols2File.toLatin1()); qputenv("QT_QUICK_CONTROLS_CONF", qtquickcontrols2File.toLatin1());
} }
qDebug() << "Initializing the qmlEngine";
m_qmlEngine.reset(new QQmlEngine);
m_qmlEngine->clearComponentCache();
qDebug("Adding import paths"); qDebug("Adding import paths");
for (const QString &importPath : importPaths) { for (const QString &importPath : importPaths) {
qDebug() << "-- Import path: " << importPath; qDebug() << "-- Import path: " << importPath;
m_qmlEngine.addImportPath(importPath); m_qmlEngine->addImportPath(importPath);
} }
QObject::connect(&m_qmlEngine, QObject::connect(m_qmlEngine.data(),
&QQmlEngine::warnings, &QQmlEngine::warnings,
this, this,
[&](const QList<QQmlError> &warnings) { [&](const QList<QQmlError> &warnings) {
...@@ -234,7 +251,7 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje ...@@ -234,7 +251,7 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje
QEventLoop().processEvents(QEventLoop::AllEvents, 1000); QEventLoop().processEvents(QEventLoop::AllEvents, 1000);
qDebug() << "Loading mainQmlUrl: " << mainQmlUrl.toString(); qDebug() << "Loading mainQmlUrl: " << mainQmlUrl.toString();
m_qmlComponent.reset(new QQmlComponent(&m_qmlEngine)); m_qmlComponent.reset(new QQmlComponent(m_qmlEngine.data()));
m_qmlComponent->loadUrl(mainQmlUrl); m_qmlComponent->loadUrl(mainQmlUrl);
qDebug() << "Waiting for qmlComponent to load"; qDebug() << "Waiting for qmlComponent to load";
...@@ -260,7 +277,7 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje ...@@ -260,7 +277,7 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje
m_quickWindow.reset(qobject_cast<QQuickWindow *>(topLevel)); m_quickWindow.reset(qobject_cast<QQuickWindow *>(topLevel));
if (m_quickWindow) { if (m_quickWindow) {
qDebug() << "Running with incubator controller"; qDebug() << "Running with incubator controller";
m_qmlEngine.setIncubationController(m_quickWindow->incubationController()); m_qmlEngine->setIncubationController(m_quickWindow->incubationController());
} else { } else {
qWarning() << "Top level object is not a QQuickWindow. Trying QQuickView..."; qWarning() << "Top level object is not a QQuickWindow. Trying QQuickView...";
...@@ -271,7 +288,7 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje ...@@ -271,7 +288,7 @@ bool ProjectManager::runProject(const QString &projectPath, const QString &proje
} }
qDebug() << "Initializing QQuickView"; qDebug() << "Initializing QQuickView";
QQuickView *view = new QQuickView(&m_qmlEngine, nullptr); QQuickView *view = new QQuickView(m_qmlEngine.data(), nullptr);
m_quickWindow.reset(view); m_quickWindow.reset(view);
view->setContent(mainQmlUrl, m_qmlComponent.data(), contentItem); view->setContent(mainQmlUrl, m_qmlComponent.data(), contentItem);
view->setResizeMode(QQuickView::SizeViewToRootObject); view->setResizeMode(QQuickView::SizeViewToRootObject);
...@@ -386,6 +403,66 @@ bool ProjectManager::runCachedProject(const QJsonObject &projectInfo) ...@@ -386,6 +403,66 @@ bool ProjectManager::runCachedProject(const QJsonObject &projectInfo)
return runProject(projectPath, projectName); return runProject(projectPath, projectName);
} }
bool ProjectManager::cacheDemoProject(const QByteArray &projectData, const QString &projectName)
{
const QString demoProjectPath = m_demoProjectCachePath + "/" + projectName;
qDebug() << "Caching demo project " << projectName << " to " << demoProjectPath;
// remove old cache
if (QDir(demoProjectPath).exists()) {
qDebug() << "Removing old cache for demo project " << projectName;
if (!QDir(demoProjectPath).removeRecursively()) {
qCritical() << "Could not remove old cache for demo project " << projectName;
return false;
}
}
// create new cache
if (!QDir().mkpath(demoProjectPath)) {
qCritical() << "Could not create new cache for demo project " << projectName;
return false;
}
const QString tempProjectPath = unpackProject(projectData);
// copy all files from tempProjectPath to demoProjectPath
QDirIterator it(tempProjectPath, QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
const QString filePath = it.filePath();
const QString relativeFilePath = filePath.mid(tempProjectPath.length());
const QString newFilePath = demoProjectPath + relativeFilePath;
qDebug() << "Copying " << filePath << " to " << newFilePath;
if (QFileInfo(filePath).isDir()) {
QDir().mkpath(newFilePath);
} else if (!QFile::copy(filePath, newFilePath)) {
qCritical() << "Could not copy " << filePath << " to " << newFilePath;
return false;
}
}
return true;
}
void ProjectManager::clearDemoCaches()
{
qDebug() << "Clearing demo caches";
QDir(m_demoProjectCachePath).removeRecursively();
}
bool ProjectManager::isDemoProjectCached(const QString &projectName)
{
const QString demoProjectPath = m_demoProjectCachePath + "/" + projectName;
qDebug() << "Checking if demo project " << projectName << " is cached";
return QDir(demoProjectPath).exists();
}
bool ProjectManager::runDemoProject(const QString &projectName)
{
const QString demoProjectPath = m_demoProjectCachePath + "/" + projectName;
qDebug() << "Running demo project " << projectName << " from " << demoProjectPath;
return runProject(demoProjectPath, projectName);
}
void ProjectManager::orientateWindow(Qt::ScreenOrientation orientation) void ProjectManager::orientateWindow(Qt::ScreenOrientation orientation)
{ {
QQuickItem *contentItem = m_quickWindow->contentItem(); QQuickItem *contentItem = m_quickWindow->contentItem();
......
...@@ -38,11 +38,19 @@ class ProjectManager : public QObject ...@@ -38,11 +38,19 @@ class ProjectManager : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit ProjectManager(QObject *parent = nullptr); explicit ProjectManager(QObject *parent = nullptr);
QString unpackProject(const QByteArray &project, bool extractZip = false); QString unpackProject(const QByteArray &project, bool extractZip = false);
bool runProject(const QString &projectPath, const QString &projectName); bool runProject(const QString &projectPath, const QString &projectName);
bool cacheProject(const QByteArray &projectData, const QJsonObject &projectInfo); bool cacheProject(const QByteArray &projectData, const QJsonObject &projectInfo);
bool isProjectCached(const QJsonObject &projectInfo); bool isProjectCached(const QJsonObject &projectInfo);
bool runCachedProject(const QJsonObject &projectInfo); bool runCachedProject(const QJsonObject &projectInfo);
bool cacheDemoProject(const QByteArray &projectData, const QString &projectName);
bool isDemoProjectCached(const QString &projectName);
bool runDemoProject(const QString &projectName);
void clearDemoCaches();
void showAppWindow(); void showAppWindow();
void hideAppWindow(); void hideAppWindow();
...@@ -53,12 +61,13 @@ private: ...@@ -53,12 +61,13 @@ private:
// Member variables // Member variables
QByteArray m_projectData; QByteArray m_projectData;
QString m_projectPath; QString m_projectPath;
QString m_projectCachePath; const QString m_projectCachePath;
const QString m_demoProjectCachePath;
// Qml related members // Qml related members
QQmlEngine m_qmlEngine; QScopedPointer<QQmlEngine> m_qmlEngine;
QSharedPointer<QQmlComponent> m_qmlComponent; QScopedPointer<QQmlComponent> m_qmlComponent;
QSharedPointer<QQuickWindow> m_quickWindow; QScopedPointer<QQuickWindow> m_quickWindow;
// Member functions // Member functions
QString findFile(const QString &dir, const QString &filter); QString findFile(const QString &dir, const QString &filter);
......
...@@ -13,7 +13,7 @@ Item { ...@@ -13,7 +13,7 @@ Item {
id: button3 id: button3
text: qsTr("Cluster Tutorial") text: qsTr("Cluster Tutorial")
Layout.fillWidth: true Layout.fillWidth: true
onClicked: backend.downloadAndRun("https://designviewer.qt.io/#ClusterTutorial.qmlrc") onClicked: backend.runDemoProject("ClusterTutorial")
} }
...@@ -21,14 +21,14 @@ Item { ...@@ -21,14 +21,14 @@ Item {
id: button id: button
text: qsTr("E-Bike Design") text: qsTr("E-Bike Design")
Layout.fillWidth: true Layout.fillWidth: true
onClicked: backend.downloadAndRun("https://designviewer.qt.io/#EBikeDesign.qmlrc") onClicked: backend.runDemoProject("EBikeDesign")
} }
Button { Button {
id: button4 id: button4
text: qsTr("Material Bundle") text: qsTr("Material Bundle")
Layout.fillWidth: true Layout.fillWidth: true
onClicked: backend.downloadAndRun("https://designviewer.qt.io/#MaterialBundle.qmlrc") onClicked: backend.runDemoProject("MaterialBundle")
} }
Item { Item {
...@@ -38,5 +38,12 @@ Item { ...@@ -38,5 +38,12 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
} }
Button {
id: button5
text: qsTr("Clear demo caches")
Layout.fillWidth: true
onClicked: backend.clearDemoCaches()
}
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment