Add broken Qt sample

This commit is contained in:
Caelan Sayler
2024-10-20 00:59:36 +01:00
committed by Caelan
parent c73811033e
commit 1de333c616
10 changed files with 585 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
cmake_minimum_required(VERSION 3.21)
project(VelopackQtSample VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Disable C and C++ compiler extensions.
# C/CXX_EXTENSIONS are ON by default to allow the compilers to use extended
# variants of the C/CXX language.
# However, this could expose cross-platform bugs in user code or in the headers
# of third-party dependencies and thus it is strongly suggested to turn
# extensions off.
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 REQUIRED COMPONENTS Quick)
qt_add_executable(appVelopackQtSample
main.cpp
constants.h
Velopack.hpp
Velopack.cpp
autoupdater.h
autoupdater.cpp
)
qt_add_qml_module(appVelopackQtSample
URI VelopackQtSample
VERSION 1.0
QML_FILES Main.qml
)
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appVelopackQtSample PROPERTIES
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appVelopackQtSample
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_link_libraries(appVelopackQtSample
PRIVATE Qt6::Quick
)
include(GNUInstallDirs)
install(TARGETS appVelopackQtSample
BUNDLE DESTINATION .
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
if (APPLE)
# Copy macOS updater/installer binary that needs to be next to our binary
install(FILES ${PROJECT_SOURCE_DIR}/platforms/macos/VfusionMac DESTINATION ${CMAKE_INSTALL_BINDIR})
elseif(WIN32)
# Copy Windows updater/installer binary that needs to be next to our binary
install(FILES ${PROJECT_SOURCE_DIR}/platforms/windows/Vfusion.exe DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
qt_generate_deploy_qml_app_script(
TARGET appVelopackQtSample
OUTPUT_SCRIPT deploy_script
)
install(SCRIPT ${deploy_script})

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Bob Jelica
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,117 @@
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Dialogs
import VelopackQt 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("Velopack Qt c++ example")
Connections {
target: AutoUpdater
// User checked for updates, but there were none, show text about it
function onNoNewUpdatesAvailable() {
noNewUpdatesTxt.visible = true
}
// There's a new version, hide the text about no new version available
function onNewVersionChanged() {
noNewUpdatesTxt.visible = false
}
function onUpdatingFailed(errorMsg) {
errDialog.text = errorMsg
errDialog.open()
}
}
Column {
anchors.fill: parent
anchors.topMargin: 40
spacing: 10
Text {
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
text: "Welcome to Velopack Qt C++ Sample App."
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
text: "Current version: %1".arg(AutoUpdater.currentVersion).arg(AutoUpdater.updateUrl())
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
font.pixelSize: 18
color: "red"
text: "New update available! v%1 ".arg(AutoUpdater.newVersion)
visible: AutoUpdater.newVersion !== ""
}
Text {
id: noNewUpdatesTxt
anchors.horizontalCenter: parent.horizontalCenter
font.bold: true
font.pixelSize: 18
color: "crimson"
text: "No new updates right now..."
visible: false
}
Button {
width: 400
height: 100
anchors.horizontalCenter: parent.horizontalCenter
text: "Check for updates"
onClicked: {
AutoUpdater.checkForUpdates()
}
}
Button {
width: 400
height: 100
anchors.horizontalCenter: parent.horizontalCenter
text: "Download update"
enabled: AutoUpdater.newVersion !== ""
&& !AutoUpdater.updateReadyToInstall
onClicked: {
AutoUpdater.downloadLatestUpdate()
}
}
Button {
width: 400
height: 100
anchors.horizontalCenter: parent.horizontalCenter
text: "Apply update and restart"
enabled: AutoUpdater.updateReadyToInstall
onClicked: {
AutoUpdater.applyUpdateAndRestart()
}
}
}
Text {
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
anchors.horizontalCenter: parent.horizontalCenter
font.bold: false
font.italic: true
font.pixelSize: 12
text: "Updates URL: %1".arg(AutoUpdater.updateUrl())
}
MessageDialog {
id: errDialog
buttons: MessageDialog.Ok
}
}

View File

@@ -0,0 +1 @@
# This sample is outdated and non-functional

View File

@@ -0,0 +1,141 @@
#include "autoupdater.h"
#include <QString>
#include <QtDebug>
#include "constants.h"
auto kUpdateUrl = UPDATE_URL;
AutoUpdater::AutoUpdater(QObject *parent) : QObject(parent) {
try {
// Init Velopack auto-updater
manager.setUrlOrPath(kUpdateUrl);
QString currentVersion =
QString::fromStdString(manager.getCurrentVersion());
qInfo() << "Current version: " << currentVersion;
setCurrentVersion(currentVersion);
} catch (const std::exception &err) {
qInfo() << "Error initating auto-updater, msg: " << err.what();
}
// Do a check on startup, if desired
// checkForUpdates();
}
AutoUpdater::~AutoUpdater(){};
void AutoUpdater::checkForUpdates() {
try {
// Check for updates
updInfo = manager.checkForUpdates();
if (updInfo == nullptr) {
// no updates available
qInfo() << "No updates available, running latest version \\o/";
Q_EMIT noNewUpdatesAvailable();
} else {
setNewVersion(
QString::fromStdString(updInfo->targetFullRelease->version));
qInfo() << "Update available: " << newVersion();
}
} catch (const std::exception &err) {
qInfo() << "Error checking for new updates, msg: " << err.what();
Q_EMIT noNewUpdatesAvailable();
}
}
void AutoUpdater::downloadLatestUpdate() {
try {
if (updInfo != nullptr) {
qInfo() << __FUNCTION__ << "Downloading new version: "
<< QString::fromStdString(updInfo->targetFullRelease->version);
manager.downloadUpdates(updInfo->targetFullRelease.get());
qInfo() << __FUNCTION__ << "Downloaded version: "
<< QString::fromStdString(updInfo->targetFullRelease->version);
setUpdateReadyToInstall(true);
Q_EMIT updateDownloaded();
} else {
qInfo() << __FUNCTION__
<< "Trying to update, even though we don't have a new version! "
"This shouldn't happen...";
setUpdateReadyToInstall(false);
}
} catch (const std::exception &err) {
qWarning() << __FUNCTION__ << "Updating failed with error: " << err.what();
setUpdateReadyToInstall(false);
Q_EMIT updateDownloadFailed();
}
}
QString AutoUpdater::updateUrl() { return QString::fromStdString(kUpdateUrl); }
void AutoUpdater::applyUpdateAndRestart() {
if (!updateReadyToInstall()) {
Q_EMIT updatingFailed("Update not ready, try restarting the sample app");
return;
}
try {
if (updInfo != nullptr) {
qInfo() << __FUNCTION__ << "Downloading and installing new update: "
<< QString::fromStdString(updInfo->targetFullRelease->version);
// We should now have the package downloaded, so update and restart the
// app
manager.applyUpdatesAndRestart(updInfo->targetFullRelease.get());
} else {
qInfo() << __FUNCTION__
<< "Trying to update, even tho we don't have a new version! This "
"shouldn't happen...";
}
} catch (const std::exception &err) {
qWarning() << __FUNCTION__ << "Updating failed with error: " << err.what();
Q_EMIT updatingFailed(QString::fromStdString(err.what()));
}
}
bool AutoUpdater::updateReadyToInstall() const {
return m_updateReadyToInstall;
}
void AutoUpdater::setUpdateReadyToInstall(bool newUpdateReady) {
if (m_updateReadyToInstall == newUpdateReady)
return;
m_updateReadyToInstall = newUpdateReady;
Q_EMIT updateReadyToInstallChanged();
}
QString AutoUpdater::currentUpdateChannel() const {
return m_currentUpdateChannel;
}
void AutoUpdater::setCurrentUpdateChannel(
const QString &newCurrentUpdateChannel) {
if (m_currentUpdateChannel == newCurrentUpdateChannel)
return;
m_currentUpdateChannel = newCurrentUpdateChannel;
Q_EMIT currentUpdateChannelChanged();
}
QString AutoUpdater::currentVersion() const { return m_currentVersion; }
void AutoUpdater::setCurrentVersion(const QString &newCurrentVersion) {
if (m_currentVersion == newCurrentVersion)
return;
m_currentVersion = newCurrentVersion;
Q_EMIT currentVersionChanged();
}
QString AutoUpdater::newVersion() const { return m_newVersion; }
void AutoUpdater::setNewVersion(const QString &newNewVersion) {
if (m_newVersion == newNewVersion)
return;
m_newVersion = newNewVersion;
Q_EMIT newVersionChanged();
}

View File

@@ -0,0 +1,69 @@
#ifndef AUTOUPDATER_H
#define AUTOUPDATER_H
#include "Velopack.hpp"
#include <QDebug>
#include <QObject>
#include <QThread>
class AutoUpdater : public QObject {
Q_OBJECT
Q_PROPERTY(
QString currentUpdateChannel READ currentUpdateChannel WRITE
setCurrentUpdateChannel NOTIFY currentUpdateChannelChanged FINAL)
Q_PROPERTY(QString currentVersion READ currentVersion WRITE setCurrentVersion
NOTIFY currentVersionChanged FINAL)
Q_PROPERTY(
bool updateReadyToInstall READ updateReadyToInstall WRITE
setUpdateReadyToInstall NOTIFY updateReadyToInstallChanged FINAL)
Q_PROPERTY(QString newVersion READ newVersion WRITE setNewVersion NOTIFY
newVersionChanged FINAL)
public:
explicit AutoUpdater(QObject *parent = nullptr);
~AutoUpdater() override;
public:
static AutoUpdater &instance() {
static AutoUpdater _instance;
return _instance;
}
bool updateReadyToInstall() const;
void setUpdateReadyToInstall(bool newUpdateReady);
QString currentUpdateChannel() const;
void setCurrentUpdateChannel(const QString &newCurrentUpdateChannel);
QString currentVersion() const;
void setCurrentVersion(const QString &newCurrentVersion);
QString newVersion() const;
void setNewVersion(const QString &newNewVersion);
Q_INVOKABLE void applyUpdateAndRestart();
Q_INVOKABLE void checkForUpdates();
Q_INVOKABLE void downloadLatestUpdate();
Q_INVOKABLE QString updateUrl();
signals:
void noNewUpdatesAvailable();
void updateReadyToInstallChanged();
void currentUpdateChannelChanged();
void currentVersionChanged();
void newVersionChanged();
void updatingFailed(QString errorMg);
void updateDownloadFailed();
void updateDownloaded();
private:
QString m_currentUpdateChannel;
QString m_currentVersion;
QString m_newVersion;
bool m_updateReadyToInstall = false;
bool m_updateDownloaded = false;
Velopack::UpdateManagerSync manager{};
std::shared_ptr<Velopack::UpdateInfo> updInfo{};
};
#endif // AUTOUPDATER_H

View File

@@ -0,0 +1,67 @@
#!/bin/bash
# Find the absolute path of the script
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Check if version and Qt path parameters are provided
if [ "$#" -ne 2 ]; then
echo "Version number and path to Qt installation are required."
echo "Usage: ./build.sh [version] [path-to-qt]"
echo ""
echo "Example: ./build.sh 1.0.4 /Users/kalle/Qt/6.53/macos"
echo ""
exit 1
fi
BUILD_VERSION="$1"
QT_DIR="$2"
BUILD_DIR="$SCRIPT_DIR/build"
RELEASE_DIR="$SCRIPT_DIR/releases"
PUBLISH_DIR="$SCRIPT_DIR/publish"
echo ""
echo "Compiling Velopack Qt sample..."
# Remove build directory if it exists
if [ -d "$BUILD_DIR" ]; then
rm -rf "$BUILD_DIR"
fi
# Remove publish directory if it exists
if [ -d "$PUBLISH_DIR" ]; then
rm -rf "$PUBLISH_DIR"
fi
# Create build directory to run cmake in
mkdir "$BUILD_DIR"
# Navigate to the build directory
cd "$BUILD_DIR" || exit
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PUBLISH_DIR -DCMAKE_PREFIX_PATH=$QT_DIR ..
# Check if cmake was successful
if [ $? -eq 0 ]; then
# Run cmake build
cmake --build .
# Run cmake install and mute the output
echo ""
echo "Packaging Qt app..."
cmake --build . --target install > /dev/null 2>&1
else
echo "CMake configuration failed."
cd $SCRIPT_DIR
exit 1
fi
echo ""
echo "Building Velopack Qt Sample Release v$BUILD_VERSION"
vpk pack --packId appVelopackQtSample \
--mainExe appVelopackQtSample \
--packTitle VelopackQtSample \
-v $BUILD_VERSION \
-o "$RELEASE_DIR" \
-p "$PUBLISH_DIR/appVelopackQtSample.app" \
-i "$SCRIPT_DIR/artwork/DefaultApp.icns"

View File

@@ -0,0 +1,61 @@
@echo off
setlocal
rem Find the absolute path of the script
set "SCRIPT_DIR=%~dp0"
rem Check if version and Qt path parameters are provided
if "%~2"=="" (
echo Version number and path to Qt installation are required.
echo Usage: %~nx0 [version] [path-to-qt]
echo.
echo Example: %~nx0 1.0.4 C:\Users\kalle\Qt\6.5.3\msvc2019_64
echo.
exit /b 1
)
set BUILD_VERSION=%~1
set QT_DIR=%~2
set BUILD_DIR=%SCRIPT_DIR%build
set RELEASE_DIR=%SCRIPT_DIR%releases
set PUBLISH_DIR=%SCRIPT_DIR%publish
echo.
echo Compiling Velopack Qt sample...
echo #define UPDATE_URL R"(%RELEASE_DIR%)" > constants.h
rem Remove build directory if it exists
if exist "%BUILD_DIR%" (
rmdir /s /q "%BUILD_DIR%"
)
rem Create build directory to run cmake in
echo Creating %BUILD_DIR%...
mkdir "%BUILD_DIR%"
rem Navigate to the build directory
cd /d "%BUILD_DIR%" || exit /b
cmake -G"Ninja" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="%PUBLISH_DIR%" -DCMAKE_PREFIX_PATH="%QT_DIR%" ..
if %errorlevel% neq 0 (
echo I couldn't run cmake. Exiting.
cd /d "%SCRIPT_DIR%"
exit /b 1
)
ninja
ninja install
echo.
echo Building Velopack Qt Sample Release v%BUILD_VERSION%
vpk pack --packId appVelopackQtSample ^
--mainExe bin\appVelopackQtSample.exe ^
--packTitle VelopackQtSample ^
-v %BUILD_VERSION% ^
-o "%RELEASE_DIR%" ^
-p "%PUBLISH_DIR%"
:end

View File

@@ -0,0 +1 @@
#define UPDATE_URL R"(C:\Source\velopack\samples\CPlusPlusQt\releases)"

View File

@@ -0,0 +1,34 @@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "autoupdater.h"
int main(int argc, char *argv[]) {
try {
// Init Velopack hooks, MUST be as early as possible in main()
// Velopack may exit / restart our app at this statement
Velopack::startup(argv, argc);
} catch (const std::exception &err) {
qInfo() << "Error initating auto-updater, msg: " << err.what();
}
QGuiApplication app(argc, argv);
// Init Auto Updater as a singleton
qmlRegisterSingletonInstance("VelopackQt", 1, 0, "AutoUpdater",
&AutoUpdater::instance());
QQmlApplicationEngine engine;
const QUrl url(u"qrc:/VelopackQtSample/Main.qml"_qs);
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}