From 96311304252d0c51f05f8b2820cbef7732560123 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Burak=20Han=C3=A7erli?= <burak.hancerli@qt.io>
Date: Fri, 29 Sep 2023 17:45:46 +0000
Subject: [PATCH] QDS-10801 Switch from widget based UI to QML based UI

---
 CMakeLists.txt                   |   1 +
 design-viewer/src/dv_android.cpp |  85 ++---------------
 design-viewer/src/dv_android.h   |  28 +++---
 design-viewer/src/dv_base.h      |   1 +
 design-viewer/src/main.cpp       |   5 +
 dvicon.png                       | Bin 0 -> 10475 bytes
 main.qml                         | 151 +++++++++++++++++++++++++++++++
 resources.qrc                    |   6 ++
 8 files changed, 188 insertions(+), 89 deletions(-)
 create mode 100644 dvicon.png
 create mode 100644 main.qml
 create mode 100644 resources.qrc

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 35d5743..6c9a182 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,6 +34,7 @@ qt_add_executable(${PROJECT_NAME}
     design-viewer/src/dv_android.cpp design-viewer/src/dv_android.h
     design-viewer/src/dv_wasm.cpp design-viewer/src/dv_wasm.h
     design-viewer/src/dv_base.cpp design-viewer/src/dv_base.h
+    resources.qrc
 )
 
 target_link_libraries(${PROJECT_NAME} PRIVATE
diff --git a/design-viewer/src/dv_android.cpp b/design-viewer/src/dv_android.cpp
index 6fe8c5e..76a8679 100644
--- a/design-viewer/src/dv_android.cpp
+++ b/design-viewer/src/dv_android.cpp
@@ -39,11 +39,9 @@
 
 void DvAndroid::printLog(const QString &log)
 {
-    QDateTime now = QDateTime::currentDateTime();
-    QString time = now.toString("hh:mm:ss");
-    m_logs->setText(m_logs->text() + "\n" + time + " >> " + log);
-
     qDebug() << log;
+    m_logs += log + "\n";
+    emit logsChanged();
 }
 
 void DvAndroid::printWarn(const QString &warn)
@@ -103,50 +101,6 @@ QSharedPointer<QNetworkReply> DvAndroid::fetchResource(const QString &url)
     return reply;
 }
 
-void DvAndroid::setupUi()
-{
-    m_mainWindow.setLayout(m_layout);
-
-    // setup UI layout
-    m_layout->addWidget(m_logo);
-    m_layout->addWidget(m_buildInfo);
-    m_layout->addWidget(m_logs);
-    m_layout->addWidget(m_scrollArea);
-    m_layout->addWidget(m_lineEdit);
-    m_layout->addWidget(m_button);
-
-    // show build info
-    QString buildInfo = "Qt Design Viewer for Android\n" + QCoreApplication::applicationVersion()
-                        + "\n" + "Built with Qt " + QString(QT_VERSION_STR) + "\n"
-                        + "OpenSSL support: " + QVariant(QSslSocket::supportsSsl()).toString();
-    m_buildInfo->setText(buildInfo);
-    m_buildInfo->setAlignment(Qt::AlignHCenter);
-
-    // configure logs area
-    m_logs->setWordWrap(true);
-
-    // configure scrollarea for the logs
-    m_scrollArea->setWidget(m_logs);
-    m_scrollArea->setWidgetResizable(true);
-
-    QObject::connect(m_scrollArea->verticalScrollBar(), &QScrollBar::rangeChanged, this, [&]() {
-        m_scrollArea->verticalScrollBar()->setSliderPosition(
-            m_scrollArea->verticalScrollBar()->maximum());
-    });
-
-    // configure line edit
-    m_lineEdit->setPlaceholderText("Enter project URL here");
-    m_lineEdit->setText(
-        "https://designviewer.qt.io/#17e8907b3b84b8206d45be4f551f4e25/TestTwo.qmlrc");
-
-    // configure the button
-    m_button->setText("Download and run project");
-    QObject::connect(m_button, &QPushButton::clicked, this, &DvAndroid::fetchAndRunProject);
-
-    // start the show
-    m_mainWindow.showMaximized();
-}
-
 void DvAndroid::printSysInfo()
 {
     const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
@@ -159,44 +113,23 @@ void DvAndroid::printSysInfo()
     printLog("-- Screen width: " + QSTRN(screenGeometry.width()));
 }
 
-void DvAndroid::updateLogo()
-{
-    printLog("Fetching logo...");
-    m_logo->setText("Fetching logo...");
-    auto logoReply = fetchResource("https://designviewer.qt.io/qtdesignstudioviewer-256.png");
-
-    if (logoReply->error() != QNetworkReply::NoError) {
-        printErr("Could not fetch logo");
-        m_logo->setText("Could not fetch logo");
-        return;
-    }
-
-    QByteArray data = logoReply->readAll();
-    QPixmap pixmap;
-    pixmap.loadFromData(data);
-    m_logo->setPixmap(pixmap);
-    m_logo->setAlignment(Qt::AlignCenter);
-    printLog("Logo fetched successfully");
-}
-
 bool DvAndroid::initialize()
 {
     printLog("Initializing Qt Design Viewer...");
-    setupUi();
     printSysInfo();
-    updateLogo();
-
+    m_buildInfo = QCoreApplication::applicationVersion() + "\n" + "Qt " + QString(QT_VERSION_STR)
+                  + "\n" + "OpenSSL support: " + QVariant(QSslSocket::supportsSsl()).toString();
+    emit buildInfoChanged();
     printLog("Initialization complete");
     return true;
 }
 
