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

QDS-11858 Cannot open project with passwords

parent aaa304d4
No related branches found
No related tags found
1 merge request!40QDS-11858 Cannot open project with passwords
Pipeline #67627 passed
......@@ -3,3 +3,4 @@ ui/*.db
ui/*.qtds
ui/*.db-shm
ui/*.db-wal
ui/share.qrc
# Qt Design Viewer for Android
# Qt UI Viewer
## About
Launch [Design Studio](https://www.qt.io/ui-design-tools) projects in your Android device. The viewer that helps you do this is done with [Qt for Android](https://doc.qt.io/qt-6/android.html).
Qt Design Viewer works with minimum Android 33.
Launch [Design Studio](https://www.qt.io/ui-design-tools) projects in your Android device. The viewer that helps you do with [Qt for Android](https://doc.qt.io/qt-6/android.html).
Qt UI Viewer works with minimum Android 33.
## Getting the App
You can get the pre-built app from either [Google Play Store][google-play-link] or [Package Registry][package-registry]. Package registry provides the APK file for manual installation.
## Prerequisites
......@@ -31,7 +36,6 @@ Build instructions are provided for Linux and macOS hosts. Windows should work a
> If you're building in a Docker container and you've mounted the source directory into the container, you may need to change the build path pointing out somewhere out of the source directory. Otherwise you may get errors like the following;
> `CMake Error at /opt/qt-v.6.5.0/android-arm64-v8a/lib/cmake/Qt6/QtSyncQtHelpers.cmake:235 (message): syncqt.cpp failed for module QtQuickStudioApplication: Unable to remove file ...`
> Note:
> Android build instructions can also be used on desktop (or host) for testing purposes. Just replace the `CMAKE_TOOLCHAIN_FILE` path with the path to your Qt host installation.
......@@ -55,7 +59,7 @@ cmake --install build
popd
```
Then build the Qt Design Viewer:
Then build the Qt UI Viewer:
```bash
cmake \
......@@ -83,3 +87,6 @@ Upload the final APK file to your Android device and run. Then follow the instru
* [QtQuickDesigner Components](https://codereview.qt-project.org/gitweb?p=qt-labs%2Fqtquickdesigner-components.git;a=summary)
GNU GENERAL PUBLIC LICENSE
QtQuickDesigner Components is a collection of QML components for Qt Quick Designer.
[google-play-link]: <https://play.google.com/store/apps/details?id=io.qt.qtdesignviewer>
[package-registry]: <https://git.qt.io/design-studio/design-viewer/qt-ui-viewer/-/packages>
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.qtdesignviewer"
android:installLocation="auto" android:versionCode="26" android:versionName="1.2">
android:installLocation="auto" android:versionCode="27" android:versionName="1.2">
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<supports-screens android:anyDensity="true" android:largeScreens="true"
......
......@@ -36,7 +36,7 @@ build-android:
cmake \
-S . \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=${DOCKER_ENV_QT_PATH_WITH_VERSION}/${QDS_CI_JOB_TARGET_PLATFORM}_${QDS_CI_JOB_TARGET_ARCH}/lib/cmake/Qt6/qt.toolchain.cmake \
-DANDROID_SDK_ROOT=${DOCKER_ENV_ANDROID_SDK_ROOT} \
-DANDROID_NDK_ROOT=${DOCKER_ENV_ANDROID_NDK_ROOT} \
......@@ -50,7 +50,7 @@ build-android:
-S . \
-B ${QDS_CI_JOB_BUILD_PATH} \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=${DOCKER_ENV_QT_PATH_WITH_VERSION}/${QDS_CI_JOB_TARGET_PLATFORM}_${QDS_CI_JOB_TARGET_ARCH}/lib/cmake/Qt6/qt.toolchain.cmake \
-DANDROID_SDK_ROOT=${DOCKER_ENV_ANDROID_SDK_ROOT} \
-DANDROID_NDK_ROOT=${DOCKER_ENV_ANDROID_NDK_ROOT} \
......@@ -58,4 +58,4 @@ build-android:
-DCMAKE_INSTALL_PREFIX=${QDS_CI_JOB_QT_ANDROID_PATH} \
-DANDROID_OPENSSL_PATH=${QDS_CI_JOB_OPENSSL_PATH}
- cmake --build ${QDS_CI_JOB_BUILD_PATH} --target all
- cp -r ${QDS_CI_JOB_BUILD_PATH}/android-build/build/outputs/apk/debug/* ${QDS_CI_JOB_ARTIFACTS_PATH}
- cp -r ${QDS_CI_JOB_BUILD_PATH}/android-build/build/outputs/apk/release/* ${QDS_CI_JOB_ARTIFACTS_PATH}
......@@ -10,7 +10,7 @@ create-packages:
optional: false
artifacts: true
variables:
QDS_PACKAGE_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/design-viewer/${CI_COMMIT_TAG}"
QDS_PACKAGE_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/qt-ui-viewer/${CI_COMMIT_TAG}"
script:
- apk add tar curl
- cd ${QDS_CI_ARTIFACTS_PATH}
......@@ -23,13 +23,13 @@ create-packages:
cd "$arch"
tar -czf "$platform-$arch.tar.gz" *
echo "Uploading $platform-$arch.tar.gz to GitLab Package Registry"
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file "${platform}-${arch}.tar.gz" ${QDS_PACKAGE_URL}/design_viewer-${CI_COMMIT_TAG}-qt${QDS_CI_QT_VERSION}-${platform}-${arch}.tar.gz
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file "${platform}-${arch}.tar.gz" ${QDS_PACKAGE_URL}/qt-ui-viewer-${CI_COMMIT_TAG}-qt${QDS_CI_QT_VERSION}-${platform}-${arch}.tar.gz
cd ..
done
cd ..
done
artifacts:
name: design-viewer-${CI_JOB_ID}-qt${QDS_CI_QT_VERSION}
name: qt-ui-viewer-${CI_JOB_ID}-qt${QDS_CI_QT_VERSION}
paths:
- ${QDS_CI_ARTIFACTS_PATH}
expire_in: 1 week
......@@ -45,8 +45,8 @@ create-release:
- job: create-packages
artifacts: true
variables:
QDS_PACKAGE_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/design-viewer/${CI_COMMIT_TAG}"
QDS_RELEASE_NAME: "Design Viewer - ${CI_COMMIT_TAG}"
QDS_PACKAGE_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/qt-ui-viewer/${CI_COMMIT_TAG}"
QDS_RELEASE_NAME: "Qt UI Viewer - ${CI_COMMIT_TAG}"
QDS_RELEASE_DESCRIPTION: "This version is built with Qt-${QDS_CI_QT_VERSION}."
release:
name: ${QDS_RELEASE_NAME}
......@@ -55,13 +55,10 @@ create-release:
assets:
links:
- name: "Binary Packages"
url: "https://git.qt.io/design-studio/cloud-services/design-viewer-app/-/packages"
url: "https://git.qt.io/design-studio/design-viewer/qt-ui-viewer/-/packages"
link_type: "package"
- name: "Docker Images - Android"
url: "https://git.qt.io/design-studio/maintenance/docker-images/container_registry/143"
link_type: "image"
- name: "Docker Images - WASM"
url: "https://git.qt.io/design-studio/maintenance/docker-images/container_registry/142"
- name: "Docker Images Used in CI/CD Pipeline"
url: "https://git.qt.io/design-studio/maintenance/docker-images/container_registry/155"
link_type: "image"
script:
- echo "Releasing ${QDS_RELEASE_NAME}"
......@@ -61,42 +61,30 @@ Backend::Backend(QObject *parent)
&ServiceConnector::downloadProgress,
this,
&Backend::downloadProgress);
}
void Backend::initialize()
{
const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
qDebug() << "Qt Design Viewer";
qDebug() << "System information:";
qDebug() << "-- Qt version: " << QT_VERSION_STR;
qDebug() << "-- OpenSSL support: " << QVariant(QSslSocket::supportsSsl()).toString();
qDebug() << "-- Screen height: " << QString::number(screenGeometry.height());
qDebug() << "-- Screen width: " << QString::number(screenGeometry.width());
updateUserProjectList();
// Initialize background update
connect(&m_backgroundTimer, &QTimer::timeout, this, &Backend::updateUserProjectList);
m_backgroundTimer.setInterval(1000 * 10);
enableBackgroundUpdate(updateInBackground());
#ifdef QT_DEBUG
const QString buildType = "Debug";
#else
const QString buildType = "Release";
#endif
const QString buildInfo = QCoreApplication::applicationVersion() + "\nTechnology Preview - "
+ QString(GIT_VERSION) + "\nQt " + QString(QT_VERSION_STR) + " - "
+ buildType + " Build" + "\nQt Quick Components "
+ QString(QT_QUICK_COMPONENTS_VERSION) + "\nOpenSSL support: "
+ QVariant(QSslSocket::supportsSsl()).toString();
emit buildInfoChanged(buildInfo);
if (userHash().isEmpty())
qDebug("User Hash is not registered. Scan QR code to register.");
else {
qDebug() << "User Hash: " << userHash();
updateUserProjectList();
}
m_buildInfo = QCoreApplication::applicationVersion() + "\nTechnology Preview - "
+ QString(GIT_VERSION) + "\nQt " + QString(QT_VERSION_STR) + " - " + buildType
+ " Build" + "\nQt Quick Components " + QString(QT_QUICK_COMPONENTS_VERSION)
+ "\nOpenSSL support: " + QVariant(QSslSocket::supportsSsl()).toString();
// Initialize background update
connect(&m_backgroundTimer, &QTimer::timeout, this, &Backend::updateUserProjectList);
m_backgroundTimer.setInterval(1000 * 10);
enableBackgroundUpdate(updateInBackground());
qDebug() << "Initialization complete";
const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
qDebug() << "Qt Design Viewer";
qDebug() << "System information:";
qDebug() << "-- Qt version: " << QT_VERSION_STR;
qDebug() << "-- OpenSSL support: " << QVariant(QSslSocket::supportsSsl()).toString();
qDebug() << "-- Screen height: " << QString::number(screenGeometry.height());
qDebug() << "-- Screen width: " << QString::number(screenGeometry.width());
}
void Backend::enableBackgroundUpdate(const bool &enabled)
......@@ -400,7 +388,7 @@ void Backend::clearDemoCaches()
emit popupClose();
}
void Backend::runUserProject(const QString &projectName)
void Backend::runUserProject(const QString &projectName, const QString &password)
{
initializeProjectManager();
updatePopup("Running user project");
......@@ -408,10 +396,20 @@ void Backend::runUserProject(const QString &projectName)
qDebug() << "Running user project:" << projectName;
QString projectLastModified;
QString projectId;
// fetch the project list to check if the project is cached
const std::optional<QJsonArray> projectList = m_serviceConnector.fetchUserProjectList(
userHash());
if (projectList == std::nullopt) {
qCritical()
<< "Could not fetch user project list. Please check your internet connection and "
"try again.";
emit popupClose();
return;
}
QJsonObject projectInfo;
for (const auto &project : m_projectList) {
for (const auto &project : projectList.value()) {
if (projectName == project.toObject().value("appName").toString()) {
projectInfo = project.toObject();
break;
......@@ -424,7 +422,7 @@ void Backend::runUserProject(const QString &projectName)
qDebug("Project is not cached. Downloading...");
updatePopup("Project is not cached. Downloading...", false);
const std::optional<QByteArray> projectData
= m_serviceConnector.fetchUserProject(userHash(), projectName);
= m_serviceConnector.fetchUserProject(userHash(), projectName, password);
if (projectData == std::nullopt) {
qCritical()
......
......@@ -62,7 +62,7 @@ class Backend : public QObject
public:
explicit Backend(QObject *parent = nullptr);
void initialize();
void setLogs(const QString &logs)
{
m_logs = logs;
......@@ -74,6 +74,7 @@ public:
private:
// UI data
QString m_logs;
QString m_buildInfo;
QJsonArray m_projectList;
// Other members
......@@ -114,11 +115,12 @@ signals:
void networkUpdated(QString);
public slots:
QString buildInfo() const { return m_buildInfo; }
void scanQrCode();
void openCamera();
void runOnlineProject(const QString &url);
void runUserProject(const QString &projectName);
void runUserProject(const QString &projectName, const QString &password);
void runDemoProject(const QString &projectName);
void clearDemoCaches();
......
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Viewer of the Qt Toolkit.
......@@ -64,33 +64,35 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
newLog += logPrefix + localMsg + logSuffix + "\n";
__android_log_print(ANDROID_LOG_DEBUG, "Qt_UI_Viewer", "%s", qPrintable(newLog));
if (type == QtWarningMsg) {
if (backend)
backend->setLogs(appLogs += newLog);
} else if (type == QtCriticalMsg || type == QtFatalMsg) {
QMessageBox msgBox{QMessageBox::Critical, "Critical:", msg, QMessageBox::Ok};
msgBox.exec();
if (type != QtDebugMsg) {
if (backend)
backend->setLogs(appLogs += newLog);
if (type == QtCriticalMsg || type == QtFatalMsg) {
QMessageBox msgBox{QMessageBox::Critical, "Critical:", msg, QMessageBox::Ok};
msgBox.exec();
}
}
}
int main(int argc, char *argv[])
{
qInstallMessageHandler(messageHandler);
qDebug() << "Starting Qt Design Viewer";
QApplication app(argc, argv);
QApplication::setOrganizationName("Qt");
QApplication::setApplicationName(QStringLiteral("Qt Design Viewer"));
QApplication::setApplicationVersion(QString("Built on %1 %2").arg(__DATE__, __TIME__));
QQuickView view;
backend = new Backend();
QQuickView view;
view.engine()->rootContext()->setContextProperty("backend", backend);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.showMaximized();
backend->initialize();
return app.exec();
}
......@@ -31,12 +31,12 @@
#include <QJsonDocument>
#include <QJsonObject>
std::optional<QByteArray> ServiceConnector::fetchResource(const QString &url)
std::optional<QByteArray> ServiceConnector::fetchResource(const QString &url, const QString &auth)
{
qDebug() << "Fetching resource from" << url;
QNetworkRequest request(url);
request.setRawHeader("Authorization", "test");
request.setRawHeader("Authorization", auth.toUtf8());
QSharedPointer<QNetworkReply> reply(m_manager.get(request));
QObject::connect(reply.data(),
&QNetworkReply::sslErrors,
......@@ -80,12 +80,13 @@ std::optional<QByteArray> ServiceConnector::fetchProject(const QString &url)
}
std::optional<QByteArray> ServiceConnector::fetchUserProject(const QString &userHash,
const QString &projectName)
const QString &projectName,
const QString &password)
{
const QString projectUrl = m_serviceUrl + "/qmlprojects/" + userHash + "/" + projectName
+ ".qmlrc";
return fetchResource(projectUrl);
return fetchResource(projectUrl, password);
}
std::optional<QJsonArray> ServiceConnector::fetchUserProjectList(const QString &userHash)
......
......@@ -34,14 +34,16 @@ class ServiceConnector : public QObject
Q_OBJECT
public:
std::optional<QByteArray> fetchProject(const QString &url);
std::optional<QByteArray> fetchUserProject(const QString &userHash, const QString &projectName);
std::optional<QByteArray> fetchUserProject(const QString &userHash,
const QString &projectName,
const QString &password);
std::optional<QJsonArray> fetchUserProjectList(const QString &userHash);
std::optional<QJsonArray> fetchDemoList();
std::optional<QByteArray> fetchDemo(const QString &demoName);
private:
QNetworkAccessManager m_manager;
std::optional<QByteArray> fetchResource(const QString &url);
std::optional<QByteArray> fetchResource(const QString &url, const QString &auth = "");
const QString m_serviceUrl = "https://designviewer.qt.io";
......
......@@ -22,7 +22,7 @@ Item {
id: logs
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
horizontalAlignment: "AlignHCenter"
text: qsTr("Hello World")
text: backend.buildInfo()
}
Item {
......
......@@ -84,10 +84,48 @@ Item {
Layout.preferredHeight: 50
}
TextField {
id: password
property bool showText: false
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
placeholderText: qsTr("Project password")
echoMode: showText ? TextInput.Normal : TextInput.Password
MouseArea {
id: mouseArea
anchors.right: parent.right
height: parent.height
width: height
Image {
id: eyeIcon
anchors.fill: parent
anchors.margins: 15
anchors.leftMargin: 10
anchors.rightMargin: 10
source: "content/images/closed_eye.png"
}
onClicked: {
if(password.showText) {
eyeIcon.source = "content/images/closed_eye.png"
} else {
eyeIcon.source = "content/images/open_eye.png"
}
password.showText = !password.showText;
}
}
}
Button {
id: downloadUserProject
text: qsTr("Run Project")
onClicked: backend.runUserProject(projectList.currentText)
onClicked: {
backend.runUserProject(projectList.displayText, password.text);
}
enabled: false
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
......
ui/content/images/closed_eye.png

25.7 KiB

ui/content/images/open_eye.png

25.8 KiB

......@@ -26,7 +26,7 @@ Rectangle {
Text {
id: qdvLabel
text: qsTr("Qt UI Viewer")
text: qsTr("Qt UI Viewer2")
anchors.top: parent.bottom
font.pixelSize: 12
anchors.topMargin: -22
......@@ -173,12 +173,9 @@ Rectangle {
checked: true
checkable: true
autoExclusive: true
Connections {
target: home
function onClicked(){
stackLayout.currentIndex = 0
}
onClicked: {
stackLayout.currentIndex = 0
drawer.close()
}
}
......@@ -188,12 +185,9 @@ Rectangle {
Layout.fillWidth: true
checkable: true
autoExclusive: true
Connections {
target: examples
function onClicked(){
stackLayout.currentIndex = 1
}
onClicked: {
stackLayout.currentIndex = 1
drawer.close()
}
}
......@@ -203,12 +197,9 @@ Rectangle {
Layout.fillWidth: true
checkable: true
autoExclusive: true
Connections {
target: logs
function onClicked(){
stackLayout.currentIndex = 2
}
onClicked: {
stackLayout.currentIndex = 2
drawer.close()
}
}
......@@ -219,12 +210,9 @@ Rectangle {
checkable: true
autoExclusive: true
visible: true;
Connections {
target: network
function onClicked(){
stackLayout.currentIndex = 3
}
onClicked: {
stackLayout.currentIndex = 3
drawer.close()
}
}
......@@ -234,12 +222,9 @@ Rectangle {
Layout.fillWidth: true
checkable: true
autoExclusive: true
Connections {
target: settings
function onClicked(){
stackLayout.currentIndex = 4
}
onClicked: {
stackLayout.currentIndex = 4
drawer.close()
}
}
......@@ -249,12 +234,9 @@ Rectangle {
Layout.fillWidth: true
checkable: true
autoExclusive: true
Connections {
target: about
function onClicked(){
stackLayout.currentIndex = 5
}
onClicked: {
stackLayout.currentIndex = 5
drawer.close()
}
}
}
......
<RCC>
<qresource prefix="/">
<file>content/images/appicon.png</file>
<file>content/images/closed_eye.png</file>
<file>content/images/open_eye.png</file>
<file>main.qml</file>
<file>HomePage.qml</file>
<file>Logs.qml</file>
......
<RCC>
<qresource>
<file>AboutHeader.qml</file>
<file>content/images/appicon.png</file>
<file>DesignViewer.qmlproject</file>
<file>ExamplesPage.qml</file>
<file>HomePage.qml</file>
<file>imports/DesignViewer/Constants.qml</file>
<file>imports/DesignViewer/DirectoryFontLoader.qml</file>
<file>imports/DesignViewer/EventListModel.qml</file>
<file>imports/DesignViewer/EventListSimulator.qml</file>
<file>imports/DesignViewer/qmldir</file>
<file>Logs.qml</file>
<file>main.qml</file>
<file>Network.qml</file>
<file>qtquickcontrols2.conf</file>
<file>SettingsPage.qml</file>
</qresource>
</RCC>
\ No newline at end of file
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