Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff3391f67b | ||
|
|
b60b21b680 | ||
|
|
8a533d22be | ||
|
|
6f32c18ef9 | ||
|
|
f36f21c55c | ||
|
|
bcacab531f | ||
|
|
85586293c8 | ||
|
|
e71eb01feb | ||
|
|
3eb3e9c98d | ||
|
|
2bf5706f73 | ||
|
|
76885c7fe1 | ||
|
|
fad0575e4d | ||
|
|
550f7d40ef | ||
|
|
6c07d39374 | ||
|
|
4285ccebd7 | ||
|
|
320d67a5ba | ||
|
|
6a80ce6dab | ||
|
|
33678a6a16 | ||
|
|
2c91dc4664 | ||
|
|
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 }}"
|
||||
54
CHANGES
Normal file
54
CHANGES
Normal file
@@ -0,0 +1,54 @@
|
||||
<!-- 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.2 (2021-05-14)
|
||||
|
||||
This release contains contributions from (alphabetically by first name):
|
||||
- Oliver Smith
|
||||
|
||||
Changes and new modules in this release:
|
||||
- New *os-* modules are intended for OS-specific work. They don't
|
||||
do anything concrete yet, though.
|
||||
- The *mobile* module has new features thanks to Oliver, with
|
||||
keyboard selection (numeric / alpha) for PIN / password entry among them.
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
@@ -24,15 +24,54 @@
|
||||
# distro can use an unmodified (upstream) Calamares package and a local
|
||||
# customisation package in tandem.
|
||||
#
|
||||
# Besides being an example repository, it is also a collection of modules
|
||||
# and branding that is usable in its own right.
|
||||
#
|
||||
### CONFIGURING
|
||||
#
|
||||
# By default, all the branding examples and all the modules are built.
|
||||
# This can be influenced through:
|
||||
# SKIP_MODULES : a space or semicolon-separated list of directory names
|
||||
# under src/modules that should not be built.
|
||||
# USE_* : fills in SKIP_MODULES for modules called *-<something>
|
||||
# In this repository, there is just one "group" to which USE_* applies:
|
||||
# USE_os : operating-system-specific modules.
|
||||
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
||||
project(calamares-extensions
|
||||
VERSION 1.0.0
|
||||
VERSION 1.1.2
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
find_package(Calamares 3.2.26 REQUIRED)
|
||||
# On developer's machine, the user package registry breaks
|
||||
# consumers by loading the developer's config from a build
|
||||
# directory (which doesn't have the rest of the config
|
||||
# installed inside it).
|
||||
find_package(Calamares 3.2.26 REQUIRED NO_CMAKE_PACKAGE_REGISTRY)
|
||||
if (NOT TARGET Calamares::calamares OR NOT TARGET Calamares::calamaresui)
|
||||
message(FATAL_ERROR "Calamares found with missing CMake targets")
|
||||
endif()
|
||||
|
||||
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()
|
||||
|
||||
find_package(YAMLCPP REQUIRED)
|
||||
|
||||
### BRANDING
|
||||
#
|
||||
@@ -56,17 +95,22 @@ calamares_add_branding_subdirectory( branding/kaos_branding NAME kaos )
|
||||
#
|
||||
# Add one of more modules, either C++ or Python.
|
||||
#
|
||||
set(SKIPPED_MODULES "")
|
||||
set(LIST_SKIPPED_MODULES "")
|
||||
|
||||
calamares_add_module_subdirectory( modules/filekeeper ) # C++ job
|
||||
calamares_add_module_subdirectory( modules/freebsddisk ) # C++ viewmodule
|
||||
calamares_add_module_subdirectory( modules/mobile )
|
||||
calamares_add_module_subdirectory( modules/slowpython ) # Python job
|
||||
calamares_add_module_subdirectory( modules/filekeeper LIST_SKIPPED_MODULES ) # C++ job
|
||||
calamares_add_module_subdirectory( modules/freebsddisk LIST_SKIPPED_MODULES ) # C++ viewmodule
|
||||
calamares_add_module_subdirectory( modules/mobile LIST_SKIPPED_MODULES )
|
||||
calamares_add_module_subdirectory( modules/os-freebsd LIST_SKIPPED_MODULES )
|
||||
calamares_add_module_subdirectory( modules/os-nixos LIST_SKIPPED_MODULES )
|
||||
calamares_add_module_subdirectory( modules/slowpython LIST_SKIPPED_MODULES ) # Python job
|
||||
|
||||
# If modules cannot be built, they usually call a macro
|
||||
# which builds a list of explanations; show that list.
|
||||
calamares_explain_skipped_modules( ${SKIPPED_MODULES} )
|
||||
calamares_explain_skipped_modules( ${LIST_SKIPPED_MODULES} )
|
||||
|
||||
### RELEASE SUPPORT
|
||||
#
|
||||
#
|
||||
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
|
||||
if( calamares-extensions_VERSION_TWEAK )
|
||||
|
||||
76
README.md
76
README.md
@@ -1,10 +1,11 @@
|
||||
# Calamares Branding and Module Examples
|
||||
|
||||
> 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.
|
||||
> 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++)
|
||||
> if there is one. Both C++ and Python allow a full control over the
|
||||
> target system during the installation.
|
||||
@@ -13,13 +14,9 @@ This repository contains complete examples of branding and some
|
||||
modules for Calamares.
|
||||
|
||||
- [Branding](#branding) documentation
|
||||
- [default](branding/default/branding.desc) branding example
|
||||
- [fancy](branding/fancy/branding.desc) branding example
|
||||
- [KaOS](branding/kaos_branding/branding.desc) branding example
|
||||
- [SameGame](branding/samegame/branding.desc) branding example
|
||||
- [Module](#module) documentation
|
||||
|
||||
## Branding
|
||||
- [Module](#modules) documentation
|
||||
|
||||
## Branding
|
||||
|
||||
> 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
|
||||
and documentation for the framework that Calamares ships with.
|
||||
|
||||
- `default/` is a copy of the default branding included with Calamares.
|
||||
- `fancy/` has navigation buttons and a slide counter.
|
||||
- `kaos_branding/` is a copy of the KaOS branding component, which
|
||||
- [`default/`](branding/default/branding.desc)
|
||||
is a copy of the default branding included with Calamares.
|
||||
- [`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.
|
||||
- `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.
|
||||
|
||||
### Writing your own Branding
|
||||
@@ -62,7 +68,7 @@ and documentation for the framework that Calamares ships with.
|
||||
parts of Calamares.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
build the translations first (using Qt Linguist `lrelease`, or by
|
||||
using the normal build system for branding components).
|
||||
@@ -87,7 +93,7 @@ qmlscene \
|
||||
-translation build/calamares-fancy_nl.qm \
|
||||
-I /usr/local/share/calamares/qml \
|
||||
-geometry 600x400 \
|
||||
fancy/show.qml
|
||||
fancy/show.qml
|
||||
```
|
||||
|
||||
This starts the viewer with the Dutch (nl) translation, using the
|
||||
@@ -104,25 +110,39 @@ every time.
|
||||
### Calamares Branding API
|
||||
|
||||
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
|
||||
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
|
||||
started. This may delay startup a little, but may appear more
|
||||
started. This may delay startup a little, but appears more
|
||||
responsive overall.
|
||||
|
||||
If the slideshow QML defines functions
|
||||
`onActivate()` and `onLeave()` then those functions
|
||||
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
|
||||
whatever.
|
||||
whatever.
|
||||
|
||||
In addition, if the slideshow QML defines a property
|
||||
`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
|
||||
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
|
||||
@@ -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*
|
||||
phase).
|
||||
|
||||
### Example Modules
|
||||
|
||||
- [filekeeper](modules/filekeeper/CMakeLists.txt) is a C++ **job** module
|
||||
to copy files from the host (live) system to the target system at
|
||||
the end of installation, like logfiles. (This module is made obsolete
|
||||
@@ -146,6 +168,18 @@ phase).
|
||||
module that just serves to slow down an installation by delaying
|
||||
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, and as of writing used by
|
||||
[postmarketOS](https://postmarketos.org) and
|
||||
[Mobian](https://mobian-project.org/). Among other things, it
|
||||
allows to set up full disk encryption and to configure the
|
||||
default user's password. Read the
|
||||
[on-device installer](https://wiki.postmarketos.org/wiki/On-device_installer)
|
||||
article for more information.
|
||||
|
||||
### CMake Preparation
|
||||
|
||||
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,
|
||||
# with not-applicable parts (such as translation-freeze) either
|
||||
# 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
|
||||
# document automatically. It's not tested on other machines or
|
||||
@@ -31,6 +32,7 @@
|
||||
# * `-B` do not build (before tagging)
|
||||
# * `-P` do not package (tag, sign, tarball)
|
||||
# * `-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:
|
||||
# * 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
|
||||
@@ -6,13 +6,9 @@ calamares_add_plugin( mobile
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
Config.cpp
|
||||
Config.h
|
||||
MobileQmlViewStep.cpp
|
||||
MobileQmlViewStep.h
|
||||
PartitionJob.cpp
|
||||
PartitionJob.h
|
||||
UsersJob.cpp
|
||||
UsersJob.h
|
||||
RESOURCES
|
||||
mobile.qrc
|
||||
SHARED_LIB
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
#include "Config.h"
|
||||
#include "PartitionJob.h"
|
||||
#include "UsersJob.h"
|
||||
|
||||
#include "ViewManager.h"
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
Config::Config( QObject* parent )
|
||||
@@ -8,37 +14,116 @@ 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
|
||||
Config::setConfigurationMap( const QVariantMap& cfgMap )
|
||||
{
|
||||
m_osName = cfgStr( cfgMap, "osName", "(unknown)" );
|
||||
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" );
|
||||
using namespace CalamaresUtils;
|
||||
|
||||
m_cmdLuksFormat = cfgStr( cfgMap, "cmdLuksFormat", "cryptsetup luksFormat --use-random" );
|
||||
m_cmdLuksOpen = cfgStr( cfgMap, "cmdLuksOpen", "cryptsetup luksOpen" );
|
||||
m_cmdMkfsRoot = cfgStr( cfgMap, "cmdMkfsRoot", "mkfs.ext4 -L 'unknownOS_root'" );
|
||||
m_cmdMount = cfgStr( cfgMap, "cmdMount", "mount" );
|
||||
m_targetDeviceRoot = cfgStr( cfgMap, "targetDeviceRoot", "/dev/unknown" );
|
||||
m_osName = getString( cfgMap, "osName", "(unknown)" );
|
||||
m_arch = getString( cfgMap, "arch", "(unknown)" );
|
||||
m_device = getString( cfgMap, "device", "(unknown)" );
|
||||
m_userInterface = getString( cfgMap, "userInterface", "(unknown)" );
|
||||
m_version = getString( cfgMap, "version", "(unknown)" );
|
||||
m_username = getString( cfgMap, "username", "user" );
|
||||
m_userPasswordNumeric = getBool( cfgMap, "userPasswordNumeric", true );
|
||||
|
||||
m_cmdPasswd = cfgStr( cfgMap, "cmdPasswd", "passwd" );
|
||||
m_cmdSshdEnable = cfgStr( cfgMap, "cmdSshdEnable", "systemctl enable sshd.service" );
|
||||
m_cmdSshdDisable = cfgStr( cfgMap, "cmdSshdDisable", "systemctl disable sshd.service" );
|
||||
m_cmdSshdUseradd = cfgStr( cfgMap, "cmdSshdUseradd", "useradd -G wheel -m" );
|
||||
m_builtinVirtualKeyboard = getBool( cfgMap, "builtinVirtualKeyboard", true );
|
||||
|
||||
m_featureSshd = getBool( cfgMap, "featureSshd", true );
|
||||
m_featureFsType = getBool( cfgMap, "featureFsType", false );
|
||||
|
||||
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
|
||||
@@ -80,3 +165,34 @@ Config::setIsFdeEnabled( const bool 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,12 +1,18 @@
|
||||
/* SPDX-FileCopyrightText: 2020 Oliver Smith <ollieparanoid@postmarketos.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "Job.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
|
||||
class Config : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
/* installer UI */
|
||||
Q_PROPERTY( bool builtinVirtualKeyboard READ builtinVirtualKeyboard CONSTANT FINAL )
|
||||
|
||||
/* welcome */
|
||||
Q_PROPERTY( QString osName READ osName CONSTANT FINAL )
|
||||
Q_PROPERTY( QString arch READ arch CONSTANT FINAL )
|
||||
@@ -17,8 +23,10 @@ class Config : public QObject
|
||||
/* default user */
|
||||
Q_PROPERTY( QString username READ username CONSTANT FINAL )
|
||||
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
|
||||
Q_PROPERTY( bool userPasswordNumeric READ userPasswordNumeric CONSTANT FINAL )
|
||||
|
||||
/* ssh server + credentials */
|
||||
Q_PROPERTY( bool featureSshd READ featureSshd CONSTANT FINAL )
|
||||
Q_PROPERTY( QString sshdUsername READ sshdUsername WRITE setSshdUsername NOTIFY sshdUsernameChanged )
|
||||
Q_PROPERTY( QString sshdPassword READ sshdPassword WRITE setSshdPassword NOTIFY sshdPasswordChanged )
|
||||
Q_PROPERTY( bool isSshEnabled READ isSshEnabled WRITE setIsSshEnabled )
|
||||
@@ -27,12 +35,23 @@ class Config : public QObject
|
||||
Q_PROPERTY( QString fdePassword READ fdePassword WRITE setFdePassword NOTIFY fdePasswordChanged )
|
||||
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 */
|
||||
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 cmdLuksOpen READ cmdLuksOpen CONSTANT FINAL )
|
||||
Q_PROPERTY( QString cmdMkfsRoot READ cmdMkfsRoot CONSTANT FINAL )
|
||||
Q_PROPERTY( QString cmdMount READ cmdMount 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 */
|
||||
Q_PROPERTY( QString cmdSshdEnable READ cmdSshdEnable CONSTANT FINAL )
|
||||
@@ -41,6 +60,10 @@ class Config : public QObject
|
||||
public:
|
||||
Config( QObject* parent = nullptr );
|
||||
void setConfigurationMap( const QVariantMap& );
|
||||
Calamares::JobList createJobs();
|
||||
|
||||
/* installer UI */
|
||||
bool builtinVirtualKeyboard() { return m_builtinVirtualKeyboard; }
|
||||
|
||||
/* welcome */
|
||||
QString osName() const { return m_osName; }
|
||||
@@ -53,8 +76,10 @@ public:
|
||||
QString username() const { return m_username; }
|
||||
QString userPassword() const { return m_userPassword; }
|
||||
void setUserPassword( const QString& userPassword );
|
||||
bool userPasswordNumeric() const { return m_userPasswordNumeric; }
|
||||
|
||||
/* ssh server + credetials */
|
||||
bool featureSshd() { return m_featureSshd; }
|
||||
QString sshdUsername() const { return m_sshdUsername; }
|
||||
QString sshdPassword() const { return m_sshdPassword; }
|
||||
bool isSshEnabled() { return m_isSshEnabled; }
|
||||
@@ -68,12 +93,30 @@ public:
|
||||
void setFdePassword( const QString& fdePassword );
|
||||
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 */
|
||||
bool runPartitionJobThenLeaveDummy() { return 0; }
|
||||
void runPartitionJobThenLeave( bool b );
|
||||
QString cmdInternalStoragePrepare() const { return m_cmdInternalStoragePrepare; }
|
||||
QString cmdLuksFormat() const { return m_cmdLuksFormat; }
|
||||
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 targetDeviceRoot() const { return m_targetDeviceRoot; }
|
||||
QString targetDeviceRootInternal() const { return m_targetDeviceRootInternal; }
|
||||
bool installFromExternalToInternal() { return m_installFromExternalToInternal; }
|
||||
void setInstallFromExternalToInternal( const bool val );
|
||||
|
||||
/* users job */
|
||||
QString cmdPasswd() const { return m_cmdPasswd; }
|
||||
@@ -82,6 +125,9 @@ public:
|
||||
QString cmdSshdUseradd() const { return m_cmdSshdUseradd; }
|
||||
|
||||
private:
|
||||
/* installer UI */
|
||||
bool m_builtinVirtualKeyboard;
|
||||
|
||||
/* welcome */
|
||||
QString m_osName;
|
||||
QString m_arch;
|
||||
@@ -92,22 +138,37 @@ private:
|
||||
/* default user */
|
||||
QString m_username;
|
||||
QString m_userPassword;
|
||||
bool m_userPasswordNumeric;
|
||||
|
||||
/* ssh server + credetials */
|
||||
/* ssh server + credentials */
|
||||
bool m_featureSshd = false;
|
||||
QString m_sshdUsername;
|
||||
QString m_sshdPassword;
|
||||
bool m_isSshEnabled;
|
||||
bool m_isSshEnabled = false;
|
||||
|
||||
/* full disk encryption */
|
||||
QString m_fdePassword = "";
|
||||
QString m_fdePassword;
|
||||
bool m_isFdeEnabled = false;
|
||||
|
||||
/* filesystem selection */
|
||||
bool m_featureFsType = false;
|
||||
QString m_defaultFs;
|
||||
QString m_fsType;
|
||||
// Index of the currently selected filesystem in UI.
|
||||
int m_fsIndex = -1;
|
||||
QStringList m_fsList;
|
||||
|
||||
/* partition job */
|
||||
QString m_cmdInternalStoragePrepare;
|
||||
QString m_cmdLuksFormat;
|
||||
QString m_cmdLuksOpen;
|
||||
QString m_cmdMkfsRoot;
|
||||
QString m_cmdMkfsRootBtrfs;
|
||||
QString m_cmdMkfsRootExt4;
|
||||
QString m_cmdMkfsRootF2fs;
|
||||
QString m_cmdMount;
|
||||
QString m_targetDeviceRoot;
|
||||
QString m_targetDeviceRootInternal;
|
||||
bool m_installFromExternalToInternal = false;
|
||||
|
||||
/* users job */
|
||||
QString m_cmdPasswd;
|
||||
@@ -116,14 +177,18 @@ private:
|
||||
QString m_cmdSshdUseradd;
|
||||
|
||||
signals:
|
||||
/* booleans we don't read from QML (like isSshEnabled) don't need a signal */
|
||||
|
||||
/* default user */
|
||||
void userPasswordChanged( QString userPassword );
|
||||
|
||||
/* ssh server + credetials */
|
||||
/* ssh server + credentials */
|
||||
void sshdUsernameChanged( QString sshdUsername );
|
||||
void sshdPasswordChanged( QString sshdPassword );
|
||||
/* isSshEnabled doesn't need a signal, we don't read it from QML */
|
||||
|
||||
/* full disk encryption */
|
||||
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-License-Identifier: GPL-3.0-or-later */
|
||||
#include "MobileQmlViewStep.h"
|
||||
#include "PartitionJob.h"
|
||||
#include "UsersJob.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
#include "locale/LabelModel.h"
|
||||
#include "utils/Dirs.h"
|
||||
@@ -35,34 +32,7 @@ MobileQmlViewStep::MobileQmlViewStep( QObject* parent )
|
||||
void
|
||||
MobileQmlViewStep::onLeave()
|
||||
{
|
||||
Calamares::Job *partition, *users;
|
||||
|
||||
/* 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 ) );
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -95,7 +65,7 @@ MobileQmlViewStep::isAtEnd() const
|
||||
Calamares::JobList
|
||||
MobileQmlViewStep::jobs() const
|
||||
{
|
||||
return m_jobs;
|
||||
return m_config->createJobs();
|
||||
}
|
||||
|
||||
QObject*
|
||||
|
||||
@@ -32,7 +32,6 @@ public:
|
||||
|
||||
private:
|
||||
Config* m_config;
|
||||
QList< Calamares::job_ptr > m_jobs;
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( MobileQmlViewStepFactory )
|
||||
|
||||
@@ -12,19 +12,25 @@
|
||||
#include <QFileInfo>
|
||||
|
||||
|
||||
PartitionJob::PartitionJob( QString cmdLuksFormat,
|
||||
QString cmdLuksOpen,
|
||||
QString cmdMkfsRoot,
|
||||
QString cmdMount,
|
||||
QString targetDeviceRoot,
|
||||
PartitionJob::PartitionJob( const QString& cmdInternalStoragePrepare,
|
||||
const QString& cmdLuksFormat,
|
||||
const QString& cmdLuksOpen,
|
||||
const QString& cmdMkfsRoot,
|
||||
const QString& cmdMount,
|
||||
const QString& targetDeviceRoot,
|
||||
const QString& targetDeviceRootInternal,
|
||||
bool installFromExternalToInternal,
|
||||
bool isFdeEnabled,
|
||||
const QString& password )
|
||||
: Calamares::Job()
|
||||
, m_cmdInternalStoragePrepare( cmdInternalStoragePrepare )
|
||||
, m_cmdLuksFormat( cmdLuksFormat )
|
||||
, m_cmdLuksOpen( cmdLuksOpen )
|
||||
, m_cmdMkfsRoot( cmdMkfsRoot )
|
||||
, m_cmdMount( cmdMount )
|
||||
, m_targetDeviceRoot( targetDeviceRoot )
|
||||
, m_targetDeviceRootInternal( targetDeviceRootInternal )
|
||||
, m_installFromExternalToInternal( installFromExternalToInternal )
|
||||
, m_isFdeEnabled( isFdeEnabled )
|
||||
, m_password( password )
|
||||
{
|
||||
@@ -77,10 +83,18 @@ PartitionJob::exec()
|
||||
QString cryptDev = "/dev/mapper/" + cryptName;
|
||||
QString passwordStdin = m_password + "\n";
|
||||
QString dev = m_targetDeviceRoot;
|
||||
QList< QPair< QStringList, QString > > commands = {};
|
||||
|
||||
QList< QPair< QStringList, QString > > commands = {
|
||||
{ { "mkdir", "-p", pathMount }, QString() },
|
||||
};
|
||||
if ( m_installFromExternalToInternal )
|
||||
{
|
||||
dev = m_targetDeviceRootInternal;
|
||||
|
||||
commands.append( {
|
||||
{ { "sh", "-c", m_cmdInternalStoragePrepare }, QString() },
|
||||
} );
|
||||
}
|
||||
|
||||
commands.append( { { { "mkdir", "-p", pathMount }, QString() } } );
|
||||
|
||||
if ( m_isFdeEnabled )
|
||||
{
|
||||
|
||||
@@ -8,11 +8,14 @@ class PartitionJob : public Calamares::Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PartitionJob( QString cmdLuksFormat,
|
||||
QString cmdLuksOpen,
|
||||
QString cmdMkfsRoot,
|
||||
QString cmdMount,
|
||||
QString targetDeviceRoot,
|
||||
PartitionJob( const QString& cmdInternalStoragePrepare,
|
||||
const QString& cmdLuksFormat,
|
||||
const QString& cmdLuksOpen,
|
||||
const QString& cmdMkfsRoot,
|
||||
const QString& cmdMount,
|
||||
const QString& targetDeviceRoot,
|
||||
const QString& targetDeviceRootInternal,
|
||||
bool installFromExternalToInternal,
|
||||
bool isFdeEnabled,
|
||||
const QString& password );
|
||||
|
||||
@@ -22,11 +25,14 @@ public:
|
||||
Calamares::JobList createJobs();
|
||||
|
||||
private:
|
||||
QString m_cmdInternalStoragePrepare;
|
||||
QString m_cmdLuksFormat;
|
||||
QString m_cmdLuksOpen;
|
||||
QString m_cmdMkfsRoot;
|
||||
QString m_cmdMount;
|
||||
QString m_targetDeviceRoot;
|
||||
QString m_targetDeviceRootInternal;
|
||||
bool m_installFromExternalToInternal;
|
||||
bool m_isFdeEnabled;
|
||||
QString m_password;
|
||||
};
|
||||
|
||||
@@ -12,15 +12,17 @@
|
||||
#include <QFileInfo>
|
||||
|
||||
|
||||
UsersJob::UsersJob( QString cmdPasswd,
|
||||
QString cmdSshd,
|
||||
QString cmdSshdUseradd,
|
||||
UsersJob::UsersJob( bool featureSshd,
|
||||
const QString& cmdPasswd,
|
||||
const QString& cmdSshd,
|
||||
const QString& cmdSshdUseradd,
|
||||
bool isSshEnabled,
|
||||
QString username,
|
||||
QString password,
|
||||
QString sshdUsername,
|
||||
QString sshdPassword )
|
||||
const QString& username,
|
||||
const QString& password,
|
||||
const QString& sshdUsername,
|
||||
const QString& sshdPassword )
|
||||
: Calamares::Job()
|
||||
, m_featureSshd( featureSshd )
|
||||
, m_cmdPasswd( cmdPasswd )
|
||||
, m_cmdSshd( cmdSshd )
|
||||
, m_cmdSshdUseradd( cmdSshdUseradd )
|
||||
@@ -48,14 +50,18 @@ UsersJob::exec()
|
||||
|
||||
QList< QPair< QStringList, QString > > commands = {
|
||||
{ { "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_cmdPasswd + " " + m_sshdUsername }, m_sshdPassword + "\n" + m_sshdPassword + "\n" } );
|
||||
commands.append( { { "sh", "-c", m_cmdSshd }, QString() } );
|
||||
|
||||
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 )
|
||||
|
||||
@@ -8,14 +8,15 @@ class UsersJob : public Calamares::Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
UsersJob( QString cmdPasswd,
|
||||
QString cmdSshd,
|
||||
QString cmdSshdUseradd,
|
||||
UsersJob( bool featureSshd,
|
||||
const QString& cmdPasswd,
|
||||
const QString& cmdSshd,
|
||||
const QString& cmdSshdUseradd,
|
||||
bool isSshEnabled,
|
||||
QString username,
|
||||
QString password,
|
||||
QString sshdUsername,
|
||||
QString sshdPassword );
|
||||
const QString& username,
|
||||
const QString& password,
|
||||
const QString& sshdUsername,
|
||||
const QString& sshdPassword );
|
||||
|
||||
QString prettyName() const override;
|
||||
Calamares::JobResult exec() override;
|
||||
@@ -23,6 +24,7 @@ public:
|
||||
Calamares::JobList createJobs();
|
||||
|
||||
private:
|
||||
bool m_featureSshd;
|
||||
QString m_cmdPasswd;
|
||||
QString m_cmdSshd;
|
||||
QString m_cmdSshdUseradd;
|
||||
|
||||
@@ -19,7 +19,7 @@ Item {
|
||||
height: parent.height
|
||||
|
||||
Text {
|
||||
id: welcomeText
|
||||
id: mainText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 30
|
||||
@@ -37,29 +37,29 @@ Item {
|
||||
}
|
||||
|
||||
Button {
|
||||
id: enableButton
|
||||
id: firstButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: welcomeText.bottom
|
||||
anchors.top: mainText.bottom
|
||||
anchors.topMargin: 40
|
||||
width: 500
|
||||
|
||||
text: qsTr("Enable")
|
||||
onClicked: {
|
||||
config.isFdeEnabled = true;
|
||||
navTo("fde_pass");
|
||||
navNext();
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: enableButton.bottom
|
||||
anchors.top: firstButton.bottom
|
||||
anchors.topMargin: 40
|
||||
width: 500
|
||||
|
||||
text: qsTr("Disable")
|
||||
onClicked: {
|
||||
config.isFdeEnabled = false;
|
||||
navTo("install_confirm");
|
||||
navNextFeature();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ Item {
|
||||
onClicked: {
|
||||
if (validatePassword(password, passwordRepeat, errorText)) {
|
||||
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
|
||||
|
||||
Text {
|
||||
id: welcomeText
|
||||
id: mainText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 30
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: "Once you hit 'install', the installation will begin. It will" +
|
||||
" typically take a few minutes. Do not power off the device" +
|
||||
" until it is done. Afterwards, it will reboot into the" +
|
||||
" installed system."
|
||||
text: (function() {
|
||||
var ret = "Once you hit 'install', the installation will begin." +
|
||||
" It will typically take a few minutes. Do not power off the" +
|
||||
" 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
|
||||
}
|
||||
|
||||
Button {
|
||||
id: enableButton
|
||||
id: firstButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: welcomeText.bottom
|
||||
anchors.top: mainText.bottom
|
||||
anchors.topMargin: 40
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,10 @@
|
||||
## User Interface name (e.g. Plasma Mobile)
|
||||
# userInterface: "(unknown)"
|
||||
|
||||
## User Interface assumes that the password is numeric (as of writing, this is
|
||||
## the case with Plasma Mobile and Phosh)
|
||||
# userPasswordNumeric: true
|
||||
|
||||
## OS version
|
||||
# version: "(unknown)"
|
||||
|
||||
@@ -27,9 +31,47 @@
|
||||
## Name of the device (e.g. PinePhone)
|
||||
# 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"
|
||||
|
||||
## 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
|
||||
|
||||
## Start Qt's virtual keyboard within the mobile module. Disable if you bring
|
||||
## your own virtual keyboard (e.g. svkbd).
|
||||
# builtinVirtualKeyboard: true
|
||||
|
||||
#######
|
||||
### Commands running in the installer OS
|
||||
#######
|
||||
@@ -46,12 +88,25 @@
|
||||
|
||||
## Format the rootfs with a file system
|
||||
## 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
|
||||
## Arguments: <device> <mountpoint>
|
||||
# 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)
|
||||
#######
|
||||
|
||||
@@ -17,16 +17,46 @@ Page
|
||||
property var screenPrevious: []
|
||||
property var titles: {
|
||||
"welcome": null, /* titlebar disabled */
|
||||
"default_pin": "Lockscreen PIN",
|
||||
"install_target": "Installation target",
|
||||
"install_target_confirm": "Warning",
|
||||
"user_pass": "User password",
|
||||
"ssh_confirm": "SSH server",
|
||||
"ssh_credentials": "SSH credentials",
|
||||
"fs_selection": "Root filesystem",
|
||||
"fde_confirm": "Full disk encryption",
|
||||
"fde_pass": "Full disk encryption",
|
||||
"install_confirm": "Ready to install",
|
||||
"wait": null
|
||||
}
|
||||
/* 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? */
|
||||
property var features: [
|
||||
{"name": "welcome",
|
||||
"screens": ["welcome"]},
|
||||
{"name": "installTarget",
|
||||
"screens": ["install_target", "install_target_confirm"]},
|
||||
{"name": "userPassword",
|
||||
"screens": ["user_pass"]},
|
||||
{"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, "user_pass": 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 osk-sdl
|
||||
* (src/keyboard.cpp). Details in big comment in validatePassword(). */
|
||||
property var allowed_chars:
|
||||
/* layer 0 */ "abcdefghijklmnopqrstuvwxyz" +
|
||||
/* layer 1 */ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||||
@@ -112,6 +142,7 @@ Page
|
||||
InputPanel {
|
||||
id: inputPanel
|
||||
y: Qt.inputMethod.visible ? parent.height - inputPanel.height : parent.height
|
||||
visible: config.builtinVirtualKeyboard
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
}
|
||||
@@ -120,8 +151,13 @@ Page
|
||||
id: timer
|
||||
}
|
||||
|
||||
function skipFeatureInstallTarget() {
|
||||
return config.targetDeviceRootInternal == "";
|
||||
}
|
||||
|
||||
/* Navigation related */
|
||||
function navTo(name, historyPush=true) {
|
||||
console.log("Navigating to screen: " + name);
|
||||
if (historyPush)
|
||||
screenPrevious.push(screen);
|
||||
screen = name;
|
||||
@@ -131,15 +167,71 @@ Page
|
||||
Qt.inputMethod.hide();
|
||||
}
|
||||
function navFinish() {
|
||||
/* Show a waiting screen and wait a second (so it can render), then let
|
||||
* MobileQmlViewStep.cpp::onLeave() create the (encrypted) partition
|
||||
* and mount it. We can't have this as proper job due to ondev#18. */
|
||||
/* Show a waiting screen and wait a second (so it can render). The big
|
||||
* comment in Config.cpp::runPartitionJobThenLeave() explains why this
|
||||
* is necessary. */
|
||||
navTo("wait");
|
||||
timer.interval = 1000;
|
||||
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();
|
||||
}
|
||||
function navNextFeature() {
|
||||
var id;
|
||||
|
||||
/* Skip disabled features */
|
||||
for (id = featureIdByScreen[screen] + 1; id < features.length; id++) {
|
||||
/* 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);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check skipFeature<Name>() */
|
||||
var funcName = "skipFeature" + nameUp;
|
||||
if (eval("typeof " + funcName) === "function"
|
||||
&& eval(funcName + "()")) {
|
||||
console.log("Skipping feature (skip function): " + name);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
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() {
|
||||
if (screenPrevious.length)
|
||||
return navTo(screenPrevious.pop(), false);
|
||||
@@ -161,7 +253,7 @@ Page
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Input validation: user-screens (default_pin, ssh_credentials) */
|
||||
/* Input validation: user-screens (user_pass, ssh_credentials) */
|
||||
function validatePin(userPin, userPinRepeat, errorText) {
|
||||
var pin = userPin.text;
|
||||
var repeat = userPinRepeat.text;
|
||||
@@ -183,7 +275,7 @@ Page
|
||||
if (repeat != pin)
|
||||
return validationFailure(errorText,
|
||||
"The PINs don't match.");
|
||||
|
||||
|
||||
return validationFailureClear(errorText);
|
||||
}
|
||||
function validateSshdUsername(username, errorText) {
|
||||
@@ -297,11 +389,21 @@ Page
|
||||
if (pass == "")
|
||||
return validationFailure(errorText);
|
||||
|
||||
/* This function gets called for the FDE password and for the user
|
||||
* password. As of writing, all distributions shipping the mobile
|
||||
* module are using osk-sdl to type in the FDE password after the
|
||||
* installation, and another keyboard after booting up, to type in the
|
||||
* user password. The osk-sdl password has the same keys as
|
||||
* squeekboard's default layout, and other keyboards should be able to
|
||||
* type these characters in as well. For now, verify that the password
|
||||
* only contains characters that can be typed in by osk-sdl. If you
|
||||
* need this to be more sophisticated, feel free to submit patches to
|
||||
* make this more configurable. */
|
||||
if (!check_chars(pass))
|
||||
return validationFailure(errorText,
|
||||
"The password must only contain" +
|
||||
" these characters, others cannot be" +
|
||||
" typed in at boot time:\n" +
|
||||
" these characters, others can possibly" +
|
||||
" not be typed in after installation:\n" +
|
||||
"\n" +
|
||||
allowed_chars_multiline());
|
||||
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
|
||||
<file>welcome.qml</file>
|
||||
|
||||
<file>default_pin.qml</file> <!-- default user: pin -->
|
||||
<file>install_target.qml</file> <!-- install from external to internal? -->
|
||||
<file>install_target_confirm.qml</file> <!-- overwrite internal storage? -->
|
||||
|
||||
<file>user_pass.qml</file> <!-- default user: password -->
|
||||
<file>ssh_confirm.qml</file> <!-- sshd: enable or not? -->
|
||||
<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_pass.qml</file> <!-- FDE password (optional) -->
|
||||
|
||||
@@ -19,7 +19,7 @@ Item {
|
||||
height: parent.height
|
||||
|
||||
Text {
|
||||
id: welcomeText
|
||||
id: mainText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 30
|
||||
@@ -40,29 +40,29 @@ Item {
|
||||
}
|
||||
|
||||
Button {
|
||||
id: enableButton
|
||||
id: firstButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: welcomeText.bottom
|
||||
anchors.top: mainText.bottom
|
||||
anchors.topMargin: 40
|
||||
width: 500
|
||||
|
||||
text: qsTr("Enable")
|
||||
onClicked: {
|
||||
config.isSshEnabled = true;
|
||||
navTo("ssh_credentials");
|
||||
navNext();
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: enableButton.bottom
|
||||
anchors.top: firstButton.bottom
|
||||
anchors.topMargin: 40
|
||||
width: 500
|
||||
|
||||
text: qsTr("Disable")
|
||||
onClicked: {
|
||||
config.isSshEnabled = false;
|
||||
navTo("fde_confirm");
|
||||
navNextFeature();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ Item {
|
||||
config.sshdUsername = username.text;
|
||||
config.sshdPassword = password.text;
|
||||
|
||||
navTo("fde_confirm");
|
||||
navNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,17 @@ import QtQuick.Window 2.3
|
||||
import QtQuick.VirtualKeyboard 2.1
|
||||
|
||||
Item {
|
||||
property var placeholder: (config.userPasswordNumeric
|
||||
? "PIN"
|
||||
: "Password")
|
||||
property var hints: (config.userPasswordNumeric
|
||||
? Qt.ImhDigitsOnly
|
||||
: Qt.ImhPreferLowercase)
|
||||
property var validateFunc: (config.userPasswordNumeric
|
||||
? validatePin
|
||||
: validatePassword);
|
||||
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
@@ -25,23 +36,31 @@ Item {
|
||||
anchors.topMargin: 30
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: "Set the numeric password of your user. The lockscreen will" +
|
||||
" ask for this PIN. This is <i>not</i> the PIN of your SIM" +
|
||||
" card. Make sure to remember it."
|
||||
text: (function() {
|
||||
if (config.userPasswordNumeric) {
|
||||
return "Set the numeric password of your user. The" +
|
||||
" lockscreen will ask for this PIN. This is" +
|
||||
" <i>not</i> the PIN of your SIM card. Make sure to" +
|
||||
" remember it.";
|
||||
} else {
|
||||
return "Set the password of your user. The lockscreen will" +
|
||||
" ask for this password. Make sure to remember it.";
|
||||
}
|
||||
}())
|
||||
|
||||
width: 500
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: userPin
|
||||
id: userPass
|
||||
anchors.top: description.bottom
|
||||
placeholderText: qsTr("PIN")
|
||||
placeholderText: qsTr(placeholder)
|
||||
echoMode: TextInput.Password
|
||||
onTextChanged: validatePin(userPin, userPinRepeat, errorText)
|
||||
onTextChanged: validateFunc(userPass, userPassRepeat, errorText)
|
||||
text: config.userPassword
|
||||
|
||||
/* Let the virtual keyboard change to digits only */
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
inputMethodHints: hints
|
||||
onActiveFocusChanged: {
|
||||
if(activeFocus) {
|
||||
Qt.inputMethod.update(Qt.ImQueryInput)
|
||||
@@ -54,12 +73,12 @@ Item {
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: userPinRepeat
|
||||
anchors.top: userPin.bottom
|
||||
placeholderText: qsTr("PIN (repeat)")
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
id: userPassRepeat
|
||||
anchors.top: userPass.bottom
|
||||
placeholderText: qsTr(placeholder + " (repeat)")
|
||||
inputMethodHints: hints
|
||||
echoMode: TextInput.Password
|
||||
onTextChanged: validatePin(userPin, userPinRepeat, errorText)
|
||||
onTextChanged: validateFunc(userPass, userPassRepeat, errorText)
|
||||
text: config.userPassword
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
@@ -68,7 +87,7 @@ Item {
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.top: userPinRepeat.bottom
|
||||
anchors.top: userPassRepeat.bottom
|
||||
id: errorText
|
||||
visible: false
|
||||
wrapMode: Text.WordWrap
|
||||
@@ -86,9 +105,9 @@ Item {
|
||||
|
||||
text: qsTr("Continue")
|
||||
onClicked: {
|
||||
if (validatePin(userPin, userPinRepeat, errorText)) {
|
||||
config.userPassword = userPin.text;
|
||||
navTo("ssh_confirm");
|
||||
if (validateFunc(userPass, userPassRepeat, errorText)) {
|
||||
config.userPassword = userPass.text;
|
||||
navNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ Page
|
||||
anchors.topMargin: 150
|
||||
wrapMode: Text.WordWrap
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ Page
|
||||
source: "file:///usr/share/calamares/branding/default-mobile/logo.png"
|
||||
}
|
||||
Text {
|
||||
id: welcomeText
|
||||
id: mainText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: logo.bottom
|
||||
anchors.topMargin: 50
|
||||
@@ -53,12 +53,12 @@ Page
|
||||
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: welcomeText.bottom
|
||||
anchors.top: mainText.bottom
|
||||
anchors.topMargin: 50
|
||||
width: 500
|
||||
|
||||
text: qsTr("Continue")
|
||||
onClicked: navTo("default_pin")
|
||||
onClicked: navNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
modules/os-freebsd/CMakeLists.txt
Normal file
20
modules/os-freebsd/CMakeLists.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
# The OS-FreeBSD module does "all the things" in a FreeBSD installation.
|
||||
# Since the other modules -- users, fstab, grub, pretty much all of them
|
||||
# -- are Linux-specific, it doesn't make much sense to fork each of them
|
||||
# or provide alternatives, so instead we have one module that completes
|
||||
# a FreeBSD installation based on the GlobalStorage values set by
|
||||
# Calamares viewmodules.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# License-Filename: LICENSE
|
||||
#
|
||||
|
||||
calamares_add_plugin( os-freebsd
|
||||
TYPE job
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
FreeBSDJob.cpp
|
||||
SHARED_LIB
|
||||
NO_CONFIG
|
||||
)
|
||||
58
modules/os-freebsd/FreeBSDJob.cpp
Normal file
58
modules/os-freebsd/FreeBSDJob.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
#include "FreeBSDJob.h"
|
||||
|
||||
#include "CalamaresVersion.h"
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QProcess>
|
||||
#include <QThread>
|
||||
|
||||
|
||||
FreeBSDJob::FreeBSDJob( QObject* parent )
|
||||
: Calamares::CppJob( parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FreeBSDJob::~FreeBSDJob() {}
|
||||
|
||||
|
||||
QString
|
||||
FreeBSDJob::prettyName() const
|
||||
{
|
||||
return tr( "FreeBSD Installation Job" );
|
||||
}
|
||||
|
||||
Calamares::JobResult
|
||||
FreeBSDJob::exec()
|
||||
{
|
||||
emit progress( 0.1 );
|
||||
cDebug() << "[FREEBSD]";
|
||||
|
||||
Calamares::JobQueue::instance()->globalStorage()->debugDump();
|
||||
emit progress( 0.5 );
|
||||
|
||||
QThread::sleep( 3 );
|
||||
emit progress( 1.0 );
|
||||
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FreeBSDJob::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
// TODO: actually fetch something from that configuration
|
||||
m_configurationMap = configurationMap;
|
||||
}
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( FreeBSDJobFactory, registerPlugin< FreeBSDJob >(); )
|
||||
39
modules/os-freebsd/FreeBSDJob.h
Normal file
39
modules/os-freebsd/FreeBSDJob.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*/
|
||||
|
||||
#ifndef FREEBSDJOB_H
|
||||
#define FREEBSDJOB_H
|
||||
|
||||
#include "CppJob.h"
|
||||
#include "DllMacro.h"
|
||||
#include "utils/PluginFactory.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
|
||||
class PLUGINDLLEXPORT FreeBSDJob : public Calamares::CppJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FreeBSDJob( QObject* parent = nullptr );
|
||||
virtual ~FreeBSDJob() override;
|
||||
|
||||
QString prettyName() const override;
|
||||
|
||||
Calamares::JobResult exec() override;
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap ) override;
|
||||
|
||||
private:
|
||||
QVariantMap m_configurationMap;
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( FreeBSDJobFactory )
|
||||
|
||||
#endif // FREEBSDJOB_H
|
||||
83
modules/os-nixos/main.py
Normal file
83
modules/os-nixos/main.py
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
#
|
||||
# Calamares is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Calamares is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# License-Filename: LICENSE
|
||||
#
|
||||
|
||||
"""
|
||||
=== NixOS Configuration
|
||||
|
||||
NixOS has its own "do all the things" configuration file which
|
||||
declaratively handles what things need to be done in the target
|
||||
system, and it has an existing tool to "execute" that declarative
|
||||
specification. This module takes configuration values set by
|
||||
Calamares viewmodules (e.g. the users module) and puts
|
||||
them into the configuration file in the target system,
|
||||
and then runs the necessary NixOS specific tools.
|
||||
"""
|
||||
|
||||
import libcalamares
|
||||
import os
|
||||
from time import gmtime, strftime, sleep
|
||||
|
||||
import gettext
|
||||
_ = gettext.translation("calamares-python",
|
||||
localedir=libcalamares.utils.gettext_path(),
|
||||
languages=libcalamares.utils.gettext_languages(),
|
||||
fallback=True).gettext
|
||||
|
||||
|
||||
def pretty_name():
|
||||
return _("NixOS Configuration.")
|
||||
|
||||
|
||||
def run():
|
||||
"""NixOS Configuration."""
|
||||
libcalamares.utils.debug("LocaleDir=" +
|
||||
str(libcalamares.utils.gettext_path()))
|
||||
libcalamares.utils.debug("Languages=" +
|
||||
str(libcalamares.utils.gettext_languages()))
|
||||
|
||||
# TODO: probably want to use the job configuration
|
||||
# with a key "stage" to distinguish generate-config
|
||||
# from execute-config; maybe it wants an "all" as well
|
||||
# to do both.
|
||||
accumulator = "*** Job configuration\n"
|
||||
accumulator += str(libcalamares.job.configuration)
|
||||
libcalamares.utils.debug(accumulator)
|
||||
|
||||
accumulator = "*** GlobalStorage configuration\n"
|
||||
accumulator += "count: " + str(libcalamares.globalstorage.count()) + "\n"
|
||||
accumulator += "keys: {}\n".format(str(libcalamares.globalstorage.keys()))
|
||||
libcalamares.utils.debug(accumulator)
|
||||
|
||||
libcalamares.utils.debug("Run NixOS tools.")
|
||||
|
||||
libcalamares.job.setprogress( 0.1 )
|
||||
sleep(1)
|
||||
libcalamares.job.setprogress( 0.5 )
|
||||
sleep(1)
|
||||
libcalamares.job.setprogress( 1.0 )
|
||||
|
||||
sleep(3)
|
||||
|
||||
# To indicate an error, return a tuple of:
|
||||
# (message, detailed-error-message)
|
||||
return None
|
||||
5
modules/os-nixos/module.desc
Normal file
5
modules/os-nixos/module.desc
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: "job"
|
||||
name: "os-nixos"
|
||||
interface: "python"
|
||||
script: "main.py"
|
||||
Reference in New Issue
Block a user