Skip to content

Commit ecc3421

Browse files
committed
WIP porting guide
1 parent 2eda3ce commit ecc3421

File tree

5 files changed

+237
-7
lines changed

5 files changed

+237
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The Qt auto updater library is a library to automatically check for updates and
1010
[![Appveyor Build status](https://ci.appveyor.com/api/projects/status/5iw2byrvnsdfytxv/branch/master?svg=true)](https://ci.appveyor.com/project/Skycoder42/qtautoupdater/branch/master)
1111
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a5b2e3cc66c644869515d2f3a5c3ff49)](https://www.codacy.com/app/Skycoder42/QtAutoUpdater)
1212

13-
> The library was recently updated to version 3.0. That release differes strongly from 2.1. Use the [Porting Guide](port_to_3_0.md) to get your application from 2.1 to 3.0!
13+
> The library was recently updated to version 3.0. That release differes strongly from 2.1. Use the [Porting Guide](porting_guide.md) to get your application from 2.1 to 3.0!
1414
1515
## Features
1616
### Core Library

doc/doc.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ OTHER_FILES += Doxyfile \
44
makedoc.sh \
55
doxme.py \
66
../README.md \
7+
../porting_guide.md \
78
*.dox \
89
snippets/*.cpp \
910
images/*

doc/doxme.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,45 @@
11
#!/usr/bin/python
22
# $1 The readme to be transformed
3+
# $2 brief description
34
# $pwd: dest dir
45

56
import sys
7+
import os.path
68

7-
def readFirst(line, out):
9+
def readFirst(line, brief, out):
810
if line[0:2] != "# ":
911
raise ValueError("Expected first line to start with '# '")
1012
# skip the first line
13+
if brief is not None:
14+
out.write(line + "\n");
15+
out.write("@brief " + brief + "\n\n")
1116
out.write("[TOC]\n\n")
1217

1318
readCounter = 0
14-
def readMore(line, out):
19+
def readMore(line, label, offset, out):
1520
global readCounter
1621
if line[0:2] == "##":
17-
out.write(line[1:] + " {{#qtautoupdater_readme_label_{}}}\n".format(readCounter))
22+
out.write(line[1:] + " {{#qtautoupdater_{}_label_{}}}\n".format(label, readCounter))
1823
readCounter += 1
1924
else:
2025
out.write(line + "\n")
2126

2227
#read args
2328
readme = sys.argv[1]
24-
doxme = "./README.md"
29+
brief = sys.argv[2] if len(sys.argv) > 2 else None
30+
doxme = os.path.basename(readme)
31+
label, _ = os.path.splitext(doxme)
2532

2633
inFile = open(readme, "r")
2734
outFile = open(doxme, "w")
2835

2936
isFirst = True
3037
for line in inFile:
3138
if isFirst:
32-
readFirst(line[:-1], outFile)
39+
readFirst(line[:-1], brief, outFile)
3340
isFirst = False
3441
else:
35-
readMore(line[:-1], outFile)
42+
readMore(line[:-1], label, 1 if brief is None else 0, outFile)
3643

3744
inFile.close();
3845
outFile.close();

doc/makedoc.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ qtDocs=$5
1818
doxyTemplate="$srcDir/Doxyfile"
1919
doxyRes=Doxyfile.generated
2020
readme="$destDir/README.md"
21+
guide="$destDir/porting_guide.md"
2122
doxme="$scriptDir/doxme.py"
2223

2324
python3 "$doxme" "$srcDir/../README.md"
25+
python3 "$doxme" "$srcDir/../porting_guide.md" "A guide to port from 2.1.5 to 3.0.0"
2426

2527
cat "$doxyTemplate" > $doxyRes
2628
echo "PROJECT_NUMBER = \"$version\"" >> $doxyRes
2729
echo "INPUT += \"$readme\"" >> $doxyRes
30+
echo "INPUT += \"$guide\"" >> $doxyRes
2831
echo "USE_MDFILE_AS_MAINPAGE = \"$readme\"" >> $doxyRes
2932
echo "OUTPUT_DIRECTORY = \"$destDir\"" >> $doxyRes
3033
echo "QHP_NAMESPACE = \"de.skycoder42.qtautoupdater.$verTag\"" >> $doxyRes

porting_guide.md

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# Porting guide
2+
The following guide will help you to convert an application that uses version 2.1.5 of the library to the new
3+
version 3.0.0. This was a major update and thus introduces code changes that have to be manually adjusted. The
4+
update mostly added features and changed the internal structure, but existing classes had their APIs cleaned up
5+
as well.
6+
7+
> This guide will only handle changes to existing APIs, i.e. the core and widgets modules with the QtIFW plugin. Any other new additions are not referenced here.
8+
9+
## General API changes
10+
The core change from 2 to 3 are two main things. First is, that the library now supports more than just QtIFW. It
11+
now supports 6 different backends, in the form of plugins. This does not really matter for this guide. Only how you
12+
deploy the application has sligthly changed. Second, the module now allows more sofisticated installations. It can
13+
run installations in parallel and track their progress. This too, does not really affect QtIFW, as it only launches
14+
an external installer. However, on Linux and macOs, it is now possible to run the maintenancetool in parallel to the
15+
running application.
16+
17+
Information about the plugin for QtIFW and it specialities can be found on the
18+
@ref qtautoupdater_backends "backends page" in the documentation.
19+
20+
## Porting QtAutoUpdaterCore
21+
The following changes have been made to the core module. They are mostly cosmetic changes, i.e. changing how the
22+
API is presented. The are listed in the following ordered by classes.
23+
24+
### Changes to UpdateInfo
25+
The UpdateInfo class has been moved out of Updater is now called QtAutoUpdater::UpdateInfo. Is has been converted to
26+
a fully fledged gadget. Instead of members, it has now equally named properties with get and set accessors. In
27+
addition, there are comparators and functions to use them as key to hashes.
28+
29+
The `size` member has been completly removed, as part of the generalization that happend to the library. You can
30+
still access it, via the newly added `data` property:
31+
@code{.cpp}
32+
auto size = info.data()["size"].toULongLong();
33+
@endcode
34+
The size is also the secondary info property for QtIFW. See QtAutoUpdater::UpdaterBackend::secondaryInfo.
35+
36+
### Changes to AdminAuthoriser
37+
This class has always been more of a side-class. Instead of a class it is now a namespace and provides two methods.
38+
The `hasAdminRights` method has been removed and replaced with QtAutoUpdater::AdminAuthoriser::needsAdminPermission.
39+
That method instead tries to guess if the execution of the given executable needs an elevation of rights first, or
40+
if it can be executed in the current context. `executeAsAdmin` has not been changed, but now allows you to add the
41+
working directory as parameter (ignored on macOs).
42+
43+
### Changes to Updater
44+
As the primary class of the module, this class has changed the most. While is functionality stayed the same - to
45+
check for updates and launch the installation - the API has been improved and generalized. Also, since now plugins
46+
are used, the configuration is different
47+
48+
#### Creation
49+
Instead of creating it via the constructor, there is now a factory method - QtAutoUpdater::Updater::create. It
50+
takes a backend and a configuration and creates the updater using that backend from it. To create an updater with a
51+
maintenancetool, use the following code:
52+
53+
@code{.cpp}
54+
auto updater = QtAutoUpdater::Updater::create("qtifw", {
55+
{"path", pathToTheMaintenancetool}
56+
}, parent);
57+
@endcode
58+
59+
To create an updater instance with the default path, simply leave out the configuration. There are a few other
60+
parameters you can use here. There are partially explained in other parts of this guide - but you can also take a
61+
look at @ref qtautoupdater_backends_qtifw. You can also use a configuration file. It would look like this:
62+
63+
@code{.ini}
64+
[General]
65+
backend=qtifw
66+
path=pathToTheMaintenancetool
67+
...
68+
@endcode
69+
70+
#### Status report
71+
The updater now uses the QtAutoUpdater::Updater::state property to track the state. The
72+
QtAutoUpdater::Updater::running property stayed, but is simply a wrapper around that state to simplify it down to
73+
the information, whether the updater is doing something or not. All the accessors directly linked with the
74+
maintenancetool have been removed. This includes the members `maintenanceToolPath`, `exitedNormally`, `errorCode`
75+
and `errorLog`. This information is now logged internally and cannot be accessed anymore.
76+
77+
#### Checking for updates
78+
The method to start an update check stayed the same: QtAutoUpdater::Updater::checkForUpdates - but it now returns
79+
void instead of bool, as the state can be used to track the progress. The QtAutoUpdater::Updater::progressChanged
80+
signal has been added to provide a more detailed progress for supported plugins. QtIFW does not provide those
81+
details, so you can ignore the signal. Once the update check is done, the QtAutoUpdater::Updater::checkUpdatesDone signal is still beeing emitted, but it
82+
now only has the status as parameter instead of two booleans. The update details can still be accessed via the
83+
QtAutoUpdater::Updater::updateInfo property.
84+
85+
It is also possible to add additional arguments to the update check run of the maintenancetool. To do so, use the
86+
`extraCheckArgs` in the configuration to specify those arguments:
87+
88+
@code{.code}
89+
{
90+
{"extraCheckArgs", "someArg=tree"}
91+
}
92+
@endcode
93+
94+
#### Installing updates
95+
The method to start an installation has been renamed from `runUpdaterOnExit` to QtAutoUpdater::Updater::runUpdater
96+
and now takes two arguments to specify how updates should be installed. There are various options, but only two of
97+
them are viable:
98+
99+
- QtAutoUpdater::Updater::runUpdater(QtAutoUpdater::Updater::InstallModeFlag::OnExit)
100+
- QtAutoUpdater::Updater::runUpdater(QtAutoUpdater::Updater::InstallModeFlag::Parallel)
101+
102+
The first one works for all platforms and exhibits the same behaviour as the old version. It schedules the installer
103+
to be executed on exit of the running application. The second one only works on Linux and macOs and launches the
104+
installer immediatly, in parallel to the running application. For this variant, you can track the installation via
105+
the state and by waiting for the QtAutoUpdater::Updater::installDone signal.
106+
107+
If you want to specify additional arguments to the installation, use the configuration. The following parameters
108+
can be added. `silent` will make the updater run in background, `extraInstallArgs` allows you to pass any additional
109+
arguments you desire to the installer and `runAsAdmin` can be used to specify if the installer should be run as
110+
admin or not. Leaving that one out will make the backend use the QtAutoUpdater::AdminAuthoriser to guess the
111+
correct value. The code below shows how the old constants are mapped to parameters in the configuration:
112+
113+
@code{.code}
114+
// NormalUpdateArguments
115+
{}
116+
// PassiveUpdateArguments
117+
{
118+
{"extraInstallArgs", "skipPrompt=true"}
119+
}
120+
// HiddenUpdateArguments
121+
{
122+
{"silent", true}
123+
}
124+
@endcode
125+
126+
#### Other changes
127+
The remaining changes are mostly stuff that has to do with the new plugin architecture and other small additions.
128+
Read the documentation for more details. Scheduling update checks is also still possible and now even supports use
129+
of the std::chrono classes.
130+
131+
### Added classes
132+
The remaining changes to the module are mostly added classes that have to do with the new plugin architecture.
133+
Again, check the documentation for more details about these classes.
134+
135+
## Porting QtAutoUpdaterGui
136+
The first thing to say here is, that the module has been renamed. It is now called *QtAutoUpdaterWidgets*, as it
137+
only creates a widgets GUI. For QML, there now is the `de.skycoder42.QtAutoUpdater.Quick` module you can import and
138+
use. Refer to the documentation of that namespace and the README for more details on how to use it. There haven't
139+
been any big changes functionality wise to this module. It still uses the controller to show a GUI and provides the
140+
UpdateButton as a dynamic button. However, the way these classes are used has changed and adjusted to the changes
141+
in the core module. No classes have been added or removed.
142+
143+
### Changes to UpdateController
144+
The controllers API has been changed quite a bit. A lot of functionality that was duplicated from the internally
145+
used updater has been removed, as it can now be completly controlled via the updater. The GUIs that are shown by
146+
the controller however have not been changed.
147+
148+
#### Construction and window affiliation
149+
Instead of using a maintenancetool, you now have to create the controller by passing it an updater. The controller
150+
does not take ownership of the updater, which is why the parenting has been united. If you create the controller
151+
with a QWidget as parent, all windows will be parented to that widget as well. If any other QObject is used as
152+
parent, the windows will be parentless toplevel windows instead. If the controller gets destroyed early, the updater
153+
stays alive and can still trigger an installer on exit. Thus, it is recommended to parent the controller correctly.
154+
155+
In addition, the controller will now only show the GUIs if the parent window is visible (or minimized). A windows
156+
counts as visible even if hidden behind other windows or on another desktop. This allows you to add multiple
157+
controllers to different GUIs of your application, without the interferring, as long as only one of those windows
158+
is visible at a times.
159+
160+
Finally, the QtAutoUpdater::UpdateController::createUpdateAction has been made static, the the action only requires
161+
a reference to an updater, not to the controller anymore. Otherwise, the action is still the same. It will however
162+
call QtAutoUpdater::Updater::checkForUpdates instead of using a controller, which means it is not possible to have
163+
an action with asklevel anymore. Any other level still works, as explained in the next section.
164+
165+
#### Auto attachment to updaters
166+
Unlike before, the controller now "attaches" to the updater and can show a GUI in any state of the update check. If
167+
you for example create a controller while already checking for updates, there won't be a progress, but as soon as
168+
the check has finished, a result dialog will be shown (if enabled by display level).
169+
170+
Because of this change, the `running` property of the controller has been removed. Use the updater instead to check
171+
if it is running or not.
172+
173+
#### Setting the display level and running the controller
174+
Another change has been made to the display level handling. The display level is now a property,
175+
QtAutoUpdater::UpdateController::displayLevel. This property can be set and changed even during a running update
176+
check and takes effect as soon as the next dialog is shown. It is know global for all checks run via this
177+
controller. It is still possible to pass the level to the QtAutoUpdater::UpdateController::start method, but this
178+
will only set the property and then call `start` without any parameters.
179+
180+
To run the controller, you should still call `start`, as it will show the ask dialog if wished before checking for
181+
updates. However, it is also possible to use QtAutoUpdater::Updater::checkForUpdates instead, as the controller is
182+
attached to the updater. This will work for all levels but the ask level, as the ask dialog will never be shown when
183+
an update check is started via the updater.
184+
185+
Use the properties and signals of the QtAutoUpdater::Updater to track the progress. All such methods have been
186+
removed from the controller, as they are not needed there anymore.
187+
188+
#### Removed members
189+
There are quite a few properties and methods that have been removed. Those have been mostly removed because the
190+
same functionality is already beeing provided by the underlying updater. The removed members are:
191+
`maintenanceToolPath`, `running`, `runAsAdmin`, `updateRunArgs`, `scheduleUpdate` and `cancelScheduledUpdate`.
192+
193+
In the GUI, the run as admin checkbox has been removed. You should get this information programatically, and not
194+
by prompting the user, as the user typically has no clue about this. You can still specify it, by using the
195+
`runAsAdmin` configuration value.
196+
197+
### Changes to UpdateButton
198+
The update button has seen changes similar to the controller. The main difference is, that it now only needs an
199+
updater instead of a controller, and that it supports a more sofisticated UI, including a state that is shown while
200+
installing parallel updates for Linux or macOs. The rest of it's GUI however has stayed the same.
201+
202+
The fact that the button now uses an QtAutoUpdater::Updater only also means, that there is no display level anymore.
203+
Again, this is not problematic as any controller will automatically show required GUIs, even if completely detached
204+
from the button, as long as they use the same updater.
205+
206+
Another thing that changed is, that you can now trigger an installation via the button, if updates are available.
207+
The QtAutoUpdater::UpdateButton::mode property controlls whether this is possible and how the button operates in
208+
general. If allowed and a user triggers the installation, the QtAutoUpdater::UpdateButton::installMode and
209+
QtAutoUpdater::UpdateButton::installScope properties are used as arguments for the
210+
QtAutoUpdater::Updater::runUpdater method call.
211+
212+
## Final remarks
213+
As you can see from this guide, there have been quite a few changes. Most of them however are nothing more then
214+
sligthly more complex refactorings. Using this document you should be able to easily port any application from the
215+
old to the new version. If you however still have some questions, simply use the
216+
[GitHub Issues](https://github.com/Skycoder42/QtAutoUpdater/issues) to ask for help. I am aware that such a change
217+
can be challenging and I am always willing to provide any help I can.
218+
219+
## Examples

0 commit comments

Comments
 (0)