-void DvAndroid::fetchAndRunProject()
+void DvAndroid::downloadAndRun(const QString &url)
 {
     printLog("=========================");
     printLog("Fetching a new project...");
 
-    QString projectUrl = m_lineEdit->text();
-
+    QString projectUrl = url;
     if (projectUrl.startsWith("https://designviewer.qt.io/#")) {
         projectUrl = projectUrl.split("#").at(1);
         projectUrl.prepend("https://designviewer.qt.io/qmlprojects/");
@@ -208,7 +141,7 @@ void DvAndroid::fetchAndRunProject()
         return;
     }
 
-    if (!runProject(reply->readAll(), QFileInfo(m_lineEdit->text()).baseName())) {
+    if (!runProject(reply->readAll(), QFileInfo(url).baseName())) {
         printErr("Could not run project");
         return;
     }
@@ -263,8 +196,6 @@ void DvAndroid::showAppWindow()
     printLog("Initializing and showing the QML app window");
 
     m_quickWindow->show();
-    m_mainWindow.hide();
-    QObject::connect(m_quickWindow.data(), &QQuickWindow::closing, &m_mainWindow, &QWidget::show);
 }
 
 #endif // !defined(Q_OS_WASM)
diff --git a/design-viewer/src/dv_android.h b/design-viewer/src/dv_android.h
index 4889785..4d7be49 100644
--- a/design-viewer/src/dv_android.h
+++ b/design-viewer/src/dv_android.h
@@ -39,19 +39,19 @@
 
 class DvAndroid : public DvBase
 {
+    Q_OBJECT
+    Q_PROPERTY(QString logs READ logs NOTIFY logsChanged)
+    Q_PROPERTY(QString buildInfo READ buildInfo NOTIFY buildInfoChanged)
+
 public:
     bool initialize() override;
+    QString logs() const { return m_logs; }
+    QString buildInfo() const { return m_buildInfo; }
 
 private:
-    // UI components
-    QWidget m_mainWindow;
-    QVBoxLayout *m_layout{new QVBoxLayout};
-    QLabel *m_logo{new QLabel};
-    QLabel *m_buildInfo{new QLabel};
-    QLabel *m_logs{new QLabel};
-    QScrollArea *m_scrollArea{new QScrollArea};
-    QLineEdit *m_lineEdit{new QLineEdit};
-    QPushButton *m_button{new QPushButton};
+    // UI data
+    QString m_logs;
+    QString m_buildInfo;
 
     // Other members
     QNetworkAccessManager m_nam;
@@ -65,12 +65,16 @@ private:
     void showFatalMessageAndDie(const QStringList &message);
     QSharedPointer<QNetworkReply> fetchResource(const QString &url);
 
-    void setupUi();
     void printSysInfo();
-    void updateLogo();
+
+signals:
+    void logsChanged();
+    void buildInfoChanged();
+
+public slots:
+    void downloadAndRun(const QString &url);
 
 private slots:
-    void fetchAndRunProject();
     void orientateWindow(Qt::ScreenOrientation orientation);
 };
 
diff --git a/design-viewer/src/dv_base.h b/design-viewer/src/dv_base.h
index 8f79571..4d9c9c4 100644
--- a/design-viewer/src/dv_base.h
+++ b/design-viewer/src/dv_base.h
@@ -38,6 +38,7 @@
 
 class DvBase : public QObject
 {
+    Q_OBJECT
 public:
     virtual bool initialize() = 0;
 
diff --git a/design-viewer/src/main.cpp b/design-viewer/src/main.cpp
index 8a3ccba..624ad99 100644
--- a/design-viewer/src/main.cpp
+++ b/design-viewer/src/main.cpp
@@ -25,6 +25,7 @@
 
 #include <QApplication>
 #include <QDebug>
+#include <QQmlContext>
 #include <QSurfaceFormat>
 
 #include "dv_android.h"
@@ -50,6 +51,10 @@ int main(int argc, char *argv[])
     QApplication::setApplicationName(QStringLiteral("Qt Design Viewer"));
 
     dv.reset(new DvAndroid);
+    QQuickView view;
+    view.engine()->rootContext()->setContextProperty("backend", dv.data());
+    view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
+    view.show();
 #endif
 
     if (!dv->initialize())
diff --git a/dvicon.png b/dvicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2788115672ea03d9d8e8f828a6124f07868b6f1
GIT binary patch
literal 10475
zcmd5?`9GBJ*S}|BhDI|;M8;T(P?qdWW@?h`N~G)|lqFe5F*9Tdr6RItuk3pvCMvQU
z`#M@Mma-Khp4;d9PdxL>EU&q*>s;qL=Y7umoD*eYbb*UgkP`p^u8X>)O8@`?KSBT`
zJNRbhUEmA=Qsoy(M6-a=r8GqRA*brkFQ~qj&GX5A7XBhh8~6!p|EV!$+|%<PaDf1V
zMEDSQw=0x%Oezvd<A4tV($dmLIK(b`cM-Ycm73)LH3YrMBfqYD^ZL#Ezpv*Per{{e
zrdJ^Fny1w^hE(ruOp2Y?mEegYi9Pv$`Sx`D-P@0wMAfRKrVoFtUQXP0sL8ClcjA+W
za=H2Ie>P=_Hx|(@MK_inbE`c0R~GA5V>!I!GLme_IhGMqSmYM+sMO-aA6u6thoZ12
zRT&+6*M^0YeIqM1HR}a$3EMjPTMkbM=NAl~==-Tq-gSAn!9M8Zho6k=iMreRVTN2|
zA^ytMd%f3HD_tK>c-o_VRLh4(Y_p3Z+(J&5HEtwz?M^a=v9j{3-n<jYF7zie1`)@}
zZbbBoPQ;Z$LdVjYnlSKZn*<DE|HphOjE^FM-jGhiok5YP1S*vS*~<8)(KwkJ%5?6<
zMIH!^`kGBs!(oo_B~dAo(zRo7_KlWU&UzTc*o=7yZj=RG^@GjsS+A`aR0yRAQSIta
zAU${>wC7~ZvJM;XGjaSf1}?@3ZQP8*CQ+FXejM)c5G!12wgyHM3M61iX_-}qn93+N
z>MRSQM&>xO08gX6<~8_TWJItjQ4gso3-xe0^XQc`iYkwS=OW4nIXrl+C70Fk%s0IC
z($;CX$aRXA?cH5x<|bJNpz@(o^AKMb;H$Zawo8)Br|?PASIC4ebXN#ot$vb3#o714
z+7{r)3S#Fhg%onr_G*|rjrUdhwk9Z)zEH=DXbDeoP6PC%@vYB_1D_Ob;!3&sOoS93
zj747N$uo*8?+URV-ums#MO(OEz#D0RE{K&nj@NyzlEsa>)V-BLTT>No#{kJMs02rH
zoUA+Pgzb^zc0#7lEy7Ry*cqa&*+zGXxaY|Wd``peJn9Q=Ddx>-m1#cYz02RUW$TCp
z8b)B$W(^{S1*zh`{5|32u!_SMwLRtT`qpAoAoGPL#)M2LLGf0^3T%Cm_f56+<i-W`
z9!3_gLE!y5ITqo;HQdiew@TP&8wHQ<&bt6}i`S^8#JK(CUd6UvmejSG^@Mg!!BZQf
zI4J?R+D`~fj=9j2=LwsZlFV4nr-NG|jPGpWe!jzEM6W6|PPbBnezIT3;H^dY#igCz
z86>=WxR5vCzrEtIo4q;)(z9|0yKL)M4j3r#B9|$+V|}3#uHt>=JU2^F&sw)G@PpR$
zl}71<xryifEPtAFXV+F0+pKgNPP}m!v-61$xpRB}-)`a$i+CmK*K8Bmx-!@vWn4jm
z;$dE3LFGf{;UoPzO3|D=lUpUw&qEz3c%FPI4C)3x_f+D2V4M=DQ=@E}V+n80S+bYr
zNtrvTSc$^5y?IuzL7A-5FJjz(`g|2TCoiq5HY>;8WovME*X0`k$wgEaN+f`H^n6YA
zQkt#jC!9d%*F3}r0>Pc+CVt#QNa1B_ql>r~x$`y+*9#hmrMdTklQI`0RUBw)d%9k`
zrUq5L9h{(rgU9QWX?C<V7i(C{4_(WTNYfrIv}Y=T#-Raj<1iZeDh}KFYlrJXS*h}+
z&RZCGGPb9jhwL<WL&(%^))<y=%z!l=LrUS7%VTxh^?1r+rSjKQ39}+?W<noRLqRXb
z(kP>m;9Y!I$+|a*2A#X7PtXMu38UfmmD|@DDpA0zyRbvnkEYP2x(X=heUnH*L|I8j
zB4B~3jk}TdI$fSf7=#5G;Bc|zI4Sc439y{f|0y((H=>!}6CcnrUv_FxV+)vMucwVZ
z_fPIt4|tS02fWCw8=3y(>Q!rc`ghD}?A?}|shj#?jf->r<#~v?;k~i#*s}{aZtvyS
zyno=QufJt`B<t=O4W|1?Jy#XXQW`Qyc9gxL8A}bZc)m_Z|9l2Lbn_v8l#*-l<sjcH
z)$ghNIIm~e{-bM<XBYX`ic9}#?|v{}RO@gq8UJLn>B!X{d>;~2yO+W&yaBr<{#Ei{
zTLph@$SEJp$XFzoWXHGNEfwr0F&Wef&|}%F*m?Du4my%k=lj+(?A1`_i8jD4_b$I&
z#g8#`g+fN5vlDycw{4l`z^SE~-AT=cm8x}L8o&0x=i9SEzu$26$;v!I0FPUsgeo$d
zDRIo?$-8si+m@1%9^%J&fGl4??7>P#k<;GK?L0YOTKZ}JyCEeN=C>1eXXuI)nUdu9
zingF6B%syt^$ThyPFgD3l;~N=_kBAJtEH@Q2a<W>ki+fWzxcw%ILq`w4s7VXB#R*9
z)aQR^=oxg&?sH)uv+r%9DZj-mM<aQlgq!H==h=)a)+IFwMYvhoNet3Od{7q(%>Dkc
zv7K->hu@u4$d-C0<jHnWv*{JfvB-po?&;mP)kpuDzP1SGfn-8Xhf$o&OpIeWzu-Uj
zrO&5am$>WL+P<FoX>P-^oZ}YT#H0=K;Hmeqn<L@)@hOXEQ5m{pI*Zyjk8E@+`%de;
z8jXAkA$S@Qfj<HywksMx_+M$u4n?atC_)J$Tuix!RuzY-5&gG~8Bw-{&;BG#*H_im
zh7=zz2|hkh&Jzd#58jvF2_^9J#e25(x&1ze2?Ie`JPJa&*0>k8de)#{$>9aPqP8)y
zD(KNg&Dem&*}LPv`3>GWlAWZu0YSxqR0_^04Je$uVJX{ijX#nz+}1~k&oM^N1IYaI
zZ@Hpe>THWl^Au5kx#NMp)zs%7GFy6ehSe#EJz9ib{b=yIB<p#CE)p=pwCJOm8T>`V
z$+-jArZj906sXh%w2z&ySKRStocZ}Hd$eFrS2Z>X?+)4MK7FHYqi;ehP5@xXVV+_s
z2_7g@qD2hnDRl_(H2^5{uUh#8)O5!p-q)mV2MMh1a+Wb7p?#sMO;LdZZu9(ohT>mf
zluNNm4tY3C2A0`)xza(%Jf|zuO4GdswMo)D=1X3?HN=SI^Pc>%`}cs#&u2ep=+)wq
zZ$r`>=>`$E+x5P~2m<if7Anq$3_Q1)Il|toYrz~TW659g<p%^{zt*?w>vEc&U%O^2
z9{P~ng_x2uHj!+;+-E$v<b3^LhU2W9^&b?F)Hua<{l>Vg4BdG4K;mlc``zy4M?jj*
zb61kp%Lfm%uuErxuYGYPxdJAY{R~-l=s3=$i3_^9ah7FV8CqcHRjdmzj~thKp1?$|
zi2s{%XmCDh8criEG<*8LvoSCCYKQzR*^}S7T`ntg=QOZBSbp--q*fd!kj!`b0rfEp
zqQmBt;lw(EFFw>}7V%^pU``s9Y?T*&|Ao)57-E*SCG5n>Bjdvr%vJRbBhG&R>MXDO
z-09d2YZOrR;Dq6k#N;n9AfP2X=_E#Jl@GqW$EQ~^o_^(i@QjlMuzcqgOPkzjH?^oG
z1_wllhnUWm7k^AwSfkk8pUwEZOF=HsZ5X-Z*Ce=s@+7x1oYXu5c{>M@d!5TcDD%AE
z*V(l%CK0?7*$9fUzF{wif*?kLu#O`gt_Q!p^_E*3fOt(&QP-n;xC2AjQ(NMH`@9PS
zA`#Gh7PVI8>$f7riPL}Dt3@1SrWw9ygQAg>UZMc)n%l!}w+XkeG~eRq$*0ErTF?Jg
zI<}mfXN*euCiZYddWq!|1@t6+Jlk}XotT3_0w`Fo5+-vxJW(WA9i0&`dH^t3@v)4$
zk_K#Gx_noHg?*2vH#(?w*R?NiJvR3aS^6X|aA=*izFV<{pp15J>W${+tpb@!P{QeL
z-12EW0bojM&kRn@5i;p^d^_rAa+Nvx5@ci{r<6b1a)!kVT{*IX-RKN;6W=;eAV7yV
z^dA~4uK$o0QGQA};Q)|~Ka6I_QkvLNUn-Aum@jE?`bn_ExlJKqbyFfcPtvsRijJ!e
z0+{cY7<nc4<~aeiFJFSzfM}P^_Zb%!{s^OYX6TP^Zu%X?s{5MHGgu%Baa``?K$gP?
zI2O;dIh9A04%9uCJ`97(XRiZ$cv;7Z3H#L_nTg4VBd+||#C`0{j7v#D$oQ}L9$Q^q
zqaU&P6Y%O)pb)pJ(As>%m9gCSu~MP{iqP}|8(GX7&j#E(aO3qYzwD1RyIcrTNnpn!
z_O^K?6eT_|kM`u$ftU9m;@a-@2>UD%;E9dd4N%?~D&jmrGRbF5?4(WKb$jtRqZLN^
zoDIPpglEmeohl;AtAZZORLoBuPGYAGu;JwO(R%$Zm({YYG-Tp!iiBjIs_&F%fF`n>
zxWH4$J3CPEZ1!#j>28II(;Pwusu{dG)7LpZwQ=s><kP=C??^yE_^TN(Szdteu!tko
z=MwI%Ylaa}$VV&!=DMWRikaW{Z(_c8E*7}t-WD*$Ce7X?FPB9pOk71U@loN8_4RUx
z8pkWOOTS5K+C9p+uxUg318Nlv4!I4{oB@5I-b>-q6{|=p60@ib5Y5P$&?aVr=;*oM
zn0ulEIu7z#sW%(?`|p!`z6tLpOl+Qh`!+T*#G*d*;@?}kKRv}q_0d1WCbsHf1hosI
z+wLULIOC6;ZMuO`yNLc$)lN;{<M^SBquKp??;>#Yv>{pyVh4qOR1}qVIbcf9)GFzN
zS#fl|v2Eg>7}xPxOW%DN?D;oX1AkX*4=~xN;lCInWU2_bI74X^M(8R)F<hRzneAYX
zi!9=eFBln|Ea$N{i?hjdmBMG=M7ptAkS29nY{{z4XVt_yf;1Zb91wXYU9fdu<No5k
zU^{%@o;%Apza2(VWNtdGV@hd6-XK#dQ^jHHkGft+2!k$iC>laNPc|uc)|@@3%Z4-2
ziO;y*{jeXKDmgy`p~YAXycFvW(hv^WT2;T{Rv*%OI(BYGMa*-7$5T8jyS=vG%##Pg
zw9HH9#cYC?GZic_hKdmG!N3JkDu+pINZMQhK%^Xo0g{@WVp%k24Bz?(!_OAuIS7yN
zuu+5U4+E@qF2Hc|rJ%NPes;F?_r)Z;msi%6viN<W91si}O;Lr&JSS8J1?*&QPty&x
zu5*HJN{Hf=?F)UXJXU9G&cn^u6uJ6LSYTYg;~RvUGIn2W%F|zV1PPbBzbm{k^oc*g
zD4#o!5vtd`IrQRpa@Fuu(fL#swPhcfN*JM6G4Y<-NButhYpI3+skBVTqCa1sC(jd?
zF_ZeYx%J-k3T4r_xBQ3{gmmEVzgdQl^0>2$c5B}jvxf%caR(BZGf)#2@z-#$$5BTz
z4h=Bp^1&#EJcBRjv9B#3yRUhcpnyjjeWDQ(vGIiylPONe>@m!*Ps6uZ#(uN{oTQwM
z5H}(y;P+N|Lvi)tY4JmogQF6mWsa)tdWCk&ERFXJ=h}8m+O_XWSr#nnJpdV+`N9WR
z&~ry^EO7DASm1j6sv4YF+5o_(3z%_t%)BC?z^~^Cqzh~;FS)YT%m2>yCO%QZ>{M)^
zJOI0h=A}Wgu;Y*AbHBdO`F;^y8uvN78;A=&C3A<N6ORNsEm81AT9Yr?t|azq**9eM
zfpAwpQTRHp=K|Yt7EuDwst?5Q@;Uy<zq0h<VZYE}Za$`zRLSzJcU|H41i7KR_uX&X
zewC|YxRUZ&bZsy&{SM{o+F$;%WE=`0pQcd@)+r@M6kr$zG(~CL#HqFYEMU+#a`U)x
zO$R|7;(IkBGRYUi`7(4hd^*Tpx@W2UX}H{qcIm6vOUJy_V&~xSkyGrH<(CPqt|U2-
zyaJh4N<bk2V?Z`3W9U|Iv~)k5)+n72L;+Ai6b9bQg3t&M0-+8iZg0Y0EOpKdXx7c|
zn(_We6Vbfi_4^V-+sW9c_rX=V^8VVOW8b_hcS4o>ypcG0WM3sGliX-TTxsmpS8KY}
zB4_@2ox*CfDPxACIK===e`jbxf!*$C+F}rLHUx@M<6vJ_FOAI2t3Rh=>p9sCu9;)h
zRHq8@6lJffip)2{i2^=2FF5SiSR@j-7ehO6CY8o~q#>O9E|8+)*{M=}sG9%e2-)Pw
zs=C)I|Mlz-wIdf=9?@Q<K7P_QV`H8=%u>pl&>%+rdG<E@8PV%N@2{fs9(}MV&{<$Z
zIIj$>R<F|`&4AUIuTu6H$`ZpalZunZ6ENeJCC_|R(PymQp0_loVR{IqK4ZjOk2~|J
zzGTY5ML)}n&n{+oX^u8-zi-1oKPrcBJ=(oz1d2^AFKo$H$<hL(_KvE(a~31uN{yBS
zM1g~QKH<V=VVI+`0MWqAOH4(&w!-En%L7~Ac<)BXsdIRg*Hi8gqipNo%>#>muUy;w
zb}}l3ryWe{-@+!>?RIvmtfm-&SGgY>&CQnc)Uc>lKu?D!W;l%aqc}VM*yD)aEF!3Z
z_H_aq#Yz?JENAWcu3t$}S}n&%d6^oWH+7E9vgHy3zr4|$tu9k@*HC;E0--&=5Y1%I
znrhb@ujW1mCFtiRpTle>Va<MOgbP35+%yFUqR6g!g4d@*@FxJ%+D%#opY+zteLOdh
zjFDw;Zqo^~jq-c8I$<F0rgDGf_^F%Czo<6_6>P{9qvkqA_qlDEMPqT5-=42tT_J;4
zi6WSs!6J7qqNV+XvX8blsR)erGNh4@4p9ivoCgJS5dMP;ViTRA{)vSLeku0LDJ#DV
zEHywtE5}~fbQ!<t<BoW;Iw33Ls`4V__;lC75^qECYt+oI^1GVhAUEOGh@HD2Wa<E1
zrQ(v-nHPa34z*%x-Q*$6jun#DT7Xl**B*d?HVAvB@)gmpdj6zxmH!$*^wQ6Do=<_6
zu6uW`G1BLoEA1sDaZM+iJ=jAR4~mWy@h%?(ribOj`)%Z8xUD7Q5CGpbg^wf}!Apo6
zLK*Vyi6MG*9fJE0EC_C1Vz>z0t0(J^TZcQd=)ZrI`;?%rV4C(MwKT)+bN;G7B2c(_
zA1|vbbSq_DF_RC$PXRrOn?c-oQ1mpy8K8xY%FqDwKQSm!@^9y=ojqnJi^i<Q!cAFJ
zPT;Kv_TKKqqh-)skc;D5QZ~{I=G!|E<nqX!t=ZM+{>2DWqSWLiMopsow6{iT`S%w(
zN-*Ne@f%;OwL6uLdWigeTSzh!GPMDQY1Bp*G2y42bjeIG?SulHeo+|dkVRuWVbQIB
z*XjAM+4XJ&xyvaJOle&`$W5rX2)7rAcMHh16KGSC4)FLgYh@Ji=A-=MAK(^Hx;EL+
zUpWIu7VLezP7nl`nR>mYZ5&W|lj~+!lW~+hvg;Fs2tob)vUnW4-XGUD#;n`~1J~?U
zX6_#hkMl7lJ}}4dp_*v+x@g+=yZTQ{0kuO-oh+XQC*yBIzz2UGRY)YsNc?XC7R;s|
z7QJvNCNSNF%A^4xXga@Fj1YJ0AdR-p^k4(LC$z3Mta$|_+SmVQq{F4rHw4RyPe}*-
z)l2q1!rHob5>L=wEtb4{SHl`jsYzVR6+@oyWkd#7?R$VwUNQ`$_K0(QfaCQafj6iR
zJKob-P$(Pw>?vtnWF#k;!@2n1^h=zdA+GdUD#&ycg3*r=x^=6jPVnr*NKR>|S^ih}
zxXx>33GG{lJ<c>K$GXI07k}J~4^u^-Hx~bUMKTTpnBu&I`6Bhvum2p)j|uvkkbIgQ
zr{)eox!9$F?{5RWf^>u~=o|hvrH>~}MO&I@MRU&o4pA2oF|@8<T;%S08=aT{O&?>h
zLb}ph(!!aY=l10v;E-Uaz;Tf@qA~#NewbEDhSIFK;E9|>yQkRkiOf1PRW!DB-u_17
z%azX14JJp~u+uT$5$mc^X*sSH^`(vF-z&d5etzINit-N9Nb?7D$4n%=1x+2(K$f^4
zs&$>oA8$J!q^ZazX%OwrD1cfBOHmVzQM0h?#r1%;W6GjWaFKO=*D?*pQkTo07O~?>
z-v!G5i}q~sI4Mn`j}KgLHh#qKsb1i7beYeoKL2f+oqX#OYkehSg$uAJNr3j#y-qj<
zxR@(oQJh5PO*4~*4YlV%>W{5!a|CJ3`h#$D79G#IuOyQL!OuVNIZFx`X^5=-oK2UN
zIr8UEzCr~8N&9#mEd}cBad6k`B`ZcG8Dr-jdLdxJ1Wc4NSX2_=(k_O>Kw#>9q4N!&
zWsJ`#7{>ziV|Zj%Hk1##p|mJE&>4DIJYW5q+iL_d<HX+d(X-{nypDe|?9^flr~o5$
zVEHg4!(!n={7P9u3WL??uJP!{kr=Hp)04HnQu~Kc$#MjGu46##M=O%wJacdX3*yGv
z>6a$7=2U-&ekeNs8AY(WvzGazU<ePE{cQgkDV)>Q&km2P)PU^%I{A*<N$XqZ>DWkf
z(VHq8=OnC(PI?RWwy!sVC1Es>9?1@%ksW<71^1SiN#1zlhwW^K!-)`N76W!ajR2vL
zK>R<sGwAi|Ray$d_ixOGqh;Hb$Ij()gTJb)vI!!5%;=9A;y24H4Fdc+?r7WxW&z9~
zi3D2b#C`-{N^(;nVhH58-q~Zh^Fhb7Z6U;T$UZvIG>C8j3aW*gDX_Ek>EGw0CzS{C
z5qoZvQx#6f<T@<vZV4&~!Y7WuKVU1#n=b5sFn6Hyj?(j;kDnT>fF_}ctbFc&#k^q2
zB#>wV12D8w^f_%lxajjlPXHRa&YaX~$axz`$!@D3i{*ybn7gt@E-^lxJ3f}I6JvyS
zmc1&xQVg6Dw>FBfm!J?@IpJ54EkC&)&&O`-ZYpI>f%F2B38NxdkZze~!TUDmyUjO(
zuED76Fg!@z=7<;$ik&C6e@=OD<<jLMqf+NtqH)b(d{4pk4$RXur(;N}&==)L_q=2N
zxP;bMx>=uf{hgs|fW|JisRCi1hjx4ZI=y5>g0vcBop>3g0|LYB)J>Hvc1o*ln2DL0
zT`G2b+egIJ1G^qB{eHqayw{YT`f)1oUE%lFm$(w_#oxG+D%La2+997R5Yya0%mZDk
z*hwTdciX+E+giyfW0B=K2rxfWR10>(!{HQy7ugO@kw=2?C;)#~Kwu-(&wkn+*Gg)1
zzS}>Tb-J1;|2_6G-qw7z4-qY!&)wM<I(WnRDq8eG#1nbxxleubXmmrfIuK^@5M)o4
zVbsU}@h|EFQ49=L!hi+g3VJtwY`(NdA^Sny7oNE^u2tLMd|@snBg)$CFXIR!1wqF2
zvot5yoQ`!y7{>~nEw3wd{5pQ@Pae0gDSgMc?yOqTi(kto4$T~ERuejh(y+^59s#3F
zrc#;~)|<`%phXrLdD)uVp76j{9>wFq63Y6e%WqN;&&OifPReY3KHY!{kNYYoV~LV%
zewgTH7bLjy*tptcG}0wW$1W_C?YibWE)Su1Z)4|F@E8y~1psp#@;JVr*I(==9SQW*
zdNTD5qv;uPQ{_Xwr_S9^vztg4e-BoqOn+R_JUC)y&hxf^y~Ko6sTpSW>b_A+5VZ1v
z-KKAd+TBSX0at{N4j4wkPCx*-Gy*X8b9{IaMT>dA!|(p<*0|hq3WAUMuB;+A?};k<
zcyOieu#$ro#$d})eW?6tp=il4_U!ylUq|Z({JJ=iVoJBs4a&L@Z@W#-jvI?Co`=&$
zBUd4~Q^<NFbjMiak$>Y*Tx|;CBQxWqRpZ3qrOOp52<2^qW%opTA*s0)5Wtid4vd}C
zWi(!O3RnZ(6o))a@8dp7>(hy^u-Og!CUI@q7n)r__%D24Fr{8h!(~rN5P{{8SFYbu
zPvn6VC>vU3R4Q_Y!?R$#FWc!@87=^6BeW_jV_E8vUnH8d@I{IJv$o6j+cGE&pg$D8
zFuc@#@UybBXiW{blZ&_>oMKeiBLN|rnK3y5!@q2PYk)uZ(aq_2dO6RwzTwmsxvIyt
zC4faAa7r%qW%d{)Cg6~IgSSQek*w*Ne@D|ujJ{CI=%F{~TOt-_^DS6OiRN;j2i-}w
z3>X3js`yIN%9}Y+CJ!82$!!h8QBn{?<{q8qw<q08tLCz@bMut#LMT(<PCMQS-}XH+
z8E+e@85YJH>#T|{%;VlR2-MC?yIOgh5zVS%j@$_~O*JKY?SuMUhuK{K`q`9Pr$Lnm
zHY?kg!(T5ATTHpf))lt6C5qDQnkU5<hkhh)RTq*f4t|?bNY#m{Y4>6-h<r@bOxo;q
zxKM(sTF(@;ic|@{Ofe<S@NG^sJT=#j2!uf8_6z1soN#&`;wR8EHI$nNcBWH`#>+ns
zmh*hG4u8NR4n={bLD7{V4y-%Ab)}pKPQNg9yBq|Q?%2d8!?4;C6c=GRKgRqHmjA)8
zV>SjQc$}ED7g=NCu}T)muA#&PfPi5OjR`LCf-!9Xibx$Q+QRLlhCx!B5p`{J>YC&G
zexJRl%Zr0C)n984k3@17pO}hwXG8dx7m^IQj7n3|UF`pkZw3d**bVAbzKh+QR!tGE
zSL_deqIgGuBa1fs<2A2i8#|yTl3<g2;534GlZay)qsJk3lzdgR$E#k`J39>*LVW5A
zzZcRkT|SAQgEy>ZRv&&jz1(|hLdju$KcIu`F!NsBQO4}2Saw52ck%fQp$o?12a^@#
zx@4N)-2r#;W-Kt}`{v?geW7oGOv{7-`Q>sWyMv)IyB-jn^D9?{&59tqTI2@rdf?Li
zYRBe-UVmlA+x5h<pw?-2%^tM@*H_eS6B9_yncF$)Dt?DrPAM-znTkOkTAa_5SL+oE
z2ZCg$j^(%n<xKymoS!JpQ5NW$(2<ocFv4*I@5+%#QWN3PIxc(9(F0i2x<_-L^zZMh
z4qMVKT+;q>@T|<Q*}MFQB>gpFTPxa2uXUHD8;EPTia&Q(jk$G;I~|{bKp4yvkLL&s
zvMF7MWz3tqgP6^HG`cjNMmjBMT0AVRTGYi{PKP!!U~S;}O!i~^IM5{bVxNl;LaA7I
z_Vi`NNT*{U`up--r!?<5-m+{v7^(p=7E;i_6OhakzBQkX3vaP;$>k2ry+8+X-FM$F
z=(~}DWm?nNI(Uqxib4qu{MC1NBxP*MoN(=WF$8(^8T!UT_2G}QGG%rB>!l4US*B!p
zhnd-853E`==jivm0pYLuLZ)JX&yCmWkbM?Wx37gavfMu;@WXfJ)MQLc>LRX3r`B+9
z8wO4F4rT?gAZVl@Dxhtk6INW1Y4$DJRhdj@`@x+KrowOvACgwY>xj}d0EP|GJzM(D
zf0l0xK2gO7WVK6OZ`Z3_w@W0FnK`inX;>Wc=YteB4-afDlz#5_Sq$~8nY>v*8o>dW
z1KaRqJAg_;P)7EB;!o)3VPX4Ow6kT@5u_KAg;T4qu96~Kww(!GZ<?E-PN+Een3cl)
z4(;l_F#FyZh&zr4WG2*98=R-^F|uBs!|1{(KMkrpI(XRAa}g^G@HRMrM>@+{HG6c-
zVdl!82Kdt0Zq-~nC9|T47ue1y2?Oz6h_9cE{>#zh+CO_e1hpnsiVNs_9lB;Qgu|fO
z={bltcFF;hCC`6fucsS}Kh#BszuzkRQO@H@$jn0+dLNIj3zNXYk*x>3V50EuN5c90
z@gH#xsm4xJ-Xp{*c<EhIJ98M4-)Y;W=lG{mJ*Y=)**bh6DCXq&wL?{fq{jaBOk!Ho
z&rVo{%GZC!{`}r+P1a<L2z)-$d)8`cq)Zs2%MLUgp%cu=O%{^6K7iGi_8S%a_uGGZ
zYV;(!l0Z(@IZ!^b!YI2Qy|}38!^>AV;u~pw<*%!#D*E0VUOO|BnUOX57`Q3bmyA;Y
zt2;gTI1S>brXilb6${U?&!fgkA3cf&25P_(5TW!o!y}~*)s56g9}lU&I@bxySb(c#
zr6L+<`5B54LU~{gg3Fe?+;JIGtB>Y^09X6R$V>s*0jp2RF-i2Flot?fqx|hVYj)o|
zx>2B~Qkd(OKT{Ao?k!-_%+U~tF-yy|BW+oc)95dKtj%yDz*k!41yST{u+=%&A^rOW
z+<xwe-%k9V-@4@Hc|8016G<FbEADGwN0t1ZDVglZ>$0W)HAra}{BCdqT_xP+Q8=O;
z$6y7M*aqxX?8oT5w{KD1)xE6Bz~)SI)s0HSZL=}tX+9ylaH#t~o66?bOX{eFPITEX
zzc<x~xqb=<AE<VYaC_r_)b34<h~1l}-O<{bo)pj!xCerw)MCO+>F8Bx(_vJ7A#bZ{
ztkfFI=g2&KzXs>eQ$&?u5gU$zRqJTJWF)3_NXNhiQyKq0wpBBB?qetHL|<sc!a-@V
zXUxvi(P0#Qj9FqytW>aNlvX~&$y1zMR!CaEs5CViS+3s5NtrZI=ElWUfLnCJOu;6c
zAv&Ey3Xk#Eutp-W#c~;I7oY?LO;CkMU=h6sIKHs?gV7-cLC-}z)o9$m*0`^}&=(9?
z)L5iq4gylm{lhny4KV%<x$vvG9zpbSC%y2**5cEQSk!(Hebcm2K&LE`=}X3#2|d~G
z<CA-I?p0EEx<p_UBxVzwK1l<+{*X%U1|u}j$E_>Cy3+$^c9;k;j>o;l51a-VRB;ef
z50M1|h;dTxEvLYize-jjPFHr;0x;n%ev_pR1;-D}Bz3D*vc@dJV|lu_!~sn8djkVA
z0#3KUBD`P6$5c|+WLA}(Qi#h`5d(4Mw)mOnO<g6>Ozq1>8E>Nsd3D#m#O;qB_*hB?
zfY_F13n85J+Px+S|4Ij^X1)hFCAqniR#?PKYM=%ovM8z}K<!`=zf^H&=zmdh=u-<3
z1(X&%p|BDnvvhyDq5ci887Su!a-3P0$N|6xV<PlqG_q|<NA}OvXWzX+ja4CN&(Mya
zaJuE|;Q22O>#R%SrTzr)XoLs=<O&$=S`?DzXl>s2$mR$coc1VM6M_=d_OrNxSY3D0
zFYuA29ch5Q?CfbMoe+V`++U?_<xA=CH^XORTYNx&FN}hKx0y)J5#31;U)s6^IG+->
z_688>ID{N#BWALQuTRRnOhJHD;>5R|2SCs5I1Us$IRl(X0Y&Ah<c>~of35*a56-FR
zeq5(`U~|5dKaIZ|%m<uHatnQN40X>K4JAA2s-iEI$0j}PDgiQ2sfAc`K~)G$OENfM
zqKBqkL|+=*;&TOhQjVcWxrqPfHRv__OF#JlK42%s=s1F8zr1e(91VqGsoI>tgBejI
zc*YXcF<tb-1j$*8D{>JhoDuNx|IPSFb<3Rd4i*Q(+zUiev{$^Kv>w<<ck#nAQ%_T;
z1OYK3xHH&WHx_!5I)wq6libv2W~A`o#pfcxp{egX&aX?re!tlNCSbnw>PXDiz?;?#
ys1#>E0)YjY(9(@laVUFO)V6i;|M8UG$nU-IpsM@|Eu&ii__}!Bh*W&mj`n}S1=8~X

literal 0
HcmV?d00001

diff --git a/main.qml b/main.qml
new file mode 100644
index 0000000..ff5d166
--- /dev/null
+++ b/main.qml
@@ -0,0 +1,151 @@
+
+
+/*
+This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
+It is supposed to be strictly declarative and only uses a subset of QML. If you edit
+this file manually, you might introduce QML code that is not supported by Qt Design Studio.
+Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
+*/
+import QtQuick 6.4
+import QtQuick.Controls 6.4
+import QtQuick.Controls.Material
+import QtQuick.Layouts
+
+Rectangle {
+    id: root
+    width: 1024
+    height: 768
+
+    color: "#EAEAEA"
+
+    Material.theme: Material.Light
+    Material.accent: Material.Blue
+    Material.primary: Material.Blue
+
+    ColumnLayout {
+        id: bar
+        y: 408
+        anchors.bottom: column.top
+        anchors.bottomMargin: 24
+        anchors.horizontalCenter: parent.horizontalCenter
+        ProgressBar {
+            id: progressBar
+            Layout.minimumWidth: 380
+            to: 100
+
+            value: 50
+        }
+    }
+
+    ColumnLayout {
+        id: column
+        y: 549
+        height: 113
+        anchors.left: parent.left
+        anchors.right: parent.right
+        anchors.bottom: parent.bottom
+        anchors.bottomMargin: 12
+        anchors.rightMargin: 22
+        anchors.leftMargin: 22
+        TextField {
+            id: urlTextField
+            horizontalAlignment: Text.AlignHCenter
+            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+            Layout.fillWidth: true
+            placeholderText: qsTr("Enter URL")
+        }
+
+        Button {
+            id: downloadButton
+            text: qsTr("Download and Run")
+            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+            onClicked: backend.downloadAndRun(urlTextField.text)
+        }
+    }
+
+    Item {
+        id: header
+        width: 351
+        height: 309
+        anchors.top: parent.top
+        anchors.topMargin: 12
+        anchors.horizontalCenter: parent.horizontalCenter
+
+        Image {
+            id: qdsicon
+            x: 47
+            y: -23
+            source: "dvicon.png"
+            fillMode: Image.PreserveAspectFit
+        }
+
+        ColumnLayout {
+            anchors.top: qdsicon.bottom
+            anchors.horizontalCenterOffset: -1
+            anchors.topMargin: -20
+            anchors.horizontalCenter: parent.horizontalCenter
+            Label {
+                id: label
+                text: qsTr("Android Design Viewer")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+            }
+
+            Label {
+                id: label1
+                text: qsTr("Technology Preview")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+            }
+
+            Label {
+                id: label2
+                text: backend.buildInfo
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+                horizontalAlignment: "AlignHCenter"
+            }
+        }
+    }
+
+    Rectangle {
+        id: log
+        visible: root.height > 620
+        color: "#ececec"
+        anchors.left: parent.left
+        anchors.right: parent.right
+        anchors.top: header.bottom
+        anchors.bottom: bar.top
+        anchors.topMargin: 0
+        anchors.bottomMargin: 24
+        anchors.leftMargin: 22
+
+        Label {
+            id: label3
+            visible: false
+            text: qsTr("Log")
+            anchors.top: parent.top
+            anchors.topMargin: 12
+            anchors.horizontalCenter: parent.horizontalCenter
+            font.bold: true
+        }
+
+        ScrollView {
+            id: scrollArea
+            anchors.left: parent.left
+            anchors.right: parent.right
+            anchors.top: label3.bottom
+            anchors.bottom: parent.bottom
+            anchors.rightMargin: 2
+
+            TextArea {
+                id: logTextArea
+                text: backend.logs
+                rightInset: 20
+
+                readOnly: true
+                clip: false
+                anchors.topMargin: 5
+                placeholderText: qsTr("Application Logs")
+                width: scrollArea.width
+            }
+        }
+    }
+}
diff --git a/resources.qrc b/resources.qrc
new file mode 100644
index 0000000..3876789
--- /dev/null
+++ b/resources.qrc
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/">
+        <file>main.qml</file>
+        <file>dvicon.png</file>
+    </qresource>
+</RCC>
-- 
GitLab