Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3cda8d7cb | ||
|
|
4611f2f9ea | ||
|
|
7acd4bb3d6 | ||
|
|
41b4b59a5e | ||
|
|
077320dc19 | ||
|
|
c5eeeb7a50 | ||
|
|
52882df5ee | ||
|
|
616e51b3ee | ||
|
|
f2e59e611f | ||
|
|
a532b309b7 | ||
|
|
45ae6084d8 | ||
|
|
e0cd044e5b | ||
|
|
2c1cbb7f85 | ||
|
|
bf5e3d857a | ||
|
|
e78bd936a3 | ||
|
|
a53f9359f4 | ||
|
|
3a525359a5 | ||
|
|
7716052fbb | ||
|
|
5e7c6ef005 | ||
|
|
83da9b2485 | ||
|
|
ceea4db418 | ||
|
|
86823162c6 | ||
|
|
19ffdc47bb | ||
|
|
0bd415f83e | ||
|
|
028042afe7 | ||
|
|
59556074cc | ||
|
|
a6a9dc6890 | ||
|
|
ed7d63d913 | ||
|
|
9b1da6ff8c | ||
|
|
7d3c483b35 | ||
|
|
0d057478b0 | ||
|
|
7f750cb145 | ||
|
|
86e77b975f | ||
|
|
70fa9fa766 | ||
|
|
c43bd06860 |
100
.github/workflows/nightly-neon.yml
vendored
Normal file
100
.github/workflows/nightly-neon.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
name: nightly-neon-xtn
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "52 1 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILDDIR: /build
|
||||||
|
SRCDIR: ${{ github.workspace }}
|
||||||
|
CMAKE_ARGS: |
|
||||||
|
-DWEBVIEW_FORCE_WEBKIT=1
|
||||||
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
|
-DWITH_PYTHONQT=OFF"
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker://kdeneon/plasma:user
|
||||||
|
options: --tmpfs /build:rw --user 0:0
|
||||||
|
steps:
|
||||||
|
- name: "fetch artifacts"
|
||||||
|
uses: dawidd6/action-download-artifact@v2
|
||||||
|
with:
|
||||||
|
workflow: nightly-neon.yml
|
||||||
|
workflow_conclusion: success
|
||||||
|
branch: calamares
|
||||||
|
name: calamares-tarball
|
||||||
|
path: ${{ env.BUILDDIR }}
|
||||||
|
repo: calamares/calamares
|
||||||
|
- name: "prepare env"
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install git-core
|
||||||
|
sudo apt-get -y install \
|
||||||
|
build-essential \
|
||||||
|
cmake \
|
||||||
|
extra-cmake-modules \
|
||||||
|
gettext \
|
||||||
|
kio-dev \
|
||||||
|
libatasmart-dev \
|
||||||
|
libboost-python-dev \
|
||||||
|
libkf5config-dev \
|
||||||
|
libkf5coreaddons-dev \
|
||||||
|
libkf5i18n-dev \
|
||||||
|
libkf5iconthemes-dev \
|
||||||
|
libkf5parts-dev \
|
||||||
|
libkf5service-dev \
|
||||||
|
libkf5solid-dev \
|
||||||
|
libkpmcore-dev \
|
||||||
|
libparted-dev \
|
||||||
|
libpolkit-qt5-1-dev \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5webkit5-dev \
|
||||||
|
libyaml-cpp-dev \
|
||||||
|
os-prober \
|
||||||
|
pkg-config \
|
||||||
|
python3-dev \
|
||||||
|
qtbase5-dev \
|
||||||
|
qtdeclarative5-dev \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools
|
||||||
|
- name: "prepare source"
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: "prepare artifacts"
|
||||||
|
run: tar xvzf "$BUILDDIR/calamares.tar.gz" -C / --strip-components 1
|
||||||
|
- name: "prepare build"
|
||||||
|
id: pre_build
|
||||||
|
run: |
|
||||||
|
test -n "$BUILDDIR" || { echo "! \$BUILDDIR not set" ; exit 1 ; }
|
||||||
|
mkdir -p $BUILDDIR
|
||||||
|
test -f $SRCDIR/CMakeLists.txt || { echo "! Missing $SRCDIR/CMakeLists.txt" ; exit 1 ; }
|
||||||
|
echo "::set-output name=message::"`git log -1 --abbrev-commit --pretty=oneline --no-decorate ${{ github.event.head_commit.id }}`
|
||||||
|
- name: "Calamares-Extensions: cmake"
|
||||||
|
working-directory: ${{ env.BUILDDIR }}
|
||||||
|
run: cmake $CMAKE_ARGS $SRCDIR
|
||||||
|
- name: "Calamares-Extensions: make"
|
||||||
|
working-directory: ${{ env.BUILDDIR }}
|
||||||
|
run: make -j2 VERBOSE=1
|
||||||
|
- name: "Calamares-Extensions: install"
|
||||||
|
working-directory: ${{ env.BUILDDIR }}
|
||||||
|
run: make install VERBOSE=1
|
||||||
|
- name: "notify: ok"
|
||||||
|
uses: rectalogic/notify-irc@v1
|
||||||
|
if: ${{ success() && github.repository == 'calamares/calamares-extensions' }}
|
||||||
|
with:
|
||||||
|
server: chat.freenode.net
|
||||||
|
nickname: cala-ci
|
||||||
|
channel: "#calamares"
|
||||||
|
message: "OK ${{ github.workflow }} in ${{ github.repository }} ${{ steps.pre_build.outputs.message }}"
|
||||||
|
- name: "notify: fail"
|
||||||
|
uses: rectalogic/notify-irc@v1
|
||||||
|
if: ${{ failure() && github.repository == 'calamares/calamares' }}
|
||||||
|
with:
|
||||||
|
server: chat.freenode.net
|
||||||
|
nickname: cala-ci
|
||||||
|
channel: "#calamares"
|
||||||
|
message: "FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ steps.pre_build.outputs.message }}"
|
||||||
106
.github/workflows/push.yml
vendored
Normal file
106
.github/workflows/push.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
name: ci-push-xtn
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- calamares
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- reopened
|
||||||
|
- synchronize
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
BUILDDIR: /build
|
||||||
|
SRCDIR: ${{ github.workspace }}
|
||||||
|
CMAKE_ARGS: |
|
||||||
|
-DWEBVIEW_FORCE_WEBKIT=1
|
||||||
|
-DKDE_INSTALL_USE_QT_SYS_PATHS=ON
|
||||||
|
-DWITH_PYTHONQT=OFF"
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker://kdeneon/plasma:user
|
||||||
|
options: --tmpfs /build:rw --user 0:0
|
||||||
|
steps:
|
||||||
|
- name: "fetch artifacts"
|
||||||
|
uses: dawidd6/action-download-artifact@v2
|
||||||
|
with:
|
||||||
|
workflow: nightly-neon.yml
|
||||||
|
workflow_conclusion: success
|
||||||
|
branch: calamares
|
||||||
|
name: calamares-tarball
|
||||||
|
path: ${{ env.BUILDDIR }}
|
||||||
|
repo: calamares/calamares
|
||||||
|
- name: "prepare env"
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install git-core
|
||||||
|
sudo apt-get -y install \
|
||||||
|
build-essential \
|
||||||
|
cmake \
|
||||||
|
extra-cmake-modules \
|
||||||
|
gettext \
|
||||||
|
kio-dev \
|
||||||
|
libatasmart-dev \
|
||||||
|
libboost-python-dev \
|
||||||
|
libkf5config-dev \
|
||||||
|
libkf5coreaddons-dev \
|
||||||
|
libkf5i18n-dev \
|
||||||
|
libkf5iconthemes-dev \
|
||||||
|
libkf5parts-dev \
|
||||||
|
libkf5service-dev \
|
||||||
|
libkf5solid-dev \
|
||||||
|
libkpmcore-dev \
|
||||||
|
libparted-dev \
|
||||||
|
libpolkit-qt5-1-dev \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5webkit5-dev \
|
||||||
|
libyaml-cpp-dev \
|
||||||
|
os-prober \
|
||||||
|
pkg-config \
|
||||||
|
python3-dev \
|
||||||
|
qtbase5-dev \
|
||||||
|
qtdeclarative5-dev \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools
|
||||||
|
- name: "prepare source"
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: "prepare artifacts"
|
||||||
|
run: tar xvzf "$BUILDDIR/calamares.tar.gz" -C / --strip-components 1
|
||||||
|
- name: "prepare build"
|
||||||
|
id: pre_build
|
||||||
|
run: |
|
||||||
|
test -n "$BUILDDIR" || { echo "! \$BUILDDIR not set" ; exit 1 ; }
|
||||||
|
mkdir -p $BUILDDIR
|
||||||
|
test -f $SRCDIR/CMakeLists.txt || { echo "! Missing $SRCDIR/CMakeLists.txt" ; exit 1 ; }
|
||||||
|
echo "::set-output name=message::"`git log -1 --abbrev-commit --pretty=oneline --no-decorate ${{ github.event.head_commit.id }}`
|
||||||
|
- name: "Calamares-Extensions: cmake"
|
||||||
|
working-directory: ${{ env.BUILDDIR }}
|
||||||
|
run: cmake $CMAKE_ARGS $SRCDIR
|
||||||
|
- name: "Calamares-Extensions: make"
|
||||||
|
working-directory: ${{ env.BUILDDIR }}
|
||||||
|
run: make -j2 VERBOSE=1
|
||||||
|
- name: "Calamares-Extensions: install"
|
||||||
|
working-directory: ${{ env.BUILDDIR }}
|
||||||
|
run: make install VERBOSE=1
|
||||||
|
- name: "notify: ok"
|
||||||
|
uses: rectalogic/notify-irc@v1
|
||||||
|
if: ${{ success() && github.repository == 'calamares/calamares-extensions' }}
|
||||||
|
with:
|
||||||
|
server: chat.freenode.net
|
||||||
|
nickname: cala-ci
|
||||||
|
channel: "#calamares"
|
||||||
|
message: "OK ${{ github.workflow }} in ${{ github.repository }} ${{ github.actor }} on ${{ github.event.ref }}\n.. ${{ steps.pre_build.outputs.message }}"
|
||||||
|
- name: "notify: fail"
|
||||||
|
uses: rectalogic/notify-irc@v1
|
||||||
|
if: ${{ failure() && github.repository == 'calamares/calamares' }}
|
||||||
|
with:
|
||||||
|
server: chat.freenode.net
|
||||||
|
nickname: cala-ci
|
||||||
|
channel: "#calamares"
|
||||||
|
message: "FAIL ${{ github.workflow }} in ${{ github.repository }} ${{ github.actor }} on ${{ github.event.ref }}\n.. ${{ steps.pre_build.outputs.message }}\n.. DIFF ${{ github.event.compare }}"
|
||||||
43
CHANGES
Normal file
43
CHANGES
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<!-- SPDX-FileCopyrightText: no
|
||||||
|
SPDX-License-Identifier: CC0-1.0
|
||||||
|
-->
|
||||||
|
|
||||||
|
This is the changelog for Calamares-Extensions. For each release, the major
|
||||||
|
changes and contributors are listed. Note that Calamares-Extensions does not
|
||||||
|
have a historical changelog -- this log starts with version 1.0.0.
|
||||||
|
|
||||||
|
|
||||||
|
# 1.1.1 (2021-02-23) #
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Oliver Smith
|
||||||
|
- Undef
|
||||||
|
|
||||||
|
Changes and new modules in this release:
|
||||||
|
- Branding has a new example, *image-slideshow*, for a QML-based
|
||||||
|
slideshow with only images.
|
||||||
|
- CI now builds the extensions against a recent Calamares build.
|
||||||
|
- *mobile* add ability to select target filesystem.
|
||||||
|
- *mobile* rename `cmdMkfsRoot` to `cmdMkfsRootExt4`.
|
||||||
|
- *mobile* wait screen has been re-worded.
|
||||||
|
|
||||||
|
|
||||||
|
# 1.1.0 (2021-01-04) #
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Oliver Smith
|
||||||
|
|
||||||
|
Changes and new modules in this release:
|
||||||
|
- *mobile* module bugfixes
|
||||||
|
- *mobile* module SSH daemon can be disabled
|
||||||
|
|
||||||
|
|
||||||
|
# 1.0.0 (2020-12-05) #
|
||||||
|
|
||||||
|
This release contains contributions from (alphabetically by first name):
|
||||||
|
- Oliver Smith
|
||||||
|
- ShalokShalom
|
||||||
|
|
||||||
|
Initial release of Calamares-Extensions as such, with one new module
|
||||||
|
- *mobile*, for PostmarketOS initial configuration
|
||||||
|
|
||||||
@@ -26,13 +26,33 @@
|
|||||||
#
|
#
|
||||||
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
||||||
project(calamares-extensions
|
project(calamares-extensions
|
||||||
VERSION 1.0.0
|
VERSION 1.1.1
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Calamares 3.2.26 REQUIRED)
|
find_package(Calamares 3.2.26 REQUIRED)
|
||||||
|
|
||||||
find_package(YAMLCPP REQUIRED)
|
find_package(YAMLCPP REQUIRED) # Needed to untangle some dependencies before Calamares 3.2.36
|
||||||
|
|
||||||
|
### CMAKE SETUP
|
||||||
|
#
|
||||||
|
# Enable IN_LIST
|
||||||
|
if( POLICY CMP0057 )
|
||||||
|
cmake_policy( SET CMP0057 NEW )
|
||||||
|
endif()
|
||||||
|
# Let ``AUTOMOC`` and ``AUTOUIC`` process ``GENERATED`` files.
|
||||||
|
if( POLICY CMP0071 )
|
||||||
|
cmake_policy( SET CMP0071 NEW )
|
||||||
|
endif()
|
||||||
|
# Recognize more macros to trigger automoc
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.10.0")
|
||||||
|
list(APPEND CMAKE_AUTOMOC_MACRO_NAMES
|
||||||
|
"K_PLUGIN_FACTORY_WITH_JSON"
|
||||||
|
"K_EXPORT_PLASMA_DATAENGINE_WITH_JSON"
|
||||||
|
"K_EXPORT_PLASMA_RUNNER"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
### BRANDING
|
### BRANDING
|
||||||
#
|
#
|
||||||
@@ -67,6 +87,9 @@ calamares_add_module_subdirectory( modules/slowpython ) # Python job
|
|||||||
# which builds a list of explanations; show that list.
|
# which builds a list of explanations; show that list.
|
||||||
calamares_explain_skipped_modules( ${SKIPPED_MODULES} )
|
calamares_explain_skipped_modules( ${SKIPPED_MODULES} )
|
||||||
|
|
||||||
|
### RELEASE SUPPORT
|
||||||
|
#
|
||||||
|
#
|
||||||
set( CALAMARES_VERSION ${calamares-extensions_VERSION_MAJOR}.${calamares-extensions_VERSION_MINOR}.${calamares-extensions_VERSION_PATCH} )
|
set( CALAMARES_VERSION ${calamares-extensions_VERSION_MAJOR}.${calamares-extensions_VERSION_MINOR}.${calamares-extensions_VERSION_PATCH} )
|
||||||
# In rare cases we have hotfix-releases with a tweak
|
# In rare cases we have hotfix-releases with a tweak
|
||||||
if( calamares-extensions_VERSION_TWEAK )
|
if( calamares-extensions_VERSION_TWEAK )
|
||||||
|
|||||||
72
README.md
72
README.md
@@ -1,10 +1,11 @@
|
|||||||
# Calamares Branding and Module Examples
|
# Calamares Branding and Module Examples
|
||||||
|
|
||||||
> A *branding component* in Calamares is a description of the
|
> A *branding component* in Calamares is a description of the
|
||||||
> produce (i.e. distribution) being installed along with a "slideshow"
|
> product (i.e. distribution) being installed along with a "slideshow"
|
||||||
> that is displayed during the installation phase of Calamares.
|
> that is displayed during the installation phase of Calamares.
|
||||||
|
> This shapes the **look** of your installation.
|
||||||
>
|
>
|
||||||
> A *module* adds functionality to Calamares; modules may be written
|
> A *module* adds **functionality** to Calamares; modules may be written
|
||||||
> in C++ or Python, using Qt Widgets or QML for the UI (with C++)
|
> in C++ or Python, using Qt Widgets or QML for the UI (with C++)
|
||||||
> if there is one. Both C++ and Python allow a full control over the
|
> if there is one. Both C++ and Python allow a full control over the
|
||||||
> target system during the installation.
|
> target system during the installation.
|
||||||
@@ -13,13 +14,9 @@ This repository contains complete examples of branding and some
|
|||||||
modules for Calamares.
|
modules for Calamares.
|
||||||
|
|
||||||
- [Branding](#branding) documentation
|
- [Branding](#branding) documentation
|
||||||
- [default](branding/default/branding.desc) branding example
|
- [Module](#modules) documentation
|
||||||
- [fancy](branding/fancy/branding.desc) branding example
|
|
||||||
- [KaOS](branding/kaos_branding/branding.desc) branding example
|
## Branding
|
||||||
- [SameGame](branding/samegame/branding.desc) branding example
|
|
||||||
- [Module](#module) documentation
|
|
||||||
|
|
||||||
## Branding
|
|
||||||
|
|
||||||
> Branding shapes the **look** of Calamares to your distro
|
> Branding shapes the **look** of Calamares to your distro
|
||||||
|
|
||||||
@@ -28,11 +25,20 @@ can be used for testing. The examples here show what can be done
|
|||||||
with QML in the context of Calamares branding, and provide examples
|
with QML in the context of Calamares branding, and provide examples
|
||||||
and documentation for the framework that Calamares ships with.
|
and documentation for the framework that Calamares ships with.
|
||||||
|
|
||||||
- `default/` is a copy of the default branding included with Calamares.
|
- [`default/`](branding/default/branding.desc)
|
||||||
- `fancy/` has navigation buttons and a slide counter.
|
is a copy of the default branding included with Calamares.
|
||||||
- `kaos_branding/` is a copy of the KaOS branding component, which
|
- [`fancy/`](branding/fancy/branding.desc)
|
||||||
|
has navigation buttons and a slide counter.
|
||||||
|
- [`image-slideshow/`](branding/image-slideshow/branding.desc)
|
||||||
|
is a variant of the *default* branding that implements its
|
||||||
|
own slide element for QML that supports a single image.
|
||||||
|
This is useful for straightforward images-only slideshows
|
||||||
|
(probably moreso than the default slideshow).
|
||||||
|
- [`kaos_branding/`](branding/kaos_branding/branding.desc)
|
||||||
|
is a copy of the KaOS branding component, which
|
||||||
has translations and a bunch of fancy graphics.
|
has translations and a bunch of fancy graphics.
|
||||||
- `samegame/` is a copy of the Qt Company "Same Game" QML demo. It
|
- [`samegame/` ](branding/default/branding.desc)
|
||||||
|
is a copy of the Qt Company "Same Game" QML demo. It
|
||||||
shows that **any** QML can be used for branding purposes.
|
shows that **any** QML can be used for branding purposes.
|
||||||
|
|
||||||
### Writing your own Branding
|
### Writing your own Branding
|
||||||
@@ -62,7 +68,7 @@ and documentation for the framework that Calamares ships with.
|
|||||||
parts of Calamares.
|
parts of Calamares.
|
||||||
|
|
||||||
See the [styling paragraph](https://github.com/calamares/calamares/wiki/Deploy-Guide#styling-calamares) of the deployment guide for more details.
|
See the [styling paragraph](https://github.com/calamares/calamares/wiki/Deploy-Guide#styling-calamares) of the deployment guide for more details.
|
||||||
|
|
||||||
### Testing a Branding Component
|
### Testing a Branding Component
|
||||||
|
|
||||||
If Calamares is installed, then the Calamares QML support files
|
If Calamares is installed, then the Calamares QML support files
|
||||||
@@ -72,7 +78,7 @@ branding component is free to do whatever is interesting in QML.
|
|||||||
|
|
||||||
The tool for quickly viewing QML files is `qmlscene`, which is
|
The tool for quickly viewing QML files is `qmlscene`, which is
|
||||||
included with the Qt development tools. It can be used to
|
included with the Qt development tools. It can be used to
|
||||||
preview a Calamares branding component (slideshow) without starting
|
preview a Calamares branding component (slideshow) without starting
|
||||||
Calamares. If the component uses translations, you will need to
|
Calamares. If the component uses translations, you will need to
|
||||||
build the translations first (using Qt Linguist `lrelease`, or by
|
build the translations first (using Qt Linguist `lrelease`, or by
|
||||||
using the normal build system for branding components).
|
using the normal build system for branding components).
|
||||||
@@ -87,7 +93,7 @@ qmlscene \
|
|||||||
-translation build/calamares-fancy_nl.qm \
|
-translation build/calamares-fancy_nl.qm \
|
||||||
-I /usr/local/share/calamares/qml \
|
-I /usr/local/share/calamares/qml \
|
||||||
-geometry 600x400 \
|
-geometry 600x400 \
|
||||||
fancy/show.qml
|
fancy/show.qml
|
||||||
```
|
```
|
||||||
|
|
||||||
This starts the viewer with the Dutch (nl) translation, using the
|
This starts the viewer with the Dutch (nl) translation, using the
|
||||||
@@ -104,25 +110,39 @@ every time.
|
|||||||
### Calamares Branding API
|
### Calamares Branding API
|
||||||
|
|
||||||
The slideshow which is configured in the branding files can have
|
The slideshow which is configured in the branding files can have
|
||||||
one of two "API styles".
|
one of two "API styles".
|
||||||
|
|
||||||
- Version 1 is loaded when the slideshow starts. If the slideshow is
|
- Version 1 is loaded when the slideshow starts. If the slideshow is
|
||||||
large, or contains remote content, then this may be slow.
|
large, or contains remote content, then this may be slow.
|
||||||
|
The loading time may be visible as a "white flash" as the
|
||||||
|
QML component is displayed with no background until the
|
||||||
|
slideshow is loaded.
|
||||||
- Version 2 is loaded asynchronously from the moment Calamares is
|
- Version 2 is loaded asynchronously from the moment Calamares is
|
||||||
started. This may delay startup a little, but may appear more
|
started. This may delay startup a little, but appears more
|
||||||
responsive overall.
|
responsive overall.
|
||||||
|
|
||||||
If the slideshow QML defines functions
|
If the slideshow QML defines functions
|
||||||
`onActivate()` and `onLeave()` then those functions
|
`onActivate()` and `onLeave()` then those functions
|
||||||
are called when the slideshow becomes visible and when the installation is finished.
|
are called when the slideshow becomes visible and when the installation is finished.
|
||||||
These can be used to start and stop timers or sound effects or
|
These can be used to start and stop timers or sound effects or
|
||||||
whatever.
|
whatever.
|
||||||
|
|
||||||
In addition, if the slideshow QML defines a property
|
In addition, if the slideshow QML defines a property
|
||||||
`activatedInCalamares` then it is set to `true`
|
`activatedInCalamares` then it is set to `true`
|
||||||
when the slideshow becomes visible, and to `false` when
|
when the slideshow becomes visible, and to `false` when
|
||||||
the installation is finished. This can also be used to
|
the installation is finished. This can also be used to
|
||||||
start timers, etc.
|
start timers, etc. The standard `Presentation.qml` included with
|
||||||
|
Calamares has such a property.
|
||||||
|
|
||||||
|
A slideshow (`show.qml`) can be entirely independent, with bespoke code,
|
||||||
|
or it can make use of files shipped as part of Calamares: a *Presentation* and
|
||||||
|
a *Slide* element (and some others). There are also Calamares internals which
|
||||||
|
can be used from QML:
|
||||||
|
- `import calamares.slideshow 1.0` for the standard QML slideshow (e.g. *Presentation* element;
|
||||||
|
use *Slide* with this or write an API-equivalent element such as the one in `image-slideshow/`).
|
||||||
|
- `import io.calamares.ui 1.0` for a *Branding* object which has an API to
|
||||||
|
get colors and strings that are used elsewhere in Calamares (e.g. to make the
|
||||||
|
slide background the same as the background defined in `branding.desc`).
|
||||||
|
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
@@ -135,6 +155,8 @@ listed in the *show* phase, and may run jobs if listed in the
|
|||||||
*exec* phase) and a Python job module (no UI, runs in the *exec*
|
*exec* phase) and a Python job module (no UI, runs in the *exec*
|
||||||
phase).
|
phase).
|
||||||
|
|
||||||
|
### Example Modules
|
||||||
|
|
||||||
- [filekeeper](modules/filekeeper/CMakeLists.txt) is a C++ **job** module
|
- [filekeeper](modules/filekeeper/CMakeLists.txt) is a C++ **job** module
|
||||||
to copy files from the host (live) system to the target system at
|
to copy files from the host (live) system to the target system at
|
||||||
the end of installation, like logfiles. (This module is made obsolete
|
the end of installation, like logfiles. (This module is made obsolete
|
||||||
@@ -146,6 +168,14 @@ phase).
|
|||||||
module that just serves to slow down an installation by delaying
|
module that just serves to slow down an installation by delaying
|
||||||
a configurable (default 30 seconds) amount of time.
|
a configurable (default 30 seconds) amount of time.
|
||||||
|
|
||||||
|
### Functional Modules
|
||||||
|
|
||||||
|
- [mobile](modules/mobile/CMakeLists.txt) is a QML **view** that
|
||||||
|
takes over a number of other view steps. It is specific to
|
||||||
|
mobile phone use, possibly specific to PostmarketOS. It does
|
||||||
|
a number of "welcome to your new phone" things, e.g.
|
||||||
|
with PostmarketOS installed on a PinePhone.
|
||||||
|
|
||||||
### CMake Preparation
|
### CMake Preparation
|
||||||
|
|
||||||
The single macro `calamares_add_module_subdirectory()`
|
The single macro `calamares_add_module_subdirectory()`
|
||||||
|
|||||||
64
branding/image-slideshow/ImageSlide.qml
Normal file
64
branding/image-slideshow/ImageSlide.qml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* === This file is part of Calamares Extensions - <http://github.com/calamares-extensions> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* An *ImageSlide* is a *Slide* (it offers the API that *Presentation*
|
||||||
|
* expects) while displaying only a single image. This is useful
|
||||||
|
* for presentations that are all images, with no interaction or text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.5
|
||||||
|
|
||||||
|
/* To use an *ImageSlide*, instantiate it inside your *Presentation*
|
||||||
|
* and set the *src* property to a path to an image file in a supported
|
||||||
|
* format. Relative paths are ok.
|
||||||
|
*/
|
||||||
|
Item {
|
||||||
|
id: imageslide
|
||||||
|
|
||||||
|
/* Slides should be non-visible at the start; the *Presentation*
|
||||||
|
* handles visibility (so that one slide at a time is visible).
|
||||||
|
*/
|
||||||
|
visible: false
|
||||||
|
/* Make this item fill up the parent, so that alignment of the
|
||||||
|
* image (below) works out to "middle of the parent".
|
||||||
|
*/
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
/* The *Presentation* manages visibility of children that have
|
||||||
|
* attribute *isSlide* and *isSlide* is set to *true*. Other
|
||||||
|
* children are ignored, so we need to set this so that the
|
||||||
|
* *ImageSlide* elements are treated like slides.
|
||||||
|
*/
|
||||||
|
property bool isSlide: true;
|
||||||
|
/* The *Presentation* allows slides to have notes, so just leave
|
||||||
|
* an empty string here.
|
||||||
|
*/
|
||||||
|
property string notes;
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the important property for *ImageSlide*: the path to the
|
||||||
|
* image to display. When instantiating *ImageSlide*, set this for
|
||||||
|
* each instance. Relative paths are ok.
|
||||||
|
*/
|
||||||
|
property string src;
|
||||||
|
|
||||||
|
/* The image itself. It has fixed sizes (300x150px). You could set
|
||||||
|
* an aspect ratio here (e.g. `height: width / 2`) as well.
|
||||||
|
*
|
||||||
|
* This binds the image source (filename) to the string *src*
|
||||||
|
* in the *ImageSlide* element, for convenience in setting things
|
||||||
|
* up in the overall slideshow. If you want to make width and
|
||||||
|
* height configurable, add a property above and then bind to
|
||||||
|
* them from the Image element.
|
||||||
|
*/
|
||||||
|
Image {
|
||||||
|
id: image
|
||||||
|
source: src
|
||||||
|
width: 300
|
||||||
|
height: 150
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
40
branding/image-slideshow/branding.desc
Normal file
40
branding/image-slideshow/branding.desc
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
---
|
||||||
|
componentName: default
|
||||||
|
# image-slideshow
|
||||||
|
|
||||||
|
# Branding must define some strings for the welcome page,
|
||||||
|
# even though this example is about the slideshow, not the rest.
|
||||||
|
strings:
|
||||||
|
productName: Mirror Linux
|
||||||
|
shortProductName: Mirror
|
||||||
|
version:
|
||||||
|
shortVersion:
|
||||||
|
versionedName: Mirror Linux 1.0
|
||||||
|
shortVersionedName: Mirror 1.0
|
||||||
|
bootloaderEntryName: Mirror
|
||||||
|
|
||||||
|
# These images do not exist in this branding example.
|
||||||
|
images:
|
||||||
|
productLogo: "logo.png"
|
||||||
|
productIcon: "logo.png"
|
||||||
|
productWelcome: "languages.png"
|
||||||
|
|
||||||
|
# Dark-mode for Calamares. The slideshow can access these color values
|
||||||
|
# through the Branding object which is always available to QML inside Calamares.
|
||||||
|
style:
|
||||||
|
sidebarBackground: "#36393e"
|
||||||
|
sidebarText: "#efefef"
|
||||||
|
sidebarTextSelect: "#2eb69b"
|
||||||
|
sidebarTextHighlight: "#313338"
|
||||||
|
|
||||||
|
# The actual slideshow. API version 2 means that the QML is loaded at
|
||||||
|
# startup. This is **slightly** slower at startup, but means that by
|
||||||
|
# the time we reach the slideshow, it is loaded and ready-to-go.
|
||||||
|
#
|
||||||
|
# A v2 slideshow **may** have an onActivate() and onLeave() function,
|
||||||
|
# although Calamares will complain if it does not.
|
||||||
|
slideshow: "show.qml"
|
||||||
|
slideshowAPI: 2
|
||||||
|
|
||||||
103
branding/image-slideshow/show.qml
Normal file
103
branding/image-slideshow/show.qml
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* === This file is part of Calamares Extensions - <http://github.com/calamares-extensions> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is a simple slideshow for use during the *exec* phase of
|
||||||
|
* installation, that displays a handful of slides. It uses
|
||||||
|
* the *Presentation* QML components -- this allows, for instance,
|
||||||
|
* notes to be added to slides, and for arrow navigation to be
|
||||||
|
* used. But at its core it's just a bunch of images, repeating.
|
||||||
|
*
|
||||||
|
* For this kind of limited functionality, it may be better to
|
||||||
|
* use the "plain images" slideshow format in Calamares, although
|
||||||
|
* then you don't have any say in how things are animated.
|
||||||
|
*
|
||||||
|
* This slideshow is written for *slideshowAPI* version 1, so in
|
||||||
|
* `branding.desc` set that appropriately.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import QtQuick 2.0 // Basic QML
|
||||||
|
import calamares.slideshow 1.0 // Calamares slideshow: Presentation
|
||||||
|
import io.calamares.ui 1.0 // Calamares internals: Branding
|
||||||
|
|
||||||
|
/* *Presentation* comes from the pre-installed calamares.slideshow
|
||||||
|
* that comes with Calamares itself. See `Presentation.qml` in the
|
||||||
|
* Calamares repository for details and documentation.
|
||||||
|
*
|
||||||
|
* The important parts of presentation are:
|
||||||
|
* - it has a property *activatedInCalamares* which is set to *true*
|
||||||
|
* when the slideshow becomes visible, *false* afterwards.
|
||||||
|
* - it expects one or more children with a property *isSlide*
|
||||||
|
* set to *true*.
|
||||||
|
* - it has a function *goToNextSlide()* to do just that (where
|
||||||
|
* "slides" is the sequence of children that have property
|
||||||
|
* *isSlide* set to *true*.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Presentation
|
||||||
|
{
|
||||||
|
id: presentation
|
||||||
|
|
||||||
|
/* This timer ticks once per second (1000ms, set in *interval*)
|
||||||
|
* and calls *goToNextSlide()* each time. Note that it needs
|
||||||
|
* to know the *id* of the presentation, so keep *id* (above)
|
||||||
|
* matched with the function call.
|
||||||
|
*
|
||||||
|
* The timer starts when the presentation is activated; you could
|
||||||
|
* also set *running* to true, but that might cost extra resources.
|
||||||
|
*/
|
||||||
|
Timer {
|
||||||
|
interval: 1000
|
||||||
|
running: presentation.activatedInCalamares
|
||||||
|
repeat: true
|
||||||
|
onTriggered: presentation.goToNextSlide()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These functions are called when the presentation starts and
|
||||||
|
* ends, respectively. They could be used to start the timer,
|
||||||
|
* but that is done automatically through *activatedInCalamares*,
|
||||||
|
* so there's nothing **to** do.
|
||||||
|
*
|
||||||
|
* Leaving these functions out is fine, although Calamares will
|
||||||
|
* complain that they are missing, then.
|
||||||
|
*/
|
||||||
|
function onActivate() { }
|
||||||
|
function onLeave() { }
|
||||||
|
|
||||||
|
|
||||||
|
/* A presentation is an Item: it has no visual appearance at all.
|
||||||
|
* Give it a background, which fills the whole area of the presentation.
|
||||||
|
* Setting *z* to a low value places this rectangle **behind** other
|
||||||
|
* things in the presentation -- which is correct for a background.
|
||||||
|
*
|
||||||
|
* This uses the background set in the styles section of `branding.desc`.
|
||||||
|
*/
|
||||||
|
Rectangle {
|
||||||
|
id: mybackground
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Branding.styleString(Branding.SidebarBackground)
|
||||||
|
z: -1
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The *ImageSlide* is a component unique to this branding directory.
|
||||||
|
* The QML file `ImageSlide.qml` can be stored alongside `show.qml`
|
||||||
|
* and it will be loaded on-demand. See the documentation in that
|
||||||
|
* file for details, but it comes down to this: for each *ImageSlide*,
|
||||||
|
* set *src* to a suitable value (an image path in this directory)
|
||||||
|
* and that will be displayed.
|
||||||
|
*/
|
||||||
|
ImageSlide {
|
||||||
|
src: "slide1.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageSlide {
|
||||||
|
src: "slide2.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageSlide {
|
||||||
|
src: "slide3.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
branding/image-slideshow/slide1.png
Normal file
BIN
branding/image-slideshow/slide1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
branding/image-slideshow/slide2.png
Normal file
BIN
branding/image-slideshow/slide2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
branding/image-slideshow/slide3.png
Normal file
BIN
branding/image-slideshow/slide3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -10,6 +10,7 @@
|
|||||||
# NOTE: this is largely a copy of the release script for Calamares,
|
# NOTE: this is largely a copy of the release script for Calamares,
|
||||||
# with not-applicable parts (such as translation-freeze) either
|
# with not-applicable parts (such as translation-freeze) either
|
||||||
# commented-out, or skipped with if(false).
|
# commented-out, or skipped with if(false).
|
||||||
|
# NOTE: this script contains Linuxisms (in particular, expects GNU mktemp(1))
|
||||||
#
|
#
|
||||||
# This attempts to perform the different steps of the RELEASE.md
|
# This attempts to perform the different steps of the RELEASE.md
|
||||||
# document automatically. It's not tested on other machines or
|
# document automatically. It's not tested on other machines or
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
# * `-B` do not build (before tagging)
|
# * `-B` do not build (before tagging)
|
||||||
# * `-P` do not package (tag, sign, tarball)
|
# * `-P` do not package (tag, sign, tarball)
|
||||||
# * `-T` do not respect string freeze
|
# * `-T` do not respect string freeze
|
||||||
|
# * `-C <args>` set extra arguments to pass to CMake
|
||||||
#
|
#
|
||||||
# The build / package settings can be influenced via environment variables:
|
# The build / package settings can be influenced via environment variables:
|
||||||
# * BUILD_DEFAULT set to `false` to avoid first build with gcc
|
# * BUILD_DEFAULT set to `false` to avoid first build with gcc
|
||||||
|
|||||||
17
ci/astylerc
Normal file
17
ci/astylerc
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
# Do not create a backup file
|
||||||
|
suffix=none
|
||||||
|
|
||||||
|
indent=spaces=4
|
||||||
|
|
||||||
|
# Brackets
|
||||||
|
style=break
|
||||||
|
add-brackets
|
||||||
|
|
||||||
|
# Spaces
|
||||||
|
pad-paren-in
|
||||||
|
pad-header
|
||||||
|
align-pointer=type
|
||||||
77
ci/calamaresstyle
Executable file
77
ci/calamaresstyle
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
#
|
||||||
|
# Calls astyle with settings matching Calamares coding style
|
||||||
|
# Requires astyle >= 2.04 and clang-format-7 -8 or -9
|
||||||
|
#
|
||||||
|
# Clang-format-10 is **not** supported, since it changes a default
|
||||||
|
# that re-introduces a space into empty function bodies; this
|
||||||
|
# can be turned off with a style setting, but that breaks
|
||||||
|
# older format versions which don't recognize the setting.
|
||||||
|
#
|
||||||
|
# You can pass in directory names, in which case the files
|
||||||
|
# in that directory (NOT below it) are processed.
|
||||||
|
#
|
||||||
|
LANG=C
|
||||||
|
LC_ALL=C
|
||||||
|
LC_NUMERIC=C
|
||||||
|
export LANG LC_ALL LC_NUMERIC
|
||||||
|
|
||||||
|
AS=$( which astyle )
|
||||||
|
|
||||||
|
CF_VERSIONS="clang-format-7 clang-format-8 clang-format70 clang-format80 clang-format90 clang-format-9.0.1 clang-format"
|
||||||
|
for _cf in $CF_VERSIONS
|
||||||
|
do
|
||||||
|
# Not an error if this particular clang-format isn't found
|
||||||
|
CF=$( which $_cf 2> /dev/null || true )
|
||||||
|
test -n "$CF" && break
|
||||||
|
done
|
||||||
|
|
||||||
|
test -n "$AS" || { echo "! No astyle found in PATH"; exit 1 ; }
|
||||||
|
test -n "$CF" || { echo "! No clang-format ($CF_VERSIONS) found in PATH"; exit 1 ; }
|
||||||
|
test -x "$AS" || { echo "! $AS is not executable."; exit 1 ; }
|
||||||
|
test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; }
|
||||||
|
|
||||||
|
unmangle_clang_format=""
|
||||||
|
if expr `"$CF" --version | tr -dc '[^.0-9]' | cut -d . -f 1` '<' 10 > /dev/null ; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
unmangle_clang_format=$( dirname $0 )/../.clang-format
|
||||||
|
echo "SpaceInEmptyBlock: false" >> "$unmangle_clang_format"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
any_dirs=no
|
||||||
|
for d in "$@"
|
||||||
|
do
|
||||||
|
test -d "$d" && any_dirs=yes
|
||||||
|
done
|
||||||
|
|
||||||
|
style_some()
|
||||||
|
{
|
||||||
|
if test -n "$*" ; then
|
||||||
|
$AS --options=$(dirname $0)/astylerc --quiet "$@"
|
||||||
|
$CF -i -style=file "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if test "x$any_dirs" = "xyes" ; then
|
||||||
|
for d in "$@"
|
||||||
|
do
|
||||||
|
if test -d "$d" ; then
|
||||||
|
style_some $( find "$d" -maxdepth 1 -type f -name '*.cpp' -o -name '*.h' )
|
||||||
|
else
|
||||||
|
style_some "$d"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
style_some "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$unmangle_clang_format" ; then
|
||||||
|
sed -i.bak '/^SpaceInEmptyBlock/d' "$unmangle_clang_format"
|
||||||
|
fi
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "PartitionJob.h"
|
||||||
|
#include "UsersJob.h"
|
||||||
|
|
||||||
|
#include "ViewManager.h"
|
||||||
|
#include "utils/Variant.h"
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
Config::Config( QObject* parent )
|
Config::Config( QObject* parent )
|
||||||
@@ -8,37 +14,113 @@ Config::Config( QObject* parent )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
|
||||||
cfgStr( const QVariantMap& cfgMap, QString key, QString defaultStr )
|
|
||||||
{
|
|
||||||
QString ret = cfgMap.value( key ).toString();
|
|
||||||
if ( ret.isEmpty() )
|
|
||||||
{
|
|
||||||
return defaultStr;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Config::setConfigurationMap( const QVariantMap& cfgMap )
|
Config::setConfigurationMap( const QVariantMap& cfgMap )
|
||||||
{
|
{
|
||||||
m_osName = cfgStr( cfgMap, "osName", "(unknown)" );
|
using namespace CalamaresUtils;
|
||||||
m_arch = cfgStr( cfgMap, "arch", "(unknown)" );
|
|
||||||
m_device = cfgStr( cfgMap, "device", "(unknown)" );
|
|
||||||
m_userInterface = cfgStr( cfgMap, "userInterface", "(unknown)" );
|
|
||||||
m_version = cfgStr( cfgMap, "version", "(unknown)" );
|
|
||||||
m_username = cfgStr( cfgMap, "username", "user" );
|
|
||||||
|
|
||||||
m_cmdLuksFormat = cfgStr( cfgMap, "cmdLuksFormat", "cryptsetup luksFormat --use-random" );
|
m_osName = getString( cfgMap, "osName", "(unknown)" );
|
||||||
m_cmdLuksOpen = cfgStr( cfgMap, "cmdLuksOpen", "cryptsetup luksOpen" );
|
m_arch = getString( cfgMap, "arch", "(unknown)" );
|
||||||
m_cmdMkfsRoot = cfgStr( cfgMap, "cmdMkfsRoot", "mkfs.ext4 -L 'unknownOS_root'" );
|
m_device = getString( cfgMap, "device", "(unknown)" );
|
||||||
m_cmdMount = cfgStr( cfgMap, "cmdMount", "mount" );
|
m_userInterface = getString( cfgMap, "userInterface", "(unknown)" );
|
||||||
m_targetDeviceRoot = cfgStr( cfgMap, "targetDeviceRoot", "/dev/unknown" );
|
m_version = getString( cfgMap, "version", "(unknown)" );
|
||||||
|
m_username = getString( cfgMap, "username", "user" );
|
||||||
|
|
||||||
m_cmdPasswd = cfgStr( cfgMap, "cmdPasswd", "passwd" );
|
m_featureSshd = getBool( cfgMap, "featureSshd", true );
|
||||||
m_cmdSshdEnable = cfgStr( cfgMap, "cmdSshdEnable", "systemctl enable sshd.service" );
|
m_featureFsType = getBool( cfgMap, "featureFsType", false );
|
||||||
m_cmdSshdDisable = cfgStr( cfgMap, "cmdSshdDisable", "systemctl disable sshd.service" );
|
|
||||||
m_cmdSshdUseradd = cfgStr( cfgMap, "cmdSshdUseradd", "useradd -G wheel -m" );
|
m_cmdLuksFormat = getString( cfgMap, "cmdLuksFormat", "cryptsetup luksFormat --use-random" );
|
||||||
|
m_cmdLuksOpen = getString( cfgMap, "cmdLuksOpen", "cryptsetup luksOpen" );
|
||||||
|
m_cmdMount = getString( cfgMap, "cmdMount", "mount" );
|
||||||
|
m_targetDeviceRoot = getString( cfgMap, "targetDeviceRoot", "/dev/unknown" );
|
||||||
|
m_targetDeviceRootInternal = getString( cfgMap, "targetDeviceRootInternal", "" );
|
||||||
|
|
||||||
|
m_cmdMkfsRootBtrfs = getString( cfgMap, "cmdMkfsRootBtrfs", "mkfs.btrfs -L 'unknownOS_root'" );
|
||||||
|
m_cmdMkfsRootExt4 = getString( cfgMap, "cmdMkfsRootExt4", "mkfs.ext4 -L 'unknownOS_root'" );
|
||||||
|
m_cmdMkfsRootF2fs = getString( cfgMap, "cmdMkfsRootF2fs", "mkfs.f2fs -l 'unknownOS_root'" );
|
||||||
|
m_fsList = getStringList( cfgMap, "fsModel", QStringList { "ext4", "f2fs", "btrfs" } );
|
||||||
|
m_defaultFs = getString( cfgMap, "defaultFs", "ext4" );
|
||||||
|
m_fsIndex = m_fsList.indexOf( m_defaultFs );
|
||||||
|
m_fsType = m_defaultFs;
|
||||||
|
|
||||||
|
m_cmdInternalStoragePrepare = getString( cfgMap, "cmdInternalStoragePrepare", "ondev-internal-storage-prepare" );
|
||||||
|
m_cmdPasswd = getString( cfgMap, "cmdPasswd", "passwd" );
|
||||||
|
m_cmdSshdEnable = getString( cfgMap, "cmdSshdEnable", "systemctl enable sshd.service" );
|
||||||
|
m_cmdSshdDisable = getString( cfgMap, "cmdSshdDisable", "systemctl disable sshd.service" );
|
||||||
|
m_cmdSshdUseradd = getString( cfgMap, "cmdSshdUseradd", "useradd -G wheel -m" );
|
||||||
|
}
|
||||||
|
|
||||||
|
Calamares::JobList
|
||||||
|
Config::createJobs()
|
||||||
|
{
|
||||||
|
QList< Calamares::job_ptr > list;
|
||||||
|
QString cmdSshd = m_isSshEnabled ? m_cmdSshdEnable : m_cmdSshdDisable;
|
||||||
|
|
||||||
|
/* Put users job in queue (should run after unpackfs) */
|
||||||
|
Calamares::Job* j = new UsersJob( m_featureSshd,
|
||||||
|
m_cmdPasswd,
|
||||||
|
cmdSshd,
|
||||||
|
m_cmdSshdUseradd,
|
||||||
|
m_isSshEnabled,
|
||||||
|
m_username,
|
||||||
|
m_userPassword,
|
||||||
|
m_sshdUsername,
|
||||||
|
m_sshdPassword );
|
||||||
|
list.append( Calamares::job_ptr( j ) );
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::runPartitionJobThenLeave( bool b )
|
||||||
|
{
|
||||||
|
Calamares::ViewManager* v = Calamares::ViewManager::instance();
|
||||||
|
QString cmdMkfsRoot;
|
||||||
|
if ( m_fsType == QStringLiteral( "btrfs" ) )
|
||||||
|
{
|
||||||
|
cmdMkfsRoot = m_cmdMkfsRootBtrfs;
|
||||||
|
}
|
||||||
|
else if ( m_fsType == QStringLiteral( "f2fs" ) )
|
||||||
|
{
|
||||||
|
cmdMkfsRoot = m_cmdMkfsRootF2fs;
|
||||||
|
}
|
||||||
|
else if ( m_fsType == QStringLiteral( "ext4" ) )
|
||||||
|
{
|
||||||
|
cmdMkfsRoot = m_cmdMkfsRootExt4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v->onInstallationFailed( "Unknown filesystem: '" + m_fsType + "'", "" );
|
||||||
|
}
|
||||||
|
/* HACK: run partition job
|
||||||
|
* The "mobile" module has two jobs, the partition job and the users job.
|
||||||
|
* If we added both of them in Config::createJobs(), Calamares would run
|
||||||
|
* them right after each other. But we need the "unpackfs" module to run
|
||||||
|
* inbetween, that's why as workaround, the partition job is started here.
|
||||||
|
* To solve this properly, we would need to place the partition job in an
|
||||||
|
* own module and pass everything via globalstorage. But then we might as
|
||||||
|
* well refactor everything so we can unify the mobile's partition job with
|
||||||
|
* the proper partition job from Calamares. */
|
||||||
|
Calamares::Job* j = new PartitionJob( m_cmdInternalStoragePrepare,
|
||||||
|
m_cmdLuksFormat,
|
||||||
|
m_cmdLuksOpen,
|
||||||
|
cmdMkfsRoot,
|
||||||
|
m_cmdMount,
|
||||||
|
m_targetDeviceRoot,
|
||||||
|
m_targetDeviceRootInternal,
|
||||||
|
m_installFromExternalToInternal,
|
||||||
|
m_isFdeEnabled,
|
||||||
|
m_fdePassword );
|
||||||
|
Calamares::JobResult res = j->exec();
|
||||||
|
|
||||||
|
if ( res )
|
||||||
|
{
|
||||||
|
v->next();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v->onInstallationFailed( res.message(), res.details() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -80,3 +162,34 @@ Config::setIsFdeEnabled( const bool isFdeEnabled )
|
|||||||
{
|
{
|
||||||
m_isFdeEnabled = isFdeEnabled;
|
m_isFdeEnabled = isFdeEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setInstallFromExternalToInternal( const bool val )
|
||||||
|
{
|
||||||
|
m_installFromExternalToInternal = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setFsType( int idx )
|
||||||
|
{
|
||||||
|
if ( idx >= 0 && idx < m_fsList.length() )
|
||||||
|
{
|
||||||
|
setFsType( m_fsList[ idx ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void
|
||||||
|
Config::setFsType( const QString& fsType )
|
||||||
|
{
|
||||||
|
if ( fsType != m_fsType )
|
||||||
|
{
|
||||||
|
m_fsType = fsType;
|
||||||
|
emit fsTypeChanged( m_fsType );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::setFsIndex( const int fsIndex )
|
||||||
|
{
|
||||||
|
m_fsIndex = fsIndex;
|
||||||
|
emit fsIndexChanged( m_fsIndex );
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Job.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -19,6 +22,7 @@ class Config : public QObject
|
|||||||
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
|
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
|
||||||
|
|
||||||
/* ssh server + credentials */
|
/* ssh server + credentials */
|
||||||
|
Q_PROPERTY( bool featureSshd READ featureSshd CONSTANT FINAL )
|
||||||
Q_PROPERTY( QString sshdUsername READ sshdUsername WRITE setSshdUsername NOTIFY sshdUsernameChanged )
|
Q_PROPERTY( QString sshdUsername READ sshdUsername WRITE setSshdUsername NOTIFY sshdUsernameChanged )
|
||||||
Q_PROPERTY( QString sshdPassword READ sshdPassword WRITE setSshdPassword NOTIFY sshdPasswordChanged )
|
Q_PROPERTY( QString sshdPassword READ sshdPassword WRITE setSshdPassword NOTIFY sshdPasswordChanged )
|
||||||
Q_PROPERTY( bool isSshEnabled READ isSshEnabled WRITE setIsSshEnabled )
|
Q_PROPERTY( bool isSshEnabled READ isSshEnabled WRITE setIsSshEnabled )
|
||||||
@@ -27,12 +31,23 @@ class Config : public QObject
|
|||||||
Q_PROPERTY( QString fdePassword READ fdePassword WRITE setFdePassword NOTIFY fdePasswordChanged )
|
Q_PROPERTY( QString fdePassword READ fdePassword WRITE setFdePassword NOTIFY fdePasswordChanged )
|
||||||
Q_PROPERTY( bool isFdeEnabled READ isFdeEnabled WRITE setIsFdeEnabled )
|
Q_PROPERTY( bool isFdeEnabled READ isFdeEnabled WRITE setIsFdeEnabled )
|
||||||
|
|
||||||
|
/* filesystem selection */
|
||||||
|
Q_PROPERTY( QString fsType READ fsType WRITE setFsType NOTIFY fsTypeChanged )
|
||||||
|
Q_PROPERTY( bool featureFsType READ featureFsType CONSTANT FINAL )
|
||||||
|
Q_PROPERTY( QStringList fsList READ fsList CONSTANT FINAL )
|
||||||
|
Q_PROPERTY( QString defaultFs READ defaultFs CONSTANT FINAL )
|
||||||
|
Q_PROPERTY( int fsIndex READ fsIndex WRITE setFsIndex NOTIFY fsIndexChanged )
|
||||||
|
|
||||||
/* partition job */
|
/* partition job */
|
||||||
|
Q_PROPERTY( bool runPartitionJobThenLeave READ runPartitionJobThenLeaveDummy WRITE runPartitionJobThenLeave )
|
||||||
|
Q_PROPERTY( QString cmdInternalStoragePrepare READ cmdInternalStoragePrepare CONSTANT FINAL )
|
||||||
Q_PROPERTY( QString cmdLuksFormat READ cmdLuksFormat CONSTANT FINAL )
|
Q_PROPERTY( QString cmdLuksFormat READ cmdLuksFormat CONSTANT FINAL )
|
||||||
Q_PROPERTY( QString cmdLuksOpen READ cmdLuksOpen CONSTANT FINAL )
|
Q_PROPERTY( QString cmdLuksOpen READ cmdLuksOpen CONSTANT FINAL )
|
||||||
Q_PROPERTY( QString cmdMkfsRoot READ cmdMkfsRoot CONSTANT FINAL )
|
|
||||||
Q_PROPERTY( QString cmdMount READ cmdMount CONSTANT FINAL )
|
Q_PROPERTY( QString cmdMount READ cmdMount CONSTANT FINAL )
|
||||||
Q_PROPERTY( QString targetDeviceRoot READ targetDeviceRoot CONSTANT FINAL )
|
Q_PROPERTY( QString targetDeviceRoot READ targetDeviceRoot CONSTANT FINAL )
|
||||||
|
Q_PROPERTY( QString targetDeviceRootInternal READ targetDeviceRootInternal CONSTANT FINAL )
|
||||||
|
Q_PROPERTY(
|
||||||
|
bool installFromExternalToInternal READ installFromExternalToInternal WRITE setInstallFromExternalToInternal )
|
||||||
|
|
||||||
/* users job */
|
/* users job */
|
||||||
Q_PROPERTY( QString cmdSshdEnable READ cmdSshdEnable CONSTANT FINAL )
|
Q_PROPERTY( QString cmdSshdEnable READ cmdSshdEnable CONSTANT FINAL )
|
||||||
@@ -41,6 +56,7 @@ class Config : public QObject
|
|||||||
public:
|
public:
|
||||||
Config( QObject* parent = nullptr );
|
Config( QObject* parent = nullptr );
|
||||||
void setConfigurationMap( const QVariantMap& );
|
void setConfigurationMap( const QVariantMap& );
|
||||||
|
Calamares::JobList createJobs();
|
||||||
|
|
||||||
/* welcome */
|
/* welcome */
|
||||||
QString osName() const { return m_osName; }
|
QString osName() const { return m_osName; }
|
||||||
@@ -55,6 +71,7 @@ public:
|
|||||||
void setUserPassword( const QString& userPassword );
|
void setUserPassword( const QString& userPassword );
|
||||||
|
|
||||||
/* ssh server + credetials */
|
/* ssh server + credetials */
|
||||||
|
bool featureSshd() { return m_featureSshd; }
|
||||||
QString sshdUsername() const { return m_sshdUsername; }
|
QString sshdUsername() const { return m_sshdUsername; }
|
||||||
QString sshdPassword() const { return m_sshdPassword; }
|
QString sshdPassword() const { return m_sshdPassword; }
|
||||||
bool isSshEnabled() { return m_isSshEnabled; }
|
bool isSshEnabled() { return m_isSshEnabled; }
|
||||||
@@ -68,12 +85,30 @@ public:
|
|||||||
void setFdePassword( const QString& fdePassword );
|
void setFdePassword( const QString& fdePassword );
|
||||||
void setIsFdeEnabled( bool isFdeEnabled );
|
void setIsFdeEnabled( bool isFdeEnabled );
|
||||||
|
|
||||||
|
/* filesystem selection */
|
||||||
|
bool featureFsType() { return m_featureFsType; };
|
||||||
|
QString fsType() const { return m_fsType; };
|
||||||
|
void setFsType( int idx );
|
||||||
|
void setFsType( const QString& fsType );
|
||||||
|
QStringList fsList() const { return m_fsList; };
|
||||||
|
int fsIndex() const { return m_fsIndex; };
|
||||||
|
void setFsIndex( const int fsIndex );
|
||||||
|
QString defaultFs() const { return m_defaultFs; };
|
||||||
|
|
||||||
/* partition job */
|
/* partition job */
|
||||||
|
bool runPartitionJobThenLeaveDummy() { return 0; }
|
||||||
|
void runPartitionJobThenLeave( bool b );
|
||||||
|
QString cmdInternalStoragePrepare() const { return m_cmdInternalStoragePrepare; }
|
||||||
QString cmdLuksFormat() const { return m_cmdLuksFormat; }
|
QString cmdLuksFormat() const { return m_cmdLuksFormat; }
|
||||||
QString cmdLuksOpen() const { return m_cmdLuksOpen; }
|
QString cmdLuksOpen() const { return m_cmdLuksOpen; }
|
||||||
QString cmdMkfsRoot() const { return m_cmdMkfsRoot; }
|
QString cmdMkfsRootBtrfs() const { return m_cmdMkfsRootBtrfs; }
|
||||||
|
QString cmdMkfsRootExt4() const { return m_cmdMkfsRootExt4; }
|
||||||
|
QString cmdMkfsRootF2fs() const { return m_cmdMkfsRootF2fs; }
|
||||||
QString cmdMount() const { return m_cmdMount; }
|
QString cmdMount() const { return m_cmdMount; }
|
||||||
QString targetDeviceRoot() const { return m_targetDeviceRoot; }
|
QString targetDeviceRoot() const { return m_targetDeviceRoot; }
|
||||||
|
QString targetDeviceRootInternal() const { return m_targetDeviceRootInternal; }
|
||||||
|
bool installFromExternalToInternal() { return m_installFromExternalToInternal; }
|
||||||
|
void setInstallFromExternalToInternal( const bool val );
|
||||||
|
|
||||||
/* users job */
|
/* users job */
|
||||||
QString cmdPasswd() const { return m_cmdPasswd; }
|
QString cmdPasswd() const { return m_cmdPasswd; }
|
||||||
@@ -94,6 +129,7 @@ private:
|
|||||||
QString m_userPassword;
|
QString m_userPassword;
|
||||||
|
|
||||||
/* ssh server + credetials */
|
/* ssh server + credetials */
|
||||||
|
bool m_featureSshd;
|
||||||
QString m_sshdUsername;
|
QString m_sshdUsername;
|
||||||
QString m_sshdPassword;
|
QString m_sshdPassword;
|
||||||
bool m_isSshEnabled;
|
bool m_isSshEnabled;
|
||||||
@@ -102,12 +138,25 @@ private:
|
|||||||
QString m_fdePassword = "";
|
QString m_fdePassword = "";
|
||||||
bool m_isFdeEnabled = false;
|
bool m_isFdeEnabled = false;
|
||||||
|
|
||||||
|
/* filesystem selection */
|
||||||
|
bool m_featureFsType;
|
||||||
|
QString m_defaultFs;
|
||||||
|
QString m_fsType;
|
||||||
|
// Index of the currently selected filesystem in UI.
|
||||||
|
int m_fsIndex;
|
||||||
|
QStringList m_fsList;
|
||||||
|
|
||||||
/* partition job */
|
/* partition job */
|
||||||
|
QString m_cmdInternalStoragePrepare;
|
||||||
QString m_cmdLuksFormat;
|
QString m_cmdLuksFormat;
|
||||||
QString m_cmdLuksOpen;
|
QString m_cmdLuksOpen;
|
||||||
QString m_cmdMkfsRoot;
|
QString m_cmdMkfsRootBtrfs;
|
||||||
|
QString m_cmdMkfsRootExt4;
|
||||||
|
QString m_cmdMkfsRootF2fs;
|
||||||
QString m_cmdMount;
|
QString m_cmdMount;
|
||||||
QString m_targetDeviceRoot;
|
QString m_targetDeviceRoot;
|
||||||
|
QString m_targetDeviceRootInternal;
|
||||||
|
bool m_installFromExternalToInternal = false;
|
||||||
|
|
||||||
/* users job */
|
/* users job */
|
||||||
QString m_cmdPasswd;
|
QString m_cmdPasswd;
|
||||||
@@ -116,14 +165,18 @@ private:
|
|||||||
QString m_cmdSshdUseradd;
|
QString m_cmdSshdUseradd;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/* booleans we don't read from QML (like isSshEnabled) don't need a signal */
|
||||||
|
|
||||||
/* default user */
|
/* default user */
|
||||||
void userPasswordChanged( QString userPassword );
|
void userPasswordChanged( QString userPassword );
|
||||||
|
|
||||||
/* ssh server + credetials */
|
/* ssh server + credentials */
|
||||||
void sshdUsernameChanged( QString sshdUsername );
|
void sshdUsernameChanged( QString sshdUsername );
|
||||||
void sshdPasswordChanged( QString sshdPassword );
|
void sshdPasswordChanged( QString sshdPassword );
|
||||||
/* isSshEnabled doesn't need a signal, we don't read it from QML */
|
|
||||||
|
|
||||||
/* full disk encryption */
|
/* full disk encryption */
|
||||||
void fdePasswordChanged( QString fdePassword );
|
void fdePasswordChanged( QString fdePassword );
|
||||||
|
|
||||||
|
void fsTypeChanged( QString fsType );
|
||||||
|
void fsIndexChanged( int fsIndex );
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
#include "MobileQmlViewStep.h"
|
#include "MobileQmlViewStep.h"
|
||||||
#include "PartitionJob.h"
|
|
||||||
#include "UsersJob.h"
|
|
||||||
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "JobQueue.h"
|
|
||||||
|
|
||||||
#include "locale/LabelModel.h"
|
#include "locale/LabelModel.h"
|
||||||
#include "utils/Dirs.h"
|
#include "utils/Dirs.h"
|
||||||
@@ -35,34 +32,7 @@ MobileQmlViewStep::MobileQmlViewStep( QObject* parent )
|
|||||||
void
|
void
|
||||||
MobileQmlViewStep::onLeave()
|
MobileQmlViewStep::onLeave()
|
||||||
{
|
{
|
||||||
Calamares::Job *partition, *users;
|
return;
|
||||||
|
|
||||||
/* HACK: run partition job now */
|
|
||||||
partition = new PartitionJob( m_config->cmdLuksFormat(),
|
|
||||||
m_config->cmdLuksOpen(),
|
|
||||||
m_config->cmdMkfsRoot(),
|
|
||||||
m_config->cmdMount(),
|
|
||||||
m_config->targetDeviceRoot(),
|
|
||||||
m_config->isFdeEnabled(),
|
|
||||||
m_config->fdePassword() );
|
|
||||||
Calamares::JobResult res = partition->exec();
|
|
||||||
if ( !res )
|
|
||||||
{
|
|
||||||
cError() << "PARTITION JOB FAILED: " << res.message();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put users job in queue (should run after unpackfs) */
|
|
||||||
m_jobs.clear();
|
|
||||||
QString cmdSshd = m_config->isSshEnabled() ? m_config->cmdSshdEnable() : m_config->cmdSshdDisable();
|
|
||||||
users = new UsersJob( m_config->cmdPasswd(),
|
|
||||||
cmdSshd,
|
|
||||||
m_config->cmdSshdUseradd(),
|
|
||||||
m_config->isSshEnabled(),
|
|
||||||
m_config->username(),
|
|
||||||
m_config->userPassword(),
|
|
||||||
m_config->sshdUsername(),
|
|
||||||
m_config->sshdPassword() );
|
|
||||||
m_jobs.append( Calamares::job_ptr( users ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -95,7 +65,7 @@ MobileQmlViewStep::isAtEnd() const
|
|||||||
Calamares::JobList
|
Calamares::JobList
|
||||||
MobileQmlViewStep::jobs() const
|
MobileQmlViewStep::jobs() const
|
||||||
{
|
{
|
||||||
return m_jobs;
|
return m_config->createJobs();
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject*
|
QObject*
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Config* m_config;
|
Config* m_config;
|
||||||
QList< Calamares::job_ptr > m_jobs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( MobileQmlViewStepFactory )
|
CALAMARES_PLUGIN_FACTORY_DECLARATION( MobileQmlViewStepFactory )
|
||||||
|
|||||||
@@ -12,19 +12,25 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
|
||||||
PartitionJob::PartitionJob( QString cmdLuksFormat,
|
PartitionJob::PartitionJob( const QString& cmdInternalStoragePrepare,
|
||||||
QString cmdLuksOpen,
|
const QString& cmdLuksFormat,
|
||||||
QString cmdMkfsRoot,
|
const QString& cmdLuksOpen,
|
||||||
QString cmdMount,
|
const QString& cmdMkfsRoot,
|
||||||
QString targetDeviceRoot,
|
const QString& cmdMount,
|
||||||
|
const QString& targetDeviceRoot,
|
||||||
|
const QString& targetDeviceRootInternal,
|
||||||
|
bool installFromExternalToInternal,
|
||||||
bool isFdeEnabled,
|
bool isFdeEnabled,
|
||||||
const QString& password )
|
const QString& password )
|
||||||
: Calamares::Job()
|
: Calamares::Job()
|
||||||
|
, m_cmdInternalStoragePrepare( cmdInternalStoragePrepare )
|
||||||
, m_cmdLuksFormat( cmdLuksFormat )
|
, m_cmdLuksFormat( cmdLuksFormat )
|
||||||
, m_cmdLuksOpen( cmdLuksOpen )
|
, m_cmdLuksOpen( cmdLuksOpen )
|
||||||
, m_cmdMkfsRoot( cmdMkfsRoot )
|
, m_cmdMkfsRoot( cmdMkfsRoot )
|
||||||
, m_cmdMount( cmdMount )
|
, m_cmdMount( cmdMount )
|
||||||
, m_targetDeviceRoot( targetDeviceRoot )
|
, m_targetDeviceRoot( targetDeviceRoot )
|
||||||
|
, m_targetDeviceRootInternal( targetDeviceRootInternal )
|
||||||
|
, m_installFromExternalToInternal( installFromExternalToInternal )
|
||||||
, m_isFdeEnabled( isFdeEnabled )
|
, m_isFdeEnabled( isFdeEnabled )
|
||||||
, m_password( password )
|
, m_password( password )
|
||||||
{
|
{
|
||||||
@@ -77,10 +83,18 @@ PartitionJob::exec()
|
|||||||
QString cryptDev = "/dev/mapper/" + cryptName;
|
QString cryptDev = "/dev/mapper/" + cryptName;
|
||||||
QString passwordStdin = m_password + "\n";
|
QString passwordStdin = m_password + "\n";
|
||||||
QString dev = m_targetDeviceRoot;
|
QString dev = m_targetDeviceRoot;
|
||||||
|
QList< QPair< QStringList, QString > > commands = {};
|
||||||
|
|
||||||
QList< QPair< QStringList, QString > > commands = {
|
if ( m_installFromExternalToInternal )
|
||||||
{ { "mkdir", "-p", pathMount }, QString() },
|
{
|
||||||
};
|
dev = m_targetDeviceRootInternal;
|
||||||
|
|
||||||
|
commands.append( {
|
||||||
|
{ { "sh", "-c", m_cmdInternalStoragePrepare }, QString() },
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.append( { { { "mkdir", "-p", pathMount }, QString() } } );
|
||||||
|
|
||||||
if ( m_isFdeEnabled )
|
if ( m_isFdeEnabled )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ class PartitionJob : public Calamares::Job
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PartitionJob( QString cmdLuksFormat,
|
PartitionJob( const QString& cmdInternalStoragePrepare,
|
||||||
QString cmdLuksOpen,
|
const QString& cmdLuksFormat,
|
||||||
QString cmdMkfsRoot,
|
const QString& cmdLuksOpen,
|
||||||
QString cmdMount,
|
const QString& cmdMkfsRoot,
|
||||||
QString targetDeviceRoot,
|
const QString& cmdMount,
|
||||||
|
const QString& targetDeviceRoot,
|
||||||
|
const QString& targetDeviceRootInternal,
|
||||||
|
bool installFromExternalToInternal,
|
||||||
bool isFdeEnabled,
|
bool isFdeEnabled,
|
||||||
const QString& password );
|
const QString& password );
|
||||||
|
|
||||||
@@ -22,11 +25,14 @@ public:
|
|||||||
Calamares::JobList createJobs();
|
Calamares::JobList createJobs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString m_cmdInternalStoragePrepare;
|
||||||
QString m_cmdLuksFormat;
|
QString m_cmdLuksFormat;
|
||||||
QString m_cmdLuksOpen;
|
QString m_cmdLuksOpen;
|
||||||
QString m_cmdMkfsRoot;
|
QString m_cmdMkfsRoot;
|
||||||
QString m_cmdMount;
|
QString m_cmdMount;
|
||||||
QString m_targetDeviceRoot;
|
QString m_targetDeviceRoot;
|
||||||
|
QString m_targetDeviceRootInternal;
|
||||||
|
bool m_installFromExternalToInternal;
|
||||||
bool m_isFdeEnabled;
|
bool m_isFdeEnabled;
|
||||||
QString m_password;
|
QString m_password;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,15 +12,17 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
|
||||||
UsersJob::UsersJob( QString cmdPasswd,
|
UsersJob::UsersJob( bool featureSshd,
|
||||||
QString cmdSshd,
|
const QString& cmdPasswd,
|
||||||
QString cmdSshdUseradd,
|
const QString& cmdSshd,
|
||||||
|
const QString& cmdSshdUseradd,
|
||||||
bool isSshEnabled,
|
bool isSshEnabled,
|
||||||
QString username,
|
const QString& username,
|
||||||
QString password,
|
const QString& password,
|
||||||
QString sshdUsername,
|
const QString& sshdUsername,
|
||||||
QString sshdPassword )
|
const QString& sshdPassword )
|
||||||
: Calamares::Job()
|
: Calamares::Job()
|
||||||
|
, m_featureSshd( featureSshd )
|
||||||
, m_cmdPasswd( cmdPasswd )
|
, m_cmdPasswd( cmdPasswd )
|
||||||
, m_cmdSshd( cmdSshd )
|
, m_cmdSshd( cmdSshd )
|
||||||
, m_cmdSshdUseradd( cmdSshdUseradd )
|
, m_cmdSshdUseradd( cmdSshdUseradd )
|
||||||
@@ -48,14 +50,18 @@ UsersJob::exec()
|
|||||||
|
|
||||||
QList< QPair< QStringList, QString > > commands = {
|
QList< QPair< QStringList, QString > > commands = {
|
||||||
{ { "sh", "-c", m_cmdPasswd + " " + m_username }, m_password + "\n" + m_password + "\n" },
|
{ { "sh", "-c", m_cmdPasswd + " " + m_username }, m_password + "\n" + m_password + "\n" },
|
||||||
{ { "sh", "-c", m_cmdSshd }, QString() },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( m_isSshEnabled )
|
if ( m_featureSshd )
|
||||||
{
|
{
|
||||||
commands.append( { { "sh", "-c", m_cmdSshdUseradd + " " + m_sshdUsername }, QString() } );
|
commands.append( { { "sh", "-c", m_cmdSshd }, QString() } );
|
||||||
commands.append(
|
|
||||||
{ { "sh", "-c", m_cmdPasswd + " " + m_sshdUsername }, m_sshdPassword + "\n" + m_sshdPassword + "\n" } );
|
if ( m_isSshEnabled )
|
||||||
|
{
|
||||||
|
commands.append( { { "sh", "-c", m_cmdSshdUseradd + " " + m_sshdUsername }, QString() } );
|
||||||
|
commands.append(
|
||||||
|
{ { "sh", "-c", m_cmdPasswd + " " + m_sshdUsername }, m_sshdPassword + "\n" + m_sshdPassword + "\n" } );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( auto command, commands )
|
foreach ( auto command, commands )
|
||||||
|
|||||||
@@ -8,14 +8,15 @@ class UsersJob : public Calamares::Job
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
UsersJob( QString cmdPasswd,
|
UsersJob( bool featureSshd,
|
||||||
QString cmdSshd,
|
const QString& cmdPasswd,
|
||||||
QString cmdSshdUseradd,
|
const QString& cmdSshd,
|
||||||
|
const QString& cmdSshdUseradd,
|
||||||
bool isSshEnabled,
|
bool isSshEnabled,
|
||||||
QString username,
|
const QString& username,
|
||||||
QString password,
|
const QString& password,
|
||||||
QString sshdUsername,
|
const QString& sshdUsername,
|
||||||
QString sshdPassword );
|
const QString& sshdPassword );
|
||||||
|
|
||||||
QString prettyName() const override;
|
QString prettyName() const override;
|
||||||
Calamares::JobResult exec() override;
|
Calamares::JobResult exec() override;
|
||||||
@@ -23,6 +24,7 @@ public:
|
|||||||
Calamares::JobList createJobs();
|
Calamares::JobList createJobs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_featureSshd;
|
||||||
QString m_cmdPasswd;
|
QString m_cmdPasswd;
|
||||||
QString m_cmdSshd;
|
QString m_cmdSshd;
|
||||||
QString m_cmdSshdUseradd;
|
QString m_cmdSshdUseradd;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ Item {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
if (validatePin(userPin, userPinRepeat, errorText)) {
|
if (validatePin(userPin, userPinRepeat, errorText)) {
|
||||||
config.userPassword = userPin.text;
|
config.userPassword = userPin.text;
|
||||||
navTo("ssh_confirm");
|
navNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Item {
|
|||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: welcomeText
|
id: mainText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 30
|
anchors.topMargin: 30
|
||||||
@@ -37,29 +37,29 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: enableButton
|
id: firstButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: welcomeText.bottom
|
anchors.top: mainText.bottom
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 40
|
||||||
width: 500
|
width: 500
|
||||||
|
|
||||||
text: qsTr("Enable")
|
text: qsTr("Enable")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
config.isFdeEnabled = true;
|
config.isFdeEnabled = true;
|
||||||
navTo("fde_pass");
|
navNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: enableButton.bottom
|
anchors.top: firstButton.bottom
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 40
|
||||||
width: 500
|
width: 500
|
||||||
|
|
||||||
text: qsTr("Disable")
|
text: qsTr("Disable")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
config.isFdeEnabled = false;
|
config.isFdeEnabled = false;
|
||||||
navTo("install_confirm");
|
navNextFeature();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ Item {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
if (validatePassword(password, passwordRepeat, errorText)) {
|
if (validatePassword(password, passwordRepeat, errorText)) {
|
||||||
config.fdePassword = password.text;
|
config.fdePassword = password.text;
|
||||||
navTo("install_confirm");
|
navNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
modules/mobile/fs_selection.qml
Normal file
59
modules/mobile/fs_selection.qml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2020 Undef <calamares@undef.tools>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
import io.calamares.core 1.0
|
||||||
|
import io.calamares.ui 1.0
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.10
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import org.kde.kirigami 2.7 as Kirigami
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Window 2.3
|
||||||
|
import QtQuick.VirtualKeyboard 2.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: mainText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 30
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
|
text: "Select the filesystem for root partition. If unsure, leave the default."
|
||||||
|
|
||||||
|
width: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: fsTypeCB
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: mainText.bottom
|
||||||
|
anchors.topMargin: 40
|
||||||
|
width: 500
|
||||||
|
height: 60
|
||||||
|
editable: false
|
||||||
|
model: config.fsList
|
||||||
|
/* Save the current state on selection so it is there when the back button is pressed */
|
||||||
|
onActivated: config.fsType = fsTypeCB.currentText;
|
||||||
|
Component.onCompleted: fsTypeCB.currentIndex = find( config.fsType, Qt.MatchContains );
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: fsTypeCB.bottom
|
||||||
|
anchors.topMargin: 40
|
||||||
|
width: 500
|
||||||
|
|
||||||
|
text: qsTr("Continue")
|
||||||
|
onClicked: {
|
||||||
|
config.fsType = fsTypeCB.currentText;
|
||||||
|
navNextFeature();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,24 +19,38 @@ Item {
|
|||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: welcomeText
|
id: mainText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 30
|
anchors.topMargin: 30
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
text: "Once you hit 'install', the installation will begin. It will" +
|
text: (function() {
|
||||||
" typically take a few minutes. Do not power off the device" +
|
var ret = "Once you hit 'install', the installation will begin." +
|
||||||
" until it is done. Afterwards, it will reboot into the" +
|
" It will typically take a few minutes. Do not power off the" +
|
||||||
" installed system."
|
" device until it is done.<br><br>";
|
||||||
|
|
||||||
|
if (config.installFromExternalToInternal) {
|
||||||
|
ret += "<b>After the installation, your device will shutdown" +
|
||||||
|
" automatically. You must remove the external storage" +
|
||||||
|
" (SD card) before booting again.</b>" +
|
||||||
|
"<br><br>" +
|
||||||
|
"Otherwise, your device will boot into the installer" +
|
||||||
|
" again, and not into the installed system."
|
||||||
|
} else {
|
||||||
|
ret += "Afterwards, it will reboot into the installed system.";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}())
|
||||||
|
|
||||||
width: 500
|
width: 500
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: enableButton
|
id: firstButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: welcomeText.bottom
|
anchors.top: mainText.bottom
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 40
|
||||||
width: 500
|
width: 500
|
||||||
|
|
||||||
|
|||||||
64
modules/mobile/install_target.qml
Normal file
64
modules/mobile/install_target.qml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
import io.calamares.core 1.0
|
||||||
|
import io.calamares.ui 1.0
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.10
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import org.kde.kirigami 2.7 as Kirigami
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Window 2.3
|
||||||
|
import QtQuick.VirtualKeyboard 2.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: mainText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 30
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
|
text: "The installation was started from an external storage medium." +
|
||||||
|
"<br>" +
|
||||||
|
"You can either install to the same medium and overwrite the" +
|
||||||
|
" installer, or install to the internal storage.<br>" +
|
||||||
|
"<br>" +
|
||||||
|
"Where would you like to install " + config.osName + "?"
|
||||||
|
|
||||||
|
width: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: firstButton
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: mainText.bottom
|
||||||
|
anchors.topMargin: 40
|
||||||
|
width: 500
|
||||||
|
|
||||||
|
text: qsTr("Internal (eMMC)")
|
||||||
|
onClicked: {
|
||||||
|
config.installFromExternalToInternal = true;
|
||||||
|
navNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: firstButton.bottom
|
||||||
|
anchors.topMargin: 40
|
||||||
|
width: 500
|
||||||
|
|
||||||
|
text: qsTr("External (SD card)")
|
||||||
|
onClicked: {
|
||||||
|
config.installFromExternalToInternal = false;
|
||||||
|
navNextFeature();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
modules/mobile/install_target_confirm.qml
Normal file
58
modules/mobile/install_target_confirm.qml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
import io.calamares.core 1.0
|
||||||
|
import io.calamares.ui 1.0
|
||||||
|
|
||||||
|
import QtQuick 2.10
|
||||||
|
import QtQuick.Controls 2.10
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import org.kde.kirigami 2.7 as Kirigami
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Window 2.3
|
||||||
|
import QtQuick.VirtualKeyboard 2.1
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: mainText
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 30
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
|
||||||
|
text: "Are you sure that you want to overwrite the internal storage?" +
|
||||||
|
"<br><br>" +
|
||||||
|
"<b>All existing data on the device will be lost!</b>"
|
||||||
|
width: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: firstButton
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: mainText.bottom
|
||||||
|
anchors.topMargin: 40
|
||||||
|
width: 500
|
||||||
|
|
||||||
|
text: qsTr("Yes")
|
||||||
|
onClicked: {
|
||||||
|
navNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: firstButton.bottom
|
||||||
|
anchors.topMargin: 40
|
||||||
|
width: 500
|
||||||
|
|
||||||
|
text: qsTr("No")
|
||||||
|
onClicked: {
|
||||||
|
navBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,9 +27,43 @@
|
|||||||
## Name of the device (e.g. PinePhone)
|
## Name of the device (e.g. PinePhone)
|
||||||
# device: "(unknown)"
|
# device: "(unknown)"
|
||||||
|
|
||||||
## Partition that will be formatted and mounted (optionally with FDE) for the rootfs
|
## Partition that will be formatted and mounted (optionally with FDE) for the
|
||||||
|
## rootfs
|
||||||
# targetDeviceRoot: "/dev/unknown"
|
# targetDeviceRoot: "/dev/unknown"
|
||||||
|
|
||||||
|
## Partition that will be formatted and mounted (optionally with FDE) for the
|
||||||
|
## rootfs, on internal storage. The installer OS must not set this, if it was
|
||||||
|
## booted from the internal storage (this is not checked in the mobile
|
||||||
|
## module!).
|
||||||
|
## If this is set, the user gets asked whether they want to install on internal
|
||||||
|
## or external storage. If the user chose internal storage,
|
||||||
|
## cmdInternalStoragePrepare (see below) runs before this partition gets
|
||||||
|
## formatted (see below). A note is displayed, that the device is powered off
|
||||||
|
## after installation and that the user should remove the external storage
|
||||||
|
## medium. So you need to adjust the installer OS to poweroff in that case, and
|
||||||
|
## not reboot. See postmarketos-ondev.git for reference.
|
||||||
|
# targetDeviceRootInternal: ""
|
||||||
|
|
||||||
|
######
|
||||||
|
### Installer Features
|
||||||
|
######
|
||||||
|
|
||||||
|
## Ask whether sshd should be enabled or not. If enabled, add a dedicated ssh
|
||||||
|
## user with proper username and password and suggest to change to key-based
|
||||||
|
## authentication after installation.
|
||||||
|
# featureSshd: true
|
||||||
|
|
||||||
|
## Ask the user, which filesystem to use.
|
||||||
|
# featureFsType: false
|
||||||
|
## Filesystems that the user can choose from.
|
||||||
|
#fsModel:
|
||||||
|
# - ext4
|
||||||
|
# - f2fs
|
||||||
|
# - btrfs
|
||||||
|
## Default filesystem to display in the dialog. If featureFsType is disabled,
|
||||||
|
## this gets used without asking the user.
|
||||||
|
# defaultFs: ext4
|
||||||
|
|
||||||
#######
|
#######
|
||||||
### Commands running in the installer OS
|
### Commands running in the installer OS
|
||||||
#######
|
#######
|
||||||
@@ -46,12 +80,25 @@
|
|||||||
|
|
||||||
## Format the rootfs with a file system
|
## Format the rootfs with a file system
|
||||||
## Arguments: <device>
|
## Arguments: <device>
|
||||||
# cmdMkfsRoot: "mkfs.ext4 -L 'unknownOS_root'"
|
## Btrfs: to allow snapshots to work on the root subvolume, it is recommended that this
|
||||||
|
## command be a script which will create a subvolume and make it default
|
||||||
|
## An example can be found at:
|
||||||
|
## https://gitlab.com/mobian1/calamares-settings-mobian/-/merge_requests/2/diffs#diff-content-dde34f5f1c89e3dea63608c553bbc452dedf428f
|
||||||
|
# cmdMkfsRootBtrfs: "mkfs.btrfs -L 'unknownOS_root'"
|
||||||
|
# cmdMkfsRootExt4: "mkfs.ext4 -L 'unknownOS_root'"
|
||||||
|
# cmdMkfsRootF2fs: "mkfs.f2fs -l 'unknownOS_root'"
|
||||||
|
|
||||||
## Mount the partition after formatting with file system
|
## Mount the partition after formatting with file system
|
||||||
## Arguments: <device> <mountpoint>
|
## Arguments: <device> <mountpoint>
|
||||||
# cmdMount: "mount"
|
# cmdMount: "mount"
|
||||||
|
|
||||||
|
## When user selects installation from external storage to internal storage
|
||||||
|
## (see targetDeviceRootInternal above), use this command to prepare the
|
||||||
|
## internal storage medium. The command must create a partition table with
|
||||||
|
## two partitions (boot, root) and fill the boot partition. See the
|
||||||
|
## ondev-internal-storage-prepare.sh in postmarketos-ondev as example.
|
||||||
|
# cmdInternalStoragePrepare: "ondev-internal-storage-prepare"
|
||||||
|
|
||||||
#######
|
#######
|
||||||
### Commands running in the target OS (chroot)
|
### Commands running in the target OS (chroot)
|
||||||
#######
|
#######
|
||||||
|
|||||||
@@ -17,14 +17,44 @@ Page
|
|||||||
property var screenPrevious: []
|
property var screenPrevious: []
|
||||||
property var titles: {
|
property var titles: {
|
||||||
"welcome": null, /* titlebar disabled */
|
"welcome": null, /* titlebar disabled */
|
||||||
|
"install_target": "Installation target",
|
||||||
|
"install_target_confirm": "Warning",
|
||||||
"default_pin": "Lockscreen PIN",
|
"default_pin": "Lockscreen PIN",
|
||||||
"ssh_confirm": "SSH server",
|
"ssh_confirm": "SSH server",
|
||||||
"ssh_credentials": "SSH credentials",
|
"ssh_credentials": "SSH credentials",
|
||||||
|
"fs_selection": "Root filesystem",
|
||||||
"fde_confirm": "Full disk encryption",
|
"fde_confirm": "Full disk encryption",
|
||||||
"fde_pass": "Full disk encryption",
|
"fde_pass": "Full disk encryption",
|
||||||
"install_confirm": "Ready to install",
|
"install_confirm": "Ready to install",
|
||||||
"wait": null
|
"wait": null
|
||||||
}
|
}
|
||||||
|
property var features: [
|
||||||
|
{"name": "welcome",
|
||||||
|
"screens": ["welcome"]},
|
||||||
|
{"name": "installTarget",
|
||||||
|
"screens": ["install_target", "install_target_confirm"]},
|
||||||
|
{"name": "userPin",
|
||||||
|
"screens": ["default_pin"]},
|
||||||
|
{"name": "sshd",
|
||||||
|
"screens": ["ssh_confirm", "ssh_credentials"]},
|
||||||
|
{"name": "fsType",
|
||||||
|
"screens": ["fs_selection"]},
|
||||||
|
{"name": "fde",
|
||||||
|
"screens": ["fde_confirm", "fde_pass"]},
|
||||||
|
{"name": "installConfirm",
|
||||||
|
"screens": ["install_confirm", "wait"]}
|
||||||
|
]
|
||||||
|
property var featureIdByScreen: (function() {
|
||||||
|
/* Put "features" above into an index of screen name -> feature id:
|
||||||
|
* featureIdByScreen = {"welcome": 0, "default_pin": 1, ...} */
|
||||||
|
var ret = {};
|
||||||
|
for (var i=0; i<features.length; i++) {
|
||||||
|
for (var j=0; j<features[i]["screens"].length; j++) {
|
||||||
|
ret[ features[i]["screens"][j] ] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}())
|
||||||
/* Only allow characters, that can be typed in with the initramfs on-screen keyboard
|
/* Only allow characters, that can be typed in with the initramfs on-screen keyboard
|
||||||
* (osk-sdl: see src/keyboard.cpp). FIXME: make configurable, but keep this as default? */
|
* (osk-sdl: see src/keyboard.cpp). FIXME: make configurable, but keep this as default? */
|
||||||
property var allowed_chars:
|
property var allowed_chars:
|
||||||
@@ -120,8 +150,13 @@ Page
|
|||||||
id: timer
|
id: timer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function skipFeatureInstallTarget() {
|
||||||
|
return config.targetDeviceRootInternal == "";
|
||||||
|
}
|
||||||
|
|
||||||
/* Navigation related */
|
/* Navigation related */
|
||||||
function navTo(name, historyPush=true) {
|
function navTo(name, historyPush=true) {
|
||||||
|
console.log("Navigating to screen: " + name);
|
||||||
if (historyPush)
|
if (historyPush)
|
||||||
screenPrevious.push(screen);
|
screenPrevious.push(screen);
|
||||||
screen = name;
|
screen = name;
|
||||||
@@ -131,15 +166,71 @@ Page
|
|||||||
Qt.inputMethod.hide();
|
Qt.inputMethod.hide();
|
||||||
}
|
}
|
||||||
function navFinish() {
|
function navFinish() {
|
||||||
/* Show a waiting screen and wait a second (so it can render), then let
|
/* Show a waiting screen and wait a second (so it can render). The big
|
||||||
* MobileQmlViewStep.cpp::onLeave() create the (encrypted) partition
|
* comment in Config.cpp::runPartitionJobThenLeave() explains why this
|
||||||
* and mount it. We can't have this as proper job due to ondev#18. */
|
* is necessary. */
|
||||||
navTo("wait");
|
navTo("wait");
|
||||||
timer.interval = 1000;
|
timer.interval = 1000;
|
||||||
timer.repeat = false;
|
timer.repeat = false;
|
||||||
timer.triggered.connect(ViewManager.next);
|
timer.triggered.connect(function() {
|
||||||
|
/* Trigger Config.cpp::runPartitionJobThenLeave(). (We could expose
|
||||||
|
* the function directly with qmlRegisterSingletonType somehow, but
|
||||||
|
* I haven't seen existing Calamares code do that with the Config
|
||||||
|
* object, so just use the side effect of setting the variable, as
|
||||||
|
* done in existing code of Calamares modules.) */
|
||||||
|
config.runPartitionJobThenLeave = 1
|
||||||
|
});
|
||||||
timer.start();
|
timer.start();
|
||||||
}
|
}
|
||||||
|
function navNextFeature() {
|
||||||
|
var id = featureIdByScreen[screen] + 1;
|
||||||
|
|
||||||
|
/* Skip disabled features */
|
||||||
|
do {
|
||||||
|
/* First letter uppercase */
|
||||||
|
var name = features[id]["name"];
|
||||||
|
var nameUp = name.charAt(0).toUpperCase() + name.slice(1);
|
||||||
|
|
||||||
|
/* Check config.Feature<Name> */
|
||||||
|
var configOption = "feature" + nameUp;
|
||||||
|
if (config[configOption] === false) {
|
||||||
|
console.log("Skipping feature (disabled in config): " + name);
|
||||||
|
id += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check skipFeature<Name>() */
|
||||||
|
var funcName = "skipFeature" + nameUp;
|
||||||
|
if (eval("typeof " + funcName) === "function"
|
||||||
|
&& eval(funcName + "()")) {
|
||||||
|
console.log("Skipping feature (skip function): " + name);
|
||||||
|
id += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
console.log("Navigating to feature: " + features[id]["name"]);
|
||||||
|
return navTo(features[id]["screens"][0]);
|
||||||
|
}
|
||||||
|
function navNext() {
|
||||||
|
var featureId = featureIdByScreen[screen];
|
||||||
|
var featureScreens = features[featureId]["screens"];
|
||||||
|
for (var i = 0; i<featureScreens.length; i++) {
|
||||||
|
/* Seek ahead until i is current screen */
|
||||||
|
if (featureScreens[i] != screen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Navigate to next screen in same feature */
|
||||||
|
if (i + 1 < featureScreens.length) {
|
||||||
|
var screenNext = featureScreens[i + 1];
|
||||||
|
return navTo(screenNext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Screen is last in feature */
|
||||||
|
return navNextFeature();
|
||||||
|
}
|
||||||
|
console.log("ERROR: navNext() failed for screen: " + screen);
|
||||||
|
}
|
||||||
function navBack() {
|
function navBack() {
|
||||||
if (screenPrevious.length)
|
if (screenPrevious.length)
|
||||||
return navTo(screenPrevious.pop(), false);
|
return navTo(screenPrevious.pop(), false);
|
||||||
@@ -183,7 +274,7 @@ Page
|
|||||||
if (repeat != pin)
|
if (repeat != pin)
|
||||||
return validationFailure(errorText,
|
return validationFailure(errorText,
|
||||||
"The PINs don't match.");
|
"The PINs don't match.");
|
||||||
|
|
||||||
return validationFailureClear(errorText);
|
return validationFailureClear(errorText);
|
||||||
}
|
}
|
||||||
function validateSshdUsername(username, errorText) {
|
function validateSshdUsername(username, errorText) {
|
||||||
|
|||||||
@@ -4,9 +4,13 @@
|
|||||||
|
|
||||||
<file>welcome.qml</file>
|
<file>welcome.qml</file>
|
||||||
|
|
||||||
|
<file>install_target.qml</file> <!-- install from external to internal? -->
|
||||||
|
<file>install_target_confirm.qml</file> <!-- overwrite internal storage? -->
|
||||||
|
|
||||||
<file>default_pin.qml</file> <!-- default user: pin -->
|
<file>default_pin.qml</file> <!-- default user: pin -->
|
||||||
<file>ssh_confirm.qml</file> <!-- sshd: enable or not? -->
|
<file>ssh_confirm.qml</file> <!-- sshd: enable or not? -->
|
||||||
<file>ssh_credentials.qml</file> <!-- sshd user: username, password -->
|
<file>ssh_credentials.qml</file> <!-- sshd user: username, password -->
|
||||||
|
<file>fs_selection.qml</file> <!-- filesystem selection -->
|
||||||
|
|
||||||
<file>fde_confirm.qml</file> <!-- enable FDE or not? -->
|
<file>fde_confirm.qml</file> <!-- enable FDE or not? -->
|
||||||
<file>fde_pass.qml</file> <!-- FDE password (optional) -->
|
<file>fde_pass.qml</file> <!-- FDE password (optional) -->
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Item {
|
|||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: welcomeText
|
id: mainText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 30
|
anchors.topMargin: 30
|
||||||
@@ -40,29 +40,29 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: enableButton
|
id: firstButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: welcomeText.bottom
|
anchors.top: mainText.bottom
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 40
|
||||||
width: 500
|
width: 500
|
||||||
|
|
||||||
text: qsTr("Enable")
|
text: qsTr("Enable")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
config.isSshEnabled = true;
|
config.isSshEnabled = true;
|
||||||
navTo("ssh_credentials");
|
navNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: enableButton.bottom
|
anchors.top: firstButton.bottom
|
||||||
anchors.topMargin: 40
|
anchors.topMargin: 40
|
||||||
width: 500
|
width: 500
|
||||||
|
|
||||||
text: qsTr("Disable")
|
text: qsTr("Disable")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
config.isSshEnabled = false;
|
config.isSshEnabled = false;
|
||||||
navTo("fde_confirm");
|
navNextFeature();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ Item {
|
|||||||
config.sshdUsername = username.text;
|
config.sshdUsername = username.text;
|
||||||
config.sshdPassword = password.text;
|
config.sshdPassword = password.text;
|
||||||
|
|
||||||
navTo("fde_confirm");
|
navNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Page
|
|||||||
anchors.topMargin: 150
|
anchors.topMargin: 150
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
text: "Formatting and mounting target partition. This may" +
|
text: "Formatting and mounting target partition. This may" +
|
||||||
" take up to 20 seconds, please be patient."
|
" take up to two minutes, please be patient."
|
||||||
width: 500
|
width: 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ Page
|
|||||||
source: "file:///usr/share/calamares/branding/default-mobile/logo.png"
|
source: "file:///usr/share/calamares/branding/default-mobile/logo.png"
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
id: welcomeText
|
id: mainText
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: logo.bottom
|
anchors.top: logo.bottom
|
||||||
anchors.topMargin: 50
|
anchors.topMargin: 50
|
||||||
@@ -53,12 +53,12 @@ Page
|
|||||||
|
|
||||||
Button {
|
Button {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: welcomeText.bottom
|
anchors.top: mainText.bottom
|
||||||
anchors.topMargin: 50
|
anchors.topMargin: 50
|
||||||
width: 500
|
width: 500
|
||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
onClicked: navTo("default_pin")
|
onClicked: navNext()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user