Merge pull request #1 from PikaOS-Linux/main

Merge back
This commit is contained in:
Ward Nakchbandi (Cosmic Fusion) 2024-02-19 15:04:58 +03:00 committed by GitHub
commit 5569bda9e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 4569 additions and 2207 deletions

47
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: PikaOS Package Release
on:
workflow_dispatch
jobs:
build:
runs-on: self-hosted
container:
image: ghcr.io/pikaos-linux/pika-package-container:latest
volumes:
- /proc:/proc
options: --privileged -it
steps:
- uses: actions/checkout@v3
- name: Import GPG key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.PASSPHRASE }}
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_KEY }}
name: id_rsa
known_hosts: ${{ secrets.KNOWN_HOSTS }}
if_key_exists: replace
- name: Build Package
run: chmod +x ./main.sh && ./main.sh
- name: Release Package
run: chmod +x ./release.sh && ./release.sh
- name: Purge cache
uses: strrife/cloudflare-chunked-purge-action@master
env:
# Zone is required by both authentication methods
CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE }}
CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
PURGE_URLS: ${{ vars.PURGE_URLS }}

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/pkg-pika-installer-gtk4.iml" filepath="$PROJECT_DIR$/.idea/pkg-pika-installer-gtk4.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

296
Cargo.lock generated
View File

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.79"
@ -50,6 +59,12 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "cairo-rs"
version = "0.18.5"
@ -75,6 +90,15 @@ dependencies = [
"system-deps",
]
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-expr"
version = "0.15.6"
@ -109,6 +133,18 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "duct"
version = "0.13.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c"
dependencies = [
"libc",
"once_cell",
"os_pipe",
"shared_child",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -282,6 +318,26 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "gettext-rs"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e49ea8a8fad198aaa1f9655a2524b64b70eb06b2f3ff37da407566c93054f364"
dependencies = [
"gettext-sys",
"locale_config",
]
[[package]]
name = "gettext-sys"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d"
dependencies = [
"cc",
"temp-dir",
]
[[package]]
name = "gio"
version = "0.18.4"
@ -361,6 +417,12 @@ dependencies = [
"system-deps",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "gobject-sys"
version = "0.18.0"
@ -525,9 +587,21 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.4",
"libc",
"windows-sys",
"windows-sys 0.48.0",
]
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libadwaita"
version = "0.5.3"
@ -566,6 +640,28 @@ version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "locale_config"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934"
dependencies = [
"lazy_static",
"objc",
"objc-foundation",
"regex",
"winapi",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
"libc",
]
[[package]]
name = "memchr"
version = "2.7.1"
@ -581,12 +677,51 @@ dependencies = [
"autocfg",
]
[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
"malloc_buf",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
dependencies = [
"block",
"objc",
"objc_id",
]
[[package]]
name = "objc_id"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
dependencies = [
"objc",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "os_pipe"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "pango"
version = "0.18.3"
@ -620,14 +755,19 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]]
name = "pika-installer-gtk4"
version = "0.1.0"
version = "1.0.0"
dependencies = [
"async-channel",
"duct",
"fragile",
"gettext-rs",
"glib",
"glob",
"gtk4",
"libadwaita",
"pretty-bytes",
"serde",
"serde_json",
"time",
"zoha-vte4",
]
@ -728,6 +868,35 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc_version"
version = "0.4.0"
@ -737,6 +906,12 @@ dependencies = [
"semver",
]
[[package]]
name = "ryu"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "semver"
version = "1.0.21"
@ -745,24 +920,35 @@ checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "serde"
version = "1.0.195"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.195"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "serde_json"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_spanned"
version = "0.6.5"
@ -772,6 +958,16 @@ dependencies = [
"serde",
]
[[package]]
name = "shared_child"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "slab"
version = "0.4.9"
@ -828,6 +1024,12 @@ version = "0.12.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae"
[[package]]
name = "temp-dir"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd16aa9ffe15fe021c6ee3766772132c6e98dfa395a167e16864f61a9cfb71d6"
[[package]]
name = "thiserror"
version = "1.0.56"
@ -963,7 +1165,16 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
]
[[package]]
@ -972,13 +1183,28 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm 0.52.0",
"windows_aarch64_msvc 0.52.0",
"windows_i686_gnu 0.52.0",
"windows_i686_msvc 0.52.0",
"windows_x86_64_gnu 0.52.0",
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
]
[[package]]
@ -987,42 +1213,84 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "winnow"
version = "0.5.34"

View File

@ -1,6 +1,6 @@
[package]
name = "pika-installer-gtk4"
version = "0.1.0"
version = "1.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -8,9 +8,14 @@ edition = "2021"
[dependencies]
adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] }
async-channel = "2.1.1"
duct = "0.13.7"
fragile = "2.0.0"
glib = "0.18.5"
gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] }
pretty-bytes = "0.2.2"
time = "0.3.31"
vte = { version = "0.0.2", package = "zoha-vte4", features = ["v0_72"] }
glob = "0.3.1"
gettext-rs = { version = "0.7", features = ["gettext-system"] }
serde_json = "1.0.113"
serde = { version = "1.0", features = ["derive"] }

View File

@ -1,12 +1,17 @@
export PATH := $(PWD):$(PATH)
all:
true
install:
mkdir -p $(DESTDIR)/usr/bin/
#mkdir -p $(DESTDIR)/usr/bin/
cargo fetch
cargo build --release
cp -vf target/release/pika-installer-gtk4 $(DESTDIR)/usr/bin/
chmod 755 $(DESTDIR)/usr/bin/pika-installer-gtk4
#cp -vf target/release/pika-installer-gtk4 $(DESTDIR)/usr/bin/
#chmod 755 $(DESTDIR)/usr/bin/pika-installer-gtk4
mkdir -p $(DESTDIR)/usr/lib/pika/pika-installer-gtk4/bin/
cp -vf target/release/pika-installer-gtk4 $(DESTDIR)/usr/lib/pika/pika-installer-gtk4/bin/
chmod 755 $(DESTDIR)/usr/lib/pika/pika-installer-gtk4/bin/pika-installer-gtk4
mkdir -p $(DESTDIR)/usr/lib/pika/pika-installer-gtk4/scripts/
mkdir -p $(DESTDIR)/usr/share/glib-2.0/schemas/
cp -rvf data/scripts/*.sh $(DESTDIR)/usr/lib/pika/pika-installer-gtk4/scripts/
@ -16,3 +21,4 @@ install:
mkdir -p $(DESTDIR)/usr/share/icons/hicolor/scalable/apps
#cp -vf data/pika-drivers.svg $(DESTDIR)/usr/share/icons/hicolor/scalable/apps/
#cp -vf data/com.pika.drivers.desktop $(DESTDIR)/usr/share/applications/
makepot $(DESTDIR)/usr/share/locale

8
README.md Normal file
View File

@ -0,0 +1,8 @@
### PikaOS installer
A Rust based GTK4 + Libadwaita App
for installing PikaOS.
### Help Us
#### You can help by translating the app
[Weblate](https://hosted.weblate.org/projects/pikaos/pika-installer-gtk4/)

View File

@ -1,5 +1,7 @@
#! /bin/bash
export LANG=en_US.UTF8
set -e
DISK="$(cat "/tmp/pika-installer-gtk4-target-auto.txt")"
@ -7,17 +9,23 @@ LOCALE="$(cat "/tmp/pika-installer-gtk4-lang.txt")"
KEYBOARD="$(cat "/tmp/pika-installer-gtk4-keyboard.txt")"
TIMEZONE="$(cat "/tmp/pika-installer-gtk4-timezone.txt")"
p3_size=$(echo "scale=2 ; $(cat /tmp/pika-installer-p3-size.txt) / 1024 / 1024" | bc | cut -f1 -d".")
touch "/tmp/pika-installer-gtk4-status-parting.txt"
if [[ ! -f "/tmp/pika-installer-gtk4-target-automatic-luks.txt" ]]
then
wipefs -a /dev/${DISK}
for part in $(sudo /usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh get_partitions | grep ${DISK}); do
PARTITION="/dev/$part"
sudo swapoff $PARTITION || true
done
wipefs -af /dev/${DISK}
# Partition the drives
parted -s -a optimal /dev/${DISK} mklabel gpt \
mkpart "linux-efi" 1MiB 513Mib \
mkpart "linux-boot" 513Mib 1537Mib \
mkpart "linux-root" 1537Mib 42497Mib \
mkpart "linux-home" 42497Mib 100% \
mkpart "linux-root" 1537Mib "$p3_size"Mib \
mkpart "linux-home" "$p3_size"Mib 100% \
print
# add p to partition if it's nvme
if echo ${DISK} | grep -i "nvme"
@ -39,7 +47,7 @@ then
mount /dev/${DISK}p2 /media/pika-install-mount/boot
mkdir -p /media/pika-install-mount/boot/efi
mount /dev/${DISK}p1 /media/pika-install-mount/boot/efi
pikainstall -r /media/pika-install-mount/ -c ${LUKS_KEY} -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
pikainstall -r /media/pika-install-mount/ -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
else
sleep 10
# Add filesystems
@ -57,17 +65,21 @@ then
mount /dev/${DISK}2 /media/pika-install-mount/boot
mkdir -p /media/pika-install-mount/boot/efi
mount /dev/${DISK}1 /media/pika-install-mount/boot/efi
pikainstall -r /media/pika-install-mount/ -c ${LUKS_KEY} -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
pikainstall -r /media/pika-install-mount/ -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
fi
else
LUKS_KEY="$(cat "/tmp/pika-installer-gtk4-target-automatic-luks.txt")"
wipefs -a /dev/${DISK}
for part in $(sudo /usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh get_partitions | grep ${DISK}); do
PARTITION="/dev/$part"
sudo swapoff $PARTITION || true
done
wipefs -af /dev/${DISK}
# Partition the drives
parted -s -a optimal /dev/${DISK} mklabel gpt \
mkpart "linux-efi" 1MiB 513Mib \
mkpart "linux-boot" 513Mib 1537Mib \
mkpart "linux-root" 1537Mib 42497Mib \
mkpart "linux-home" 42497Mib 100% \
mkpart "linux-root" 1537Mib "$p3_size"Mib \
mkpart "linux-home" "$p3_size"Mib 100% \
print
# add p to partition if it's nvme
if echo ${DISK} | grep -i "nvme"

View File

@ -1,5 +1,9 @@
#! /bin/bash
export LANG=en_US.UTF8
exec &> >(tee /tmp/pika-installer-gtk4-log)
if [[ -f /tmp/pika-installer-gtk4-target-manual.txt ]]
then
sudo /usr/lib/pika/pika-installer-gtk4/scripts/manual-partition-install.sh

View File

@ -1,18 +1,63 @@
#! /bin/bash
export LANG=en_US.UTF8
set -e
DISK="$(cat "/tmp/pika-installer-gtk4-target-manual.txt")"
LOCALE="$(cat "/tmp/pika-installer-gtk4-lang.txt")"
KEYBOARD="$(cat "/tmp/pika-installer-gtk4-keyboard.txt")"
TIMEZONE="$(cat "/tmp/pika-installer-gtk4-timezone.txt")"
touch "/tmp/pika-installer-gtk4-status-parting.txt"
if [[ ! -f "/tmp/pika-installer-gtk4-target-manual-luks.txt" ]]
rm -rf /tmp/pika-installer-gtk4-swaplist || true
if ls /tmp/pika-installer-gtk4-target-manual-luks-p*.json
then
pikainstall -r ${DISK}/ -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
rm -rf /tmp/pika-installer-gtk4-crypttab || true
touch /tmp/pika-installer-gtk4-crypttab
for cryptentry in /tmp/pika-installer-gtk4-target-manual-luks-p*.json; do
if [[ -z $(jq -r .password $cryptentry) ]]
then
LUKS=$(jq -r .partition $cryptentry)
MAP=$(jq -r .partition $cryptentry | cut -d "/" -f2-)
UUID="$(blkid "$(lsblk -sJp | jq -r --arg dsk /dev/"$LUKS" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name')" -s UUID -o value)"
echo "$MAP UUID="$UUID" none luks,discard" >> /tmp/pika-installer-gtk4-crypttab
else
LUKS_KEY="$(cat "/tmp/pika-installer-gtk4-target-manual-luks.txt")"
pikainstall -r ${DISK}/ -c ${LUKS_KEY} -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
LUKS=$(jq -r .partition $cryptentry)
MAP=$(jq -r .partition $cryptentry | cut -d "/" -f2-)
UUID="$(blkid "$(lsblk -sJp | jq -r --arg dsk /dev/"$LUKS" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name')" -s UUID -o value)"
LUKS_PASSWD=$(jq -r .password $cryptentry)
echo "$MAP UUID="$UUID" /key-"$MAP".txt luks" >> /tmp/pika-installer-gtk4-crypttab
touch /key-"$MAP".txt
openssl genrsa > /key-"$MAP".txt
echo $LUKS_PASSWD | cryptsetup luksAddKey UUID=$UUID /key-"$MAP".txt -
fi
done
fi
for drivemount in /tmp/pika-installer-gtk4-target-manual-p*.json; do
PARTITION="/dev/$(jq -r .partition $drivemount)"
MOUNTPOINT="/media/pika-install-mount/$(jq -r .mountpoint $drivemount)"
MOUNTOPT=$(jq -r .mountopt $drivemount)
if [[ $MOUNTPOINT = '/media/pika-install-mount/[SWAP]' ]]
then
touch /tmp/pika-installer-gtk4-swaplist
echo $PARTITION > /tmp/pika-installer-gtk4-swaplist
elif [[ -z $MOUNTOPT ]]
then
mkdir -p $MOUNTPOINT
mount $PARTITION $MOUNTPOINT
else
mkdir -p $MOUNTPOINT
mount -o $MOUNTOPT $PARTITION $MOUNTPOINT
fi
done
if [[ ! -f "/tmp/pika-installer-gtk4-crypttab" ]]
then
pikainstall -r /media/pika-install-mount/ --manual 1 -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
else
pikainstall -r /media/pika-install-mount/ --manual 2 -l ${LOCALE} -k ${KEYBOARD} -t ${TIMEZONE} && touch /tmp/pika-installer-gtk4-successful.txt || touch /tmp/pika-installer-gtk4-fail.txt && exit 1
fi

View File

@ -1,8 +1,10 @@
#! /bin/bash
export LANG=en_US.UTF8
if [[ "$1" = "get_block_devices" ]]
then
lsblk -dn -o NAME
lsblk -dn -o NAME | grep -v -i -E 'loop|zram|sr|cdrom|portal'
fi
if [[ "$1" = "get_block_size" ]]
@ -12,12 +14,14 @@ then
lsblk -b --output SIZE -n -d /dev/"$2"
fi
if [[ "$1" = "check_home_encryption" ]]
if [[ "$1" = "has_encryption" ]]
then
if blkid -o value -s TYPE $(lsblk -sJp | jq -r --arg dsk "$(df -P -h -T "$2/home" | awk 'END{print $1}')" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name') | grep -i luks > /dev/null 2>&1
if blkid -o value -s TYPE $(lsblk -sJp | jq -r --arg dsk /dev/"$2" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name') | grep -i luks > /dev/null 2>&1
then
echo "$2 has encryption"
exit 0
else
echo "$2 is unencrypted"
exit 1
fi
fi
@ -32,6 +36,36 @@ then
fi
fi
if [[ "$1" = "get_partitions" ]]
then
lsblk -ln -o NAME,TYPE | grep -E "part|crypt|lvm" | awk '{print $1}' | while read i ; do
if lsblk -ln -o NAME,TYPE | grep "$i" | grep "crypt" > /dev/null 2>&1
then
echo "mapper/$(lsblk -ln -o NAME,TYPE | grep "$i" | awk '{print $1}')"
fi
if lsblk -ln -o NAME,TYPE | grep "$i" | grep "lvm" > /dev/null 2>&1
then
echo "mapper/$(lsblk -ln -o NAME,TYPE | grep "$i" | awk '{print $1}')"
fi
if lsblk -ln -o NAME,TYPE | grep "$i" | grep "part" > /dev/null 2>&1
then
lsblk -ln -o NAME,TYPE | grep "$i" | awk '{print $1}'
fi
done
fi
if [[ "$1" = "get_part_fs" ]]
then
lsblk -ln -o NAME,FSTYPE | grep "$2" | awk '{print $2}'
fi
if [[ "$1" = "get_part_size" ]]
then
lsblk -b --output SIZE -n -d /dev/"$2"
fi
if [[ "$1" = "home_not_boot" ]]
then
if [[ $(blkid "$(df -P -h -T "$2/boot" | awk 'END{print $1}')" -s UUID -o value) == $(blkid "$(df -P -h -T "$2/home" | awk 'END{print $1}')" -s UUID -o value) ]]
@ -83,9 +117,9 @@ then
fi
fi
if [[ "$1" = "check_home_luks_passwd" ]]
if [[ "$1" = "test_luks_passwd" ]]
then
if printf "$3" | cryptsetup luksOpen --test-passphrase UUID="$(blkid "$(lsblk -sJp | jq -r --arg dsk "$(df -P -h -T "$2"/home | awk 'END{print $1}')" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name')" -s UUID -o value)"
if printf "$3" | cryptsetup luksOpen --test-passphrase UUID="$(blkid "$(lsblk -sJp | jq -r --arg dsk /dev/"$2" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name')" -s UUID -o value)"
then
exit 0
else

5
debian/changelog vendored Normal file
View File

@ -0,0 +1,5 @@
pika-installer-gtk4 (1.0.0-100pika15) pikauwu; urgency=low
* First release
-- Ward Nakchbandi <hotrod.master@hotmail.com> Thu, 20 Sep 2022 22:01:00 +0000

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

19
debian/control vendored Normal file
View File

@ -0,0 +1,19 @@
Source: pika-installer-gtk4
Section: utils
Priority: optional
Maintainer: International Arms dealers <chipichipi@chapachapa.com>
Build-Depends: build-essential,
debhelper,
cargo,
libadwaita-1-dev,
libgtk-4-dev,
desktop-file-utils,
make,
libvte-2.91-gtk4-dev
Rules-Requires-Root: no
Package: pika-installer-gtk4
Architecture: any
Depends: ${shlibs:Depends},
pikainstall
Description: A frontend in GTK 4 and Libadwaita for pikainstall.

16
debian/extras/pika-installer vendored Normal file
View File

@ -0,0 +1,16 @@
#! /bin/bash
if env | grep XDG_SESSION_DESKTOP | grep -i -E 'gnome|ubuntu|pika'
then
gnome-session-inhibit /usr/lib/pika/pika-installer-gtk4/bin/pika-installer-gtk4
elif env | grep XDG_SESSION_DESKTOP | grep -i -E 'kde|plasma'
then
# Disable Auto Suspend
cp -vf /etc/pika-installer-gtk4/powermanagementprofilesrc ~/.config/ || exit 1
# Disable screen lock
kwriteconfig5 --file kscreenlockerrc --group Daemon --key Autolock false
qdbus org.freedesktop.ScreenSaver /ScreenSaver configure
/usr/lib/pika/pika-installer-gtk4/bin/pika-installer-gtk4
else
/usr/lib/pika/pika-installer-gtk4/bin/pika-installer-gtk4
fi

View File

@ -0,0 +1,14 @@
[Desktop Entry]
Icon=calamares
Name=Install PikaOS Linux
Exec=pika-installer
Icon=calamares
Terminal=false
Type=Application
Terminal=false
StartupNotify=true
X-GNOME-Autostart-enabled=true
X-KDE-AutostartScript=true
Categories=GNOME;GTK;Utility;
Keywords=Gnome;GTK
NoDisplay=true

13
debian/extras/pika-installer.desktop vendored Normal file
View File

@ -0,0 +1,13 @@
[Desktop Entry]
Icon=calamares
Name=Install PikaOS Linux
Exec=pika-installer
Icon=calamares
Terminal=false
Type=Application
Terminal=false
StartupNotify=true
X-GNOME-Autostart-enabled=true
X-KDE-AutostartScript=true
Categories=GNOME;GTK;Utility;
Keywords=Gnome;GTK

57
debian/extras/powermanagementprofilesrc vendored Normal file
View File

@ -0,0 +1,57 @@
[AC]
icon=battery-charging
[AC][DPMSControl]
idleTime=600
lockBeforeTurnOff=0
[AC][DimDisplay]
idleTime=300000
[AC][HandleButtonEvents]
lidAction=1
powerButtonAction=16
powerDownAction=16
[Battery]
icon=battery-060
[Battery][DPMSControl]
idleTime=300
lockBeforeTurnOff=0
[Battery][DimDisplay]
idleTime=120000
[Battery][HandleButtonEvents]
lidAction=1
powerButtonAction=16
powerDownAction=16
[Battery][SuspendSession]
idleTime=600000
suspendThenHibernate=false
suspendType=1
[LowBattery]
icon=battery-low
[LowBattery][BrightnessControl]
value=30
[LowBattery][DPMSControl]
idleTime=120
lockBeforeTurnOff=0
[LowBattery][DimDisplay]
idleTime=60000
[LowBattery][HandleButtonEvents]
lidAction=1
powerButtonAction=16
powerDownAction=16
[LowBattery][SuspendSession]
idleTime=300000
suspendThenHibernate=false
suspendType=1

11
debian/postinst vendored Normal file
View File

@ -0,0 +1,11 @@
#!/bin/sh
set -e
update-mime-database /usr/share/mime
update-desktop-database
glib-compile-schemas /usr/share/glib-2.0/schemas

29
debian/rules vendored Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@
override_dh_missing:
dh_missing
mkdir -pv debian/pika-installer-gtk4/usr/share/applications/
mkdir -pv debian/pika-installer-gtk4/etc/xdg/autostart/
mkdir -pv debian/pika-installer-gtk4/usr/bin/
mkdir -pv debian/pika-installer-gtk4/etc/pika-installer-gtk4/
cp -vf debian/extras/pika-installer.desktop debian/pika-installer-gtk4/usr/share/applications/
cp -vf debian/extras/pika-installer-autostart.desktop debian/pika-installer-gtk4/etc/xdg/autostart/
cp -vf debian/extras/pika-installer debian/pika-installer-gtk4/usr/bin/
chmod +x debian/pika-installer-gtk4/usr/bin/pika-installer
cp -vf debian/extras/powermanagementprofilesrc debian/pika-installer-gtk4/etc/pika-installer-gtk4/

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (native)

15
main.sh Normal file
View File

@ -0,0 +1,15 @@
# Clone Upstream
mkdir -p ./pika-installer-gtk4
rsync -av --progress ./* ./pika-installer-gtk4 --exclude ./pika-installer-gtk4
cd ./pika-installer-gtk4
# Get build deps
apt-get build-dep ./ -y
# Build package
dpkg-buildpackage --no-sign
# Move the debs to output
cd ../
mkdir -p ./output
mv ./*.deb ./output/

9
makepot Executable file
View File

@ -0,0 +1,9 @@
#! /bin/bash
set -e
for i in po/*.po
do
mkdir -p "$1"/"$(echo $i | cut -d"/" -f2 | cut -d"." -f1)"/LC_MESSAGES
msgfmt -v $i -o "$1"/"$(echo $i | cut -d"/" -f2 | cut -d"." -f1)"/LC_MESSAGES/pika-installer-gtk4.mo
done

294
po/bg.po Normal file
View File

@ -0,0 +1,294 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2024-02-09 17:48+0300\n"
"PO-Revision-Date: 2024-02-19 11:46+0000\n"
"Last-Translator: Peter Tsvetkov <me4odefy@gmail.com>\n"
"Language-Team: Bulgarian <https://hosted.weblate.org/projects/pikaos/"
"pika-installer-gtk4-old/bg/>\n"
"Language: bg\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.4\n"
"X-Poedit-Basepath: .\n"
msgid "pikaos_installer"
msgstr "pikaos_инсталатор"
msgid "welcome_to_pikaos"
msgstr "добреошли_в_pikaos"
msgid "use_pikaos_in_live_media"
msgstr "използвай_pikaos_без_да_инсталираш"
msgid "install_distro_to_system"
msgstr "инсталирай_дистрибуцията"
msgid "welcome"
msgstr "добреошли"
msgid "back"
msgstr "върни"
msgid "next"
msgstr "следващ"
msgid "select_a_timezone"
msgstr "избертеасоваона"
msgid "please_select_timezone"
msgstr "Моля, изберете времева зона"
msgid "no_timezone_select"
msgstr "Не е избрава времева зона"
msgid "timezone"
msgstr "Времева зона"
msgid "choose_install_method"
msgstr "Изберете метод на инсталиране"
msgid "manual_partition_drive"
msgstr "ръчно_разделянеа_диска"
msgid "auto_partition_drive"
msgstr "автоматично_разделянеа_диска"
msgid "manual_part_installer"
msgstr "ръчно_"
msgid "use_utility_manual"
msgstr ""
msgid "open_gparted"
msgstr "отвори_gparter"
msgid "manual_part_note"
msgstr ""
msgid "refresh_part_table"
msgstr "обнови_таблицаа_дяловете"
msgid "validate_fs_table"
msgstr "валидиранеаблицааайлова_система"
msgid "fstab_status_valid"
msgstr "таблицатааайловата_система_еалидна"
msgid "part_need_mapper"
msgstr ""
msgid "fstab_subvol_warn"
msgstr ""
msgid "fstab_multiple_part_mountpoint_err"
msgstr ""
msgid "fstab_no_mountpoint_err"
msgstr ""
msgid "fstab_no_partition_err"
msgstr ""
msgid "fstab_badfs"
msgstr ""
msgid "fstab_small_efi_size"
msgstr "размерът_на_EFI_дялът_еалък"
msgid "fstab_badfs_efi"
msgstr ""
msgid "fstab_small_boot_size"
msgstr ""
msgid "fstab_badfs_boot"
msgstr ""
msgid "fstab_small_root_size"
msgstr ""
msgid "fstab_badfs_root"
msgstr ""
msgid "fstab_small_home_size"
msgstr ""
msgid "fstab_badfs_home"
msgstr ""
msgid "fstab_badfs_swap"
msgstr ""
msgid "fstab_bad_mountpoint"
msgstr ""
msgid "fstab_bad_mountpoint_msg"
msgstr ""
msgid "select_a_language"
msgstr ""
msgid "please_select_locale"
msgstr ""
msgid "no_locale_selected"
msgstr ""
msgid "language"
msgstr ""
msgid "select_a_keyboard"
msgstr ""
msgid "please_select_keyboard"
msgstr ""
msgid "no_keyboard_selected"
msgstr ""
msgid "test_your_keyboard"
msgstr ""
msgid "keyboard"
msgstr ""
msgid "luks_password_for"
msgstr ""
msgid "luks_how_should"
msgstr ""
msgid "be_added_crypttab"
msgstr ""
msgid "unlock_boot_manually"
msgstr ""
msgid "unlock_boot_manual"
msgstr ""
msgid "sit_back_relax"
msgstr ""
msgid "language_detail"
msgstr ""
msgid "timezone_detail"
msgstr ""
msgid "keyboard_detail"
msgstr ""
msgid "mounted_on_detail"
msgstr ""
msgid "install_target_detail"
msgstr ""
msgid "confirm_install_pika"
msgstr ""
msgid "view_logs"
msgstr ""
msgid "parting_status_text"
msgstr ""
msgid "image_status_text"
msgstr ""
msgid "flag1_status_text"
msgstr ""
msgid "flag2_status_text"
msgstr ""
msgid "crypt_status_text"
msgstr ""
msgid "lang_status_text"
msgstr ""
msgid "boot_status_status_text"
msgstr ""
msgid "post_status_text"
msgstr ""
msgid "pikaos_eula_agreement"
msgstr ""
msgid "please_read_eula"
msgstr ""
msgid "eula_buffer"
msgstr ""
msgid "i_agree_eula"
msgstr ""
msgid "eula"
msgstr ""
msgid "pika_nowork_csm"
msgstr ""
msgid "exit"
msgstr ""
msgid "subtitle_partition"
msgstr ""
msgid "title_mountpoint"
msgstr ""
msgid "title_mountopt"
msgstr ""
msgid "pika_install_good"
msgstr ""
msgid "reboot"
msgstr ""
msgid "pika_install_bad"
msgstr ""
msgid "logs"
msgstr ""
msgid "auto_part_installer"
msgstr "Автоматичен дялов инсталатор"
msgid "choose_drive_auto"
msgstr "Автоматичо избери диск"
msgid "no_drive_auto_selected"
msgstr ""
msgid "no_disk_specified"
msgstr "Не е избран диск"
msgid "luks_yes_but_empty"
msgstr ""
msgid "enable_luks2_enc"
msgstr "Активирайте Luks2 криптиране"
msgid "luks2_password"
msgstr "Luks2 парола"
msgid "disk_auto_target_small"
msgstr ""
msgid "installation"
msgstr "Инсталация"
msgid "done"
msgstr "Завършено"
msgid "partitioning"
msgstr ""

294
po/de.po Normal file
View File

@ -0,0 +1,294 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2024-02-09 17:48+0300\n"
"PO-Revision-Date: 2024-02-19 11:57+0000\n"
"Last-Translator: selektionsrest <selektionsrest@hotmail.de>\n"
"Language-Team: German <https://hosted.weblate.org/projects/pikaos/"
"pika-installer-gtk4-old/de/>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.4\n"
"X-Poedit-Basepath: .\n"
msgid "pikaos_installer"
msgstr "PikaOS-Installationsprogramm"
msgid "welcome_to_pikaos"
msgstr "Willkommen bei PikaOS"
msgid "use_pikaos_in_live_media"
msgstr "Nutze PikaOS im Live Modus"
msgid "install_distro_to_system"
msgstr "PikaOS installieren"
msgid "welcome"
msgstr "Willkommen"
msgid "back"
msgstr "Zurück"
msgid "next"
msgstr "Weiter"
msgid "select_a_timezone"
msgstr "Wähle eine Zeitzone"
msgid "please_select_timezone"
msgstr "Bitte wähle eine Zeitzone"
msgid "no_timezone_select"
msgstr "Keine Zeitzone ausgewählt"
msgid "timezone"
msgstr "Zeitzone"
msgid "choose_install_method"
msgstr "Wähle eine Installationsmethode"
msgid "manual_partition_drive"
msgstr "Manuelle Partitionierung"
msgid "auto_partition_drive"
msgstr "Automatische Partitionierung"
msgid "manual_part_installer"
msgstr ""
msgid "use_utility_manual"
msgstr ""
msgid "open_gparted"
msgstr "Öffne Gparted"
msgid "manual_part_note"
msgstr ""
msgid "refresh_part_table"
msgstr "Aktualisiere Partitionstabelle"
msgid "validate_fs_table"
msgstr ""
msgid "fstab_status_valid"
msgstr ""
msgid "part_need_mapper"
msgstr ""
msgid "fstab_subvol_warn"
msgstr ""
msgid "fstab_multiple_part_mountpoint_err"
msgstr ""
msgid "fstab_no_mountpoint_err"
msgstr ""
msgid "fstab_no_partition_err"
msgstr ""
msgid "fstab_badfs"
msgstr ""
msgid "fstab_small_efi_size"
msgstr ""
msgid "fstab_badfs_efi"
msgstr ""
msgid "fstab_small_boot_size"
msgstr ""
msgid "fstab_badfs_boot"
msgstr ""
msgid "fstab_small_root_size"
msgstr ""
msgid "fstab_badfs_root"
msgstr ""
msgid "fstab_small_home_size"
msgstr ""
msgid "fstab_badfs_home"
msgstr ""
msgid "fstab_badfs_swap"
msgstr ""
msgid "fstab_bad_mountpoint"
msgstr ""
msgid "fstab_bad_mountpoint_msg"
msgstr ""
msgid "select_a_language"
msgstr "Sprache auswählen"
msgid "please_select_locale"
msgstr ""
msgid "no_locale_selected"
msgstr ""
msgid "language"
msgstr "Sprache"
msgid "select_a_keyboard"
msgstr ""
msgid "please_select_keyboard"
msgstr ""
msgid "no_keyboard_selected"
msgstr ""
msgid "test_your_keyboard"
msgstr ""
msgid "keyboard"
msgstr "Tastatur"
msgid "luks_password_for"
msgstr "Luks Passwort für"
msgid "luks_how_should"
msgstr ""
msgid "be_added_crypttab"
msgstr ""
msgid "unlock_boot_manually"
msgstr ""
msgid "unlock_boot_manual"
msgstr ""
msgid "sit_back_relax"
msgstr ""
msgid "language_detail"
msgstr ""
msgid "timezone_detail"
msgstr ""
msgid "keyboard_detail"
msgstr ""
msgid "mounted_on_detail"
msgstr ""
msgid "install_target_detail"
msgstr ""
msgid "confirm_install_pika"
msgstr ""
msgid "view_logs"
msgstr ""
msgid "parting_status_text"
msgstr ""
msgid "image_status_text"
msgstr ""
msgid "flag1_status_text"
msgstr ""
msgid "flag2_status_text"
msgstr ""
msgid "crypt_status_text"
msgstr ""
msgid "lang_status_text"
msgstr ""
msgid "boot_status_status_text"
msgstr ""
msgid "post_status_text"
msgstr ""
msgid "pikaos_eula_agreement"
msgstr ""
msgid "please_read_eula"
msgstr ""
msgid "eula_buffer"
msgstr ""
msgid "i_agree_eula"
msgstr ""
msgid "eula"
msgstr ""
msgid "pika_nowork_csm"
msgstr ""
msgid "exit"
msgstr ""
msgid "subtitle_partition"
msgstr ""
msgid "title_mountpoint"
msgstr ""
msgid "title_mountopt"
msgstr ""
msgid "pika_install_good"
msgstr ""
msgid "reboot"
msgstr ""
msgid "pika_install_bad"
msgstr ""
msgid "logs"
msgstr ""
msgid "auto_part_installer"
msgstr ""
msgid "choose_drive_auto"
msgstr ""
msgid "no_drive_auto_selected"
msgstr ""
msgid "no_disk_specified"
msgstr ""
msgid "luks_yes_but_empty"
msgstr ""
msgid "enable_luks2_enc"
msgstr ""
msgid "luks2_password"
msgstr ""
msgid "disk_auto_target_small"
msgstr ""
msgid "installation"
msgstr ""
msgid "done"
msgstr ""
msgid "partitioning"
msgstr ""

323
po/en_US.po Normal file
View File

@ -0,0 +1,323 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2024-02-09 17:48+0300\n"
"PO-Revision-Date: 2024-02-19 00:21+0300\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.4\n"
"X-Poedit-Basepath: .\n"
msgid "pikaos_installer"
msgstr "PikaOS Installer"
msgid "welcome_to_pikaos"
msgstr "Welcome to PikaOS"
msgid "use_pikaos_in_live_media"
msgstr "Use PikaOS in Live media"
msgid "install_distro_to_system"
msgstr "Install Distro to System"
msgid "welcome"
msgstr "Welcome"
msgid "back"
msgstr "Back"
msgid "next"
msgstr "Next"
msgid "select_a_timezone"
msgstr "Select a timezone"
msgid "please_select_timezone"
msgstr "Please select a Time Zone for the system to use"
msgid "no_timezone_select"
msgstr "No Time Zone selected"
msgid "timezone"
msgstr "Time Zone"
msgid "choose_install_method"
msgstr "Choose an install method"
msgid "manual_partition_drive"
msgstr "Manually Partition The Drive"
msgid "auto_partition_drive"
msgstr ""
"Automatically Partition\n"
"The Drive"
msgid "manual_part_installer"
msgstr "Manual Partitioning Installer"
msgid "use_utility_manual"
msgstr "Use this utility to partition/mount/format your drives."
msgid "open_gparted"
msgstr "Open GPARTED"
msgid "manual_part_note"
msgstr ""
" - Press the plus button below to begin adding filesystem entries.\n"
"Notes:\n"
" - This installer doesn't erase any data automatically, format your drives manually via gparted.\n"
" - To Add a linux-swap partition set mountpoint to [SWAP]\n"
" - We recommend the following partitions as a base layout:\n"
" /boot ~ 1000mb ext4.\n"
" /boot/efi ~ 512mb vfat/fat32.\n"
" / >= 25GB btrfs.\n"
" "
msgid "refresh_part_table"
msgstr "Refresh Partition Table"
msgid "validate_fs_table"
msgstr "Validate Filesystem Table"
msgid "fstab_status_valid"
msgstr "Filesystem Table Status: All entries are valid!"
msgid "part_need_mapper"
msgstr "This partition needs a mapper!"
msgid "fstab_subvol_warn"
msgstr "Filesystem Table Warning: Partition reuse check will be skipped due to subvol usage."
msgid "fstab_multiple_part_mountpoint_err"
msgstr "Filesystem Table Error: Multiple partitions are configured to the same mountpoint!"
msgid "fstab_no_mountpoint_err"
msgstr "Filesystem Table Error: One or more partitions don't have a mountpoint configured!"
msgid "fstab_no_partition_err"
msgstr "Filesystem Table Error: One or more entries don't have a partition configured!"
msgid "fstab_badfs"
msgstr "Filesystem Table Error: Invalid filesystem: (/dev/"
msgid "fstab_small_efi_size"
msgstr ") Must at least be 512MBs!"
msgid "fstab_badfs_efi"
msgstr ") Must be FAT32/vFAT to be mounted at /boot/efi!"
msgid "fstab_small_boot_size"
msgstr ") Must at least be 1GBs!"
msgid "fstab_badfs_boot"
msgstr ") Must not be FAT32/vFAT to be mounted at /boot!"
msgid "fstab_small_root_size"
msgstr ") Must at least be 26GBs!"
msgid "fstab_badfs_root"
msgstr ""
") Must be a Linux* compatible filesystem such as:\n"
" ext4/btrfs/xfs/f2fs to be mounted at /!"
msgid "fstab_small_home_size"
msgstr ") Must at least be 11GBs!"
msgid "fstab_badfs_home"
msgstr ""
") Must be a Linux* compatible filesystem such as:\n"
" ext4/btrfs/xfs/f2fs to be mounted at /home!"
msgid "fstab_badfs_swap"
msgstr ") Must not be swap to be used as [SWAP]!"
msgid "fstab_bad_mountpoint"
msgstr "Filesystem Table Error: Invalid mountpoint: ("
msgid "fstab_bad_mountpoint_msg"
msgstr ") Is not a valid mountpoint!"
msgid "select_a_language"
msgstr "Select a language"
msgid "please_select_locale"
msgstr "Please select a locale for the system to use"
msgid "no_locale_selected"
msgstr "No locale selected"
msgid "language"
msgstr "Language"
msgid "select_a_keyboard"
msgstr "Select a keyboard"
msgid "please_select_keyboard"
msgstr "Please select a Keyboard layout for the system to use"
msgid "no_keyboard_selected"
msgstr "No Keyboard Layout selected"
msgid "test_your_keyboard"
msgstr "Test Your Keyboard here!"
msgid "keyboard"
msgstr "Keyboard"
msgid "luks_password_for"
msgstr "LUKS Password for "
msgid "luks_how_should"
msgstr "How should "
msgid "be_added_crypttab"
msgstr " be added to /etc/crypttab?"
msgid "unlock_boot_manually"
msgstr "Unlock on boot manually"
msgid "unlock_boot_manual"
msgstr "Automatic Unlock with root unlock"
msgid "sit_back_relax"
msgstr "Sit back, Relax, and watch the show."
msgid "language_detail"
msgstr "Language:"
msgid "timezone_detail"
msgstr "Timezone:"
msgid "keyboard_detail"
msgstr "Keyboard layout:"
msgid "mounted_on_detail"
msgstr " mounted on "
msgid "install_target_detail"
msgstr "Install Target:"
msgid "confirm_install_pika"
msgstr "Confirm & Install PikaOS"
msgid "view_logs"
msgstr "View Logs"
msgid "parting_status_text"
msgstr "Partitioning The Target Drives."
msgid "image_status_text"
msgstr "Writing image to target."
msgid "flag1_status_text"
msgstr "Enabling bls_boot flag on /boot."
msgid "flag2_status_text"
msgstr "Enabling efi flag on /boot/efi."
msgid "crypt_status_text"
msgstr "Setting up encryption crypttab."
msgid "lang_status_text"
msgstr "Setting Up Language and Keyboard."
msgid "boot_status_status_text"
msgstr "Configuring bootloader."
msgid "post_status_text"
msgstr "Running post installation script."
msgid "pikaos_eula_agreement"
msgstr "PikaOS User license Agreement"
msgid "please_read_eula"
msgstr "Please carefully read and make sure you consent to the following before installing PikaOS:"
msgid "eula_buffer"
msgstr ""
"There are a few things to keep in mind: \n"
" 1 - You understand that this distribution is -NOT- to be considered an Ubuntu Flavor. \n"
" 2 - This is a hobby distribution, so we will try our best to provide formal support but it will -NOT- be guaranteed. \n"
" 3 - Although PikaOS might provide identical patches and user experience to the Nobara project, we are -NOT- directly a part of them so questions and bug reports should not be sent directly to them (they dont have to deal with it!) \n"
" 4 - While the installer is running DO NOT INTERRUPT IT! or you will end up with a corrupted system. \n"
" 5 - Try to use pikman instead of apt when using the terminal, it is much faster! \n"
" 6 - You understand the xone driver downloads needed binaries locally and does not directly package or distribute any copyrighted firmware or other related data. \n"
" 7 - Automatic partitioning will format all partitons on a drive, so if you want to dualboot make a separate EFI partition for PikaOS and use manual partitioning \n"
" 8 - In case you need the login info for this session: \n"
" - username: pikaos \n"
" - password: \n"
" MEANING: JUST PRESS ENTER"
msgid "i_agree_eula"
msgstr "I Agree and Accept the User license Agreement"
msgid "eula"
msgstr "EULA"
msgid "pika_nowork_csm"
msgstr "PikaOS Only works on GPT UEFI Systems, this machine is booted in CSM/LEGACY mode."
msgid "exit"
msgstr "Exit"
msgid "subtitle_partition"
msgstr "Partition"
msgid "title_mountpoint"
msgstr "Mountpoint"
msgid "title_mountopt"
msgstr "Additional Mount Options"
msgid "pika_install_good"
msgstr "The installation of PikaOS has been completed sucessfully."
msgid "reboot"
msgstr "Reboot"
msgid "pika_install_bad"
msgstr ""
"PikaOS has Failed!\n"
"Check logs for further info."
msgid "logs"
msgstr "Log"
msgid "auto_part_installer"
msgstr "Automatic Partitioning Installer"
msgid "choose_drive_auto"
msgstr ""
"Choose the Drive you want to install PikaOS on\n"
"Note: This will erase the entire drive backup your data!"
msgid "no_drive_auto_selected"
msgstr "No disk selected for installation"
msgid "no_disk_specified"
msgstr "No Disk specified."
msgid "luks_yes_but_empty"
msgstr "LUKS Encryption Enabled but no password provided."
msgid "enable_luks2_enc"
msgstr "Enable LUKS2 Disk Encryption"
msgid "luks2_password"
msgstr "LUKS Password"
msgid "disk_auto_target_small"
msgstr "Disk Size too small, PikaOS needs 40GB Disk"
msgid "installation"
msgstr "Installation"
msgid "done"
msgstr "Done"
msgid "partitioning"
msgstr "Partitioning"

8
release.sh Normal file
View File

@ -0,0 +1,8 @@
# send debs to server
rsync -azP --include './' --include '*.deb' --exclude '*' ./output/ ferreo@direct.pika-os.com:/srv/www/incoming/
# add debs to repo
ssh ferreo@direct.pika-os.com 'aptly repo add -force-replace -remove-files pikauwu-main /srv/www/incoming/'
# publish the repo
ssh ferreo@direct.pika-os.com 'aptly publish update -batch -skip-contents -force-overwrite pikauwu filesystem:pikarepo:'

View File

@ -0,0 +1,285 @@
// Use libraries
use adw::prelude::*;
use adw::*;
use glib::*;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
use std::io::BufRead;
use std::io::BufReader;
use std::process::Command;
use std::process::Stdio;
pub fn automatic_partitioning(
partitioning_stack: &gtk::Stack,
bottom_next_button: &gtk::Button,
) -> (gtk::TextBuffer, gtk::TextBuffer) {
let partition_method_automatic_main_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.margin_bottom(15)
.margin_top(15)
.margin_end(15)
.margin_start(15)
.build();
let partition_method_automatic_header_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.build();
// the header text for the partitioning page
let partition_method_automatic_header_text = gtk::Label::builder()
.label(gettext("auto_part_installer"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(5)
.build();
partition_method_automatic_header_text.add_css_class("header_sized_text");
// the header icon for the partitioning icon
let partition_method_automatic_header_icon = gtk::Image::builder()
.icon_name("builder")
.halign(gtk::Align::Start)
.hexpand(true)
.pixel_size(78)
.margin_top(15)
.margin_bottom(15)
.margin_start(0)
.margin_end(15)
.build();
let partition_method_automatic_selection_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
let partition_method_automatic_selection_text = gtk::Label::builder()
.label(gettext("choose_drive_auto"))
.justify(Justification::Center)
.halign(gtk::Align::Center)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
partition_method_automatic_selection_text.add_css_class("medium_sized_text");
let devices_selection_expander_row = adw::ExpanderRow::builder()
.title(gettext("no_drive_auto_selected"))
.build();
let null_checkbutton = gtk::CheckButton::builder().build();
let devices_selection_expander_row_viewport =
gtk::ScrolledWindow::builder().height_request(200).build();
let devices_selection_expander_row_viewport_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
devices_selection_expander_row_viewport
.set_child(Some(&devices_selection_expander_row_viewport_box));
let devices_selection_expander_row_viewport_listbox = gtk::ListBox::builder()
.selection_mode(SelectionMode::None)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
devices_selection_expander_row_viewport_listbox.add_css_class("boxed-list");
devices_selection_expander_row_viewport_listbox.append(&devices_selection_expander_row);
devices_selection_expander_row.add_row(&devices_selection_expander_row_viewport);
let partition_method_automatic_get_devices_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_block_devices")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap_or_else(|e| panic!("failed {}", e));
let partition_method_automatic_get_devices_reader = BufReader::new(
partition_method_automatic_get_devices_cli
.stdout
.expect("could not get stdout"),
);
let partition_method_automatic_disk_error_label = gtk::Label::builder()
.label(gettext("no_disk_specified"))
.halign(Align::Start)
.valign(Align::End)
.vexpand(true)
.build();
partition_method_automatic_disk_error_label.add_css_class("small_error_text");
let partition_method_automatic_luks_error_label = gtk::Label::builder()
.label(gettext("luks_yes_but_empty"))
.halign(Align::Start)
.valign(Align::End)
.vexpand(true)
.visible(false)
.build();
partition_method_automatic_luks_error_label.add_css_class("small_error_text");
let partition_method_automatic_luks_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.build();
let partition_method_automatic_luks_checkbutton = gtk::CheckButton::builder()
.label(gettext("enable_luks2_enc"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
let partition_method_automatic_luks_listbox = gtk::ListBox::builder()
.margin_top(15)
.margin_bottom(15)
.margin_start(0)
.margin_end(15)
.build();
partition_method_automatic_luks_listbox.add_css_class("boxed-list");
let partition_method_automatic_luks_password_entry = adw::PasswordEntryRow::builder()
.title(gettext("luks2_password"))
.hexpand(true)
.sensitive(false)
.build();
let partition_method_automatic_target_buffer = gtk::TextBuffer::builder().build();
let partition_method_automatic_luks_buffer = gtk::TextBuffer::builder().build();
for device in partition_method_automatic_get_devices_reader.lines() {
let device = device.unwrap();
let device_size_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_block_size")
.arg(device.clone())
.output()
.expect("failed to execute process");
let device_size = String::from_utf8(device_size_cli.stdout)
.expect("Failed to create float")
.trim()
.parse::<f64>()
.unwrap();
let device_button = gtk::CheckButton::builder()
.valign(Align::Center)
.can_focus(false)
.build();
device_button.set_group(Some(&null_checkbutton));
let device_row = adw::ActionRow::builder()
.activatable_widget(&device_button)
.title(device.clone())
.subtitle(pretty_bytes::converter::convert(device_size))
.build();
device_row.add_prefix(&device_button);
devices_selection_expander_row_viewport_box.append(&device_row);
device_button.connect_toggled(clone!(@weak device_button,@weak partition_method_automatic_luks_password_entry, @weak devices_selection_expander_row, @weak bottom_next_button, @weak partition_method_automatic_disk_error_label, @weak partition_method_automatic_luks_error_label, @weak partition_method_automatic_luks_checkbutton, @weak partition_method_automatic_target_buffer, @weak partition_method_automatic_luks_buffer => move |_| {
if device_button.is_active() == true {
devices_selection_expander_row.set_title(&device);
if device_size > 39000000000.0 {
partition_method_automatic_disk_error_label.set_visible(false);
if partition_method_automatic_luks_checkbutton.is_active() == true {
if partition_method_automatic_luks_error_label.get_visible() {
//
} else {
bottom_next_button.set_sensitive(true);
}
} else {
partition_method_automatic_target_buffer.set_text(&device);
partition_method_automatic_luks_buffer.set_text(&partition_method_automatic_luks_password_entry.text().to_string());
bottom_next_button.set_sensitive(true);
}
} else {
partition_method_automatic_disk_error_label.set_visible(true);
partition_method_automatic_disk_error_label.set_label(&gettext("disk_auto_target_small"));
bottom_next_button.set_sensitive(false);
}
}
}));
}
partition_method_automatic_luks_checkbutton.connect_toggled(clone!(@weak partition_method_automatic_luks_checkbutton, @weak partition_method_automatic_luks_password_entry, @weak partition_method_automatic_disk_error_label, @weak partition_method_automatic_luks_error_label, @weak bottom_next_button, @weak partition_method_automatic_target_buffer, @weak partition_method_automatic_luks_buffer => move |_| {
if partition_method_automatic_luks_checkbutton.is_active() == true {
partition_method_automatic_luks_password_entry.set_sensitive(true);
if partition_method_automatic_luks_password_entry.text().to_string().is_empty() {
partition_method_automatic_luks_error_label.set_visible(true);
bottom_next_button.set_sensitive(false);
} else {
partition_method_automatic_luks_error_label.set_visible(false);
if partition_method_automatic_disk_error_label.get_visible() {
//
} else {
bottom_next_button.set_sensitive(true);
}
}
} else {
partition_method_automatic_luks_password_entry.set_sensitive(false);
partition_method_automatic_luks_error_label.set_visible(false);
if partition_method_automatic_disk_error_label.get_visible() {
//
} else {
bottom_next_button.set_sensitive(true);
}
}
}));
partition_method_automatic_luks_password_entry.connect_changed(clone!(@weak partition_method_automatic_luks_checkbutton, @weak partition_method_automatic_luks_password_entry, @weak partition_method_automatic_disk_error_label, @weak partition_method_automatic_luks_error_label, @weak bottom_next_button, @weak partition_method_automatic_luks_buffer => move |_| {
if partition_method_automatic_luks_checkbutton.is_active() == true {
partition_method_automatic_luks_password_entry.set_sensitive(true);
if partition_method_automatic_luks_password_entry.text().to_string().is_empty() {
partition_method_automatic_luks_error_label.set_visible(true);
bottom_next_button.set_sensitive(false);
} else {
partition_method_automatic_luks_error_label.set_visible(false);
if partition_method_automatic_disk_error_label.get_visible() {
//
} else {
partition_method_automatic_luks_buffer.set_text(&partition_method_automatic_luks_password_entry.text().to_string());
bottom_next_button.set_sensitive(true);
}
}
} else {
partition_method_automatic_luks_password_entry.set_sensitive(false);
partition_method_automatic_luks_error_label.set_visible(false);
if partition_method_automatic_disk_error_label.get_visible() {
//
} else {
partition_method_automatic_luks_buffer.set_text(&partition_method_automatic_luks_password_entry.text().to_string());
bottom_next_button.set_sensitive(true);
}
}
}));
partition_method_automatic_luks_listbox.append(&partition_method_automatic_luks_password_entry);
partition_method_automatic_luks_box.append(&partition_method_automatic_luks_checkbutton);
partition_method_automatic_luks_box.append(&partition_method_automatic_luks_listbox);
partition_method_automatic_header_box.append(&partition_method_automatic_header_text);
partition_method_automatic_header_box.append(&partition_method_automatic_header_icon);
partition_method_automatic_selection_box.append(&partition_method_automatic_selection_text);
partition_method_automatic_main_box.append(&partition_method_automatic_header_box);
partition_method_automatic_main_box.append(&partition_method_automatic_selection_box);
partition_method_automatic_main_box.append(&devices_selection_expander_row_viewport_listbox);
partition_method_automatic_main_box.append(&partition_method_automatic_luks_box);
partition_method_automatic_main_box.append(&partition_method_automatic_luks_error_label);
partition_method_automatic_main_box.append(&partition_method_automatic_disk_error_label);
partitioning_stack.add_titled(
&partition_method_automatic_main_box,
Some("partition_method_automatic_page"),
"partition_method_automatic_page",
);
return (
partition_method_automatic_target_buffer,
partition_method_automatic_luks_buffer,
);
}

View File

@ -1,53 +1,53 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
use crate::save_window_size;
use crate::welcome_page;
use crate::efi_error_page;
use crate::language_page;
use crate::eula_page;
use crate::timezone_page;
use crate::keyboard_page;
use crate::partitioning_page;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
use std::path::Path;
use crate::save_window_size::save_window_size;
use crate::welcome_page::welcome_page;
use crate::efi_error_page::efi_error_page;
use crate::language_page::language_page;
use crate::eula_page::eula_page;
use crate::timezone_page::timezone_page;
use crate::keyboard_page::keyboard_page;
use crate::partitioning_page::partitioning_page;
// build ui function linked to app startup above
pub fn build_ui(app: &adw::Application) {
// setup glib
gtk::glib::set_prgname(Some("PikaOS Installer"));
glib::set_application_name("PikaOS Installer");
gtk::glib::set_prgname(Some(gettext("pikaos_installer")));
glib::set_application_name(&gettext("pikaos_installer"));
let glib_settings = gio::Settings::new("com.github.pikaos-linux.pikainstallergtk4");
// Widget Bank
/// Create A box
let _main_box = gtk::Box::builder()
// that puts items vertically
.orientation(Orientation::Vertical)
.build();
/// Add adwaita title box
let window_title_bar = adw::HeaderBar::builder()
.build();
let window_title_bar = adw::HeaderBar::builder().build();
/// Add page Stack containing all primary contents
let content_stack = gtk::Stack::builder()
.hexpand(true)
.vexpand(true)
.transition_type(StackTransitionType::SlideLeftRight)
.build();
/// Add a Visual Stack Switcher for content_stack
let content_stack_switcher = gtk::StackSwitcher::builder()
.stack(&content_stack)
.margin_top(15)
@ -64,19 +64,16 @@ pub fn build_ui(app: &adw::Application) {
_main_box.append(&content_stack_switcher);
//// Add the stack pager containing all the steps to _main_box
_main_box.append(&content_stack);
//// Add the the next and back buttons box to _main_box (moved)
///_main_box.append(&bottom_box);
// create the main Application window
let window = adw::ApplicationWindow::builder()
// The text on the titlebar
.title("PikaOS Installer")
.title(gettext("pikaos_installer"))
// link it to the application "app"
.application(app)
// Add the box called "_main_box" to it
.content(&_main_box)
// Application icon
.icon_name("nautilus")
.icon_name("calamares")
// Get current size from glib
.default_width(glib_settings.int("window-width"))
.default_height(glib_settings.int("window-height"))
@ -85,6 +82,8 @@ pub fn build_ui(app: &adw::Application) {
.height_request(500)
// Hide window instead of destroy
.hide_on_close(true)
//
.deletable(false)
// Startup
.startup_id("pika-installer-gtk4")
// build the window
@ -129,21 +128,16 @@ pub fn build_ui(app: &adw::Application) {
partitioning_page(&done_main_box, &install_main_box, &content_stack, &window);
//// Add the install_main_box as page: install_page, Give it nice title
content_stack.add_titled(&install_main_box, Some("install_page"), "Installation");
content_stack.add_titled(&install_main_box, Some("install_page"), &gettext("installation"));
// Add done_page.rs as a page for content_stack
content_stack.add_titled(&done_main_box, Some("done_page"), "Done");
content_stack.add_titled(&done_main_box, Some("done_page"), &gettext("done"));
// glib maximization
if glib_settings.boolean("is-maximized") == true {
window.maximize()
}
// Connects the clicking of "_click_me_button" to the external function "print_why" and idk why but everyone tells me to be "move |_| " before the external function
/// and instead of () we put an aurgment for the target label with & before it so it's"
/// print_why() -> print_why(&_warning_label)
//_click_me_button.connect_clicked(move |_| print_why(&_warning_label));
// Connect the hiding of window to the save_window_size function and window destruction
window.connect_hide(clone!(@weak window => move |_| save_window_size(&window, &glib_settings)));
window.connect_hide(clone!(@weak window => move |_| window.destroy()));

7
src/config.rs Normal file
View File

@ -0,0 +1,7 @@
pub const APP_ID: &str = "com.github.pikaos-linux.pikainstallergtk4";
pub const GETTEXT_PACKAGE: &str = env!("CARGO_PKG_NAME");
pub const LOCALEDIR: &str = "/usr/share/locale";
//pub const PKGDATADIR: &str = " /usr/share";
//pub const RESOURCES_FILE: &str = concat!(@PKGDATADIR@, "/resources.gresource");
//pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const DISTRO_ICON: &str = "pika-logo";

View File

@ -1,19 +1,21 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use crate::config::{DISTRO_ICON};
use gettextrs::{gettext};
use std::fs;
use std::path::Path;
use std::process::Command;
pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &adw::ApplicationWindow) {
pub fn done_page(
done_main_box: &gtk::Box,
window: &adw::ApplicationWindow,
) {
// the header box for the installation_successful page
let done_header_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
@ -33,7 +35,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
// the header icon for the installation_successful icon
let done_header_icon = gtk::Image::builder()
.icon_name("debian-swirl")
.icon_name(DISTRO_ICON)
.halign(gtk::Align::Start)
.hexpand(true)
.pixel_size(78)
@ -43,7 +45,6 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.margin_end(15)
.build();
// Successful install yard
// the header box for the installation_successful page
let installation_successful_main_box = gtk::Box::builder()
@ -71,7 +72,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.build();
let installation_successful_text = gtk::Label::builder()
.label("The installation of PikaOS has been completed sucessfully.")
.label(gettext("pika_install_good"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.build();
@ -88,7 +89,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.build();
let installation_successful_exit_button = gtk::Button::builder()
.label("Exit")
.label(gettext("exit"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.margin_start(5)
@ -96,7 +97,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.build();
let installation_successful_reboot_button = gtk::Button::builder()
.label("Reboot")
.label(gettext("reboot"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.margin_start(5)
@ -126,7 +127,8 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
//// Add the installation_successful selection/page content box to installation_successful main box
installation_successful_main_box.append(&installation_successful_selection_box);
installation_successful_exit_button.connect_clicked(clone!(@weak window => move |_| window.close()));
installation_successful_exit_button
.connect_clicked(clone!(@weak window => move |_| window.close()));
installation_successful_reboot_button.connect_clicked(move |_| {
Command::new("reboot")
.spawn()
@ -160,7 +162,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.build();
let installation_failed_text = gtk::Label::builder()
.label("PikaOS has Failed!\nCheck logs for further info.")
.label(gettext("pika_install_bad"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.build();
@ -177,7 +179,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.build();
let installation_failed_exit_button = gtk::Button::builder()
.label("Exit")
.label(gettext("exit"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.margin_start(5)
@ -185,7 +187,7 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
.build();
let installation_failed_logs_button = gtk::Button::builder()
.label("Logs")
.label(gettext("logs"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.margin_start(5)
@ -215,7 +217,8 @@ pub fn done_page(done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &
//// Add the installation_failed selection/page content box to installation_failed main box
installation_failed_main_box.append(&installation_failed_selection_box);
installation_failed_exit_button.connect_clicked(clone!(@weak window => move |_| window.close()));
installation_failed_exit_button
.connect_clicked(clone!(@weak window => move |_| window.close()));
installation_failed_logs_button.connect_clicked(move |_| {
Command::new("xdg-open")
.arg("/tmp/pika-installer-gtk4-log")

187
src/drive_mount_row/imp.rs Normal file
View File

@ -0,0 +1,187 @@
use std::{
cell::{RefCell},
rc::Rc,
sync::OnceLock,
};
use adw::{prelude::*, subclass::prelude::*, *};
use glib::{clone, subclass::Signal, Properties};
use gtk::{glib, Orientation::Horizontal};
use gettextrs::{gettext};
// ANCHOR: custom_button
// Object holding the state
#[derive(Properties, Default)]
#[properties(wrapper_type = super::DriveMountRow)]
pub struct DriveMountRow {
#[property(get, set)]
mountopt: RefCell<String>,
#[property(get, set)]
partition: RefCell<String>,
#[property(get, set)]
mountpoint: RefCell<String>,
#[property(get, set)]
partitionscroll: Rc<RefCell<gtk::ScrolledWindow>>,
}
// ANCHOR_END: custom_button
// The central trait for subclassing a GObject
#[glib::object_subclass]
impl ObjectSubclass for DriveMountRow {
const NAME: &'static str = "DriveMountRow";
type Type = super::DriveMountRow;
type ParentType = adw::ActionRow;
}
// ANCHOR: object_impl
// Trait shared by all GObjects
#[glib::derived_properties]
impl ObjectImpl for DriveMountRow {
fn signals() -> &'static [Signal] {
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
SIGNALS.get_or_init(|| vec![Signal::builder("row-deleted").build()])
}
fn constructed(&self) {
self.parent_constructed();
// Bind label to number
// `SYNC_CREATE` ensures that the label will be immediately set
let obj = self.obj();
let action_row_content_box = gtk::Box::builder()
.orientation(Horizontal)
.spacing(0)
.vexpand(true)
.hexpand(true)
.build();
let partition_row_expander_adw_listbox = gtk::ListBox::builder()
.margin_end(5)
.margin_start(10)
.margin_top(5)
.margin_bottom(5)
.vexpand(true)
.hexpand(true)
.build();
partition_row_expander_adw_listbox.add_css_class("boxed-list");
let partition_row_expander = adw::ExpanderRow::builder()
.subtitle(gettext("subtitle_partition"))
.vexpand(true)
.hexpand(true)
.width_request(300)
.build();
let mountpoint_entry_adw_box = gtk::Box::builder()
.hexpand(true)
.valign(gtk::Align::Start)
.homogeneous(true)
.build();
let mountpoint_entry_adw_listbox = gtk::ListBox::builder()
.margin_top(5)
.margin_bottom(5)
.hexpand(true)
.valign(gtk::Align::Start)
.build();
mountpoint_entry_adw_listbox.add_css_class("boxed-list");
let mountpoint_entry_row = adw::EntryRow::builder()
.title(gettext("title_mountpoint"))
.hexpand(true)
.valign(gtk::Align::Start)
.width_request(300)
.build();
let mountopt_entry_adw_box = gtk::Box::builder()
.hexpand(true)
.valign(gtk::Align::Start)
.homogeneous(true)
.build();
let mountopt_entry_adw_listbox = gtk::ListBox::builder()
.margin_top(5)
.margin_bottom(5)
.margin_start(5)
.hexpand(true)
.valign(gtk::Align::Start)
.build();
mountopt_entry_adw_listbox.add_css_class("boxed-list");
let mountopt_entry_row = adw::EntryRow::builder()
.title(gettext("title_mountopt"))
.hexpand(true)
.valign(gtk::Align::Start)
.width_request(300)
.build();
let partition_row_delete_button = gtk::Button::builder()
.margin_end(0)
.margin_start(5)
.margin_top(5)
.margin_bottom(5)
.width_request(53)
.height_request(53)
.valign(gtk::Align::Start)
.icon_name("user-trash")
.halign(gtk::Align::End)
.build();
partition_row_delete_button.connect_clicked(clone!( @weak obj => move |_| {
obj.emit_by_name::<()>("row-deleted", &[]);
}));
partition_row_expander_adw_listbox.append(&partition_row_expander);
action_row_content_box.append(&partition_row_expander_adw_listbox);
mountpoint_entry_adw_listbox.append(&mountpoint_entry_row);
mountpoint_entry_adw_box.append(&mountpoint_entry_adw_listbox);
action_row_content_box.append(&mountpoint_entry_adw_box);
mountopt_entry_adw_listbox.append(&mountopt_entry_row);
mountopt_entry_adw_box.append(&mountopt_entry_adw_listbox);
action_row_content_box.append(&mountopt_entry_adw_box);
action_row_content_box.append(&partition_row_delete_button);
obj.add_prefix(&action_row_content_box);
// Bind label to number
// `SYNC_CREATE` ensures that the label will be immediately set
let obj = self.obj();
obj.bind_property("partition", &partition_row_expander, "title")
.sync_create()
.bidirectional()
.build();
obj.bind_property("mountpoint", &mountpoint_entry_row, "text")
.sync_create()
.bidirectional()
.build();
obj.bind_property("mountopt", &mountopt_entry_row, "text")
.sync_create()
.bidirectional()
.build();
obj.connect_partitionscroll_notify(clone!(@weak obj => move |_| {
partition_row_expander.add_row(&obj.property::<gtk::ScrolledWindow>("partitionscroll"));
}));
}
}
// Trait shared by all widgets
impl WidgetImpl for DriveMountRow {}
// Trait shared by all buttons
// Trait shared by all buttons
impl ListBoxRowImpl for DriveMountRow {}
impl PreferencesRowImpl for DriveMountRow {}
impl ActionRowImpl for DriveMountRow {
//fn clicked(&self) {
// let incremented_number = self.obj().number() + 1;
// self.obj().set_number(incremented_number);
//}
}

View File

@ -0,0 +1,28 @@
mod imp;
use glib::Object;
use gtk::glib;
glib::wrapper! {
pub struct DriveMountRow(ObjectSubclass<imp::DriveMountRow>)
@extends adw::ActionRow, gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow,
@implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
impl DriveMountRow {
pub fn new() -> Self {
Object::builder().build()
}
pub fn new_with_scroll(partitions_scroll: &gtk::ScrolledWindow) -> Self {
Object::builder()
.property("partitionscroll", partitions_scroll)
.build()
}
}
// ANCHOR_END: mod
impl Default for DriveMountRow {
fn default() -> Self {
Self::new()
}
}

View File

@ -1,13 +1,12 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
pub fn efi_error_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack) {
// the header box for the efi_error page
@ -22,7 +21,7 @@ pub fn efi_error_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stac
// the header text for the efi_error page
let efi_error_header_text = gtk::Label::builder()
.label("Unsupported boot platform")
.label(gettext("bad_boot_platfrom"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
@ -53,18 +52,17 @@ pub fn efi_error_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stac
.margin_end(15)
.build();
let efi_error_text = gtk::Label::builder()
.vexpand(true)
.hexpand(true)
.label("PikaOS Only works on GPT UEFI Systems, this machine is booted in CSM/LEGACY mode.")
.label(gettext("pika_nowork_csm"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.build();
efi_error_text.add_css_class("big_error_text");
let kill_me_button = gtk::Button::builder()
.label("Exit")
let exit_button = gtk::Button::builder()
.label(gettext("exit"))
.vexpand(true)
.hexpand(true)
.halign(gtk::Align::Center)
@ -89,7 +87,7 @@ pub fn efi_error_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stac
// / efi_error_selection_box appends
//// add live and install media button to efi_error page selections
efi_error_selection_box.append(&efi_error_text);
efi_error_selection_box.append(&kill_me_button);
efi_error_selection_box.append(&exit_button);
// / efi_error_header_box appends
//// Add the efi_error page header text and icon
@ -106,5 +104,5 @@ pub fn efi_error_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stac
//// Add the efi_error_main_box as page: efi_error_page, Give it nice title
content_stack.add_titled(&efi_error_main_box, Some("efi_error_page"), "Welcome");
kill_me_button.connect_clicked(clone!(@weak window => move |_| window.close()));
exit_button.connect_clicked(clone!(@weak window => move |_| window.close()));
}

View File

@ -1,22 +1,14 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use std::io::BufRead;
use std::io::BufReader;
use std::process::Command;
use std::process::Stdio;
use std::time::Instant;
use gettextrs::{gettext};
pub fn eula_page(content_stack: &gtk::Stack) {
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
@ -26,7 +18,7 @@ pub fn eula_page(content_stack: &gtk::Stack) {
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label("Back")
.label(gettext("back"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -35,7 +27,7 @@ pub fn eula_page(content_stack: &gtk::Stack) {
.hexpand(true)
.build();
let bottom_next_button = gtk::Button::builder()
.label("Next")
.label(gettext("next"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -65,7 +57,7 @@ pub fn eula_page(content_stack: &gtk::Stack) {
// the header text for the eula page
let eula_header_text = gtk::Label::builder()
.label("PikaOS User license Agreement")
.label(gettext("pikaos_eula_agreement"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
@ -105,7 +97,7 @@ pub fn eula_page(content_stack: &gtk::Stack) {
// text above eula selection box
let eula_selection_text = gtk::Label::builder()
.label("Please carefully read and make sure you consent to the following before installing PikaOS:")
.label(gettext("please_read_eula"))
.halign(gtk::Align::Center)
.hexpand(true)
.margin_top(15)
@ -116,7 +108,7 @@ pub fn eula_page(content_stack: &gtk::Stack) {
eula_selection_text.add_css_class("medium_sized_text");
let eula_buffer = gtk::TextBuffer::builder()
.text("WE OWN YOU\nWE OWN YOUR SOUL\nWE OWN YOUR WIFE\nWE OWN YOUR FIRST BORN\nWE OWN YOUR HOUSE\nWE OWN YOUR FOOD\nWE OWN YOUR CAR\nWE WILL TRACK YOU\nWE WILL FIND YOU\nTHEN WE WILL KILL YOU")
.text(gettext("eula_buffer"))
.build();
let eula_selection_text_view = gtk::TextView::builder()
@ -130,8 +122,13 @@ pub fn eula_page(content_stack: &gtk::Stack) {
.buffer(&eula_buffer)
.build();
let eula_selection_text_scroll = gtk::ScrolledWindow::builder()
.height_request(350)
.child(&eula_selection_text_view)
.build();
let eula_accept_checkbutton = gtk::CheckButton::builder()
.label("I Agree and Accept the User license Agreement")
.label(gettext("i_agree_eula"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -141,7 +138,7 @@ pub fn eula_page(content_stack: &gtk::Stack) {
// / eula_selection_box appends
//// add text and and entry to eula page selections
eula_selection_box.append(&eula_selection_text);
eula_selection_box.append(&eula_selection_text_view);
eula_selection_box.append(&eula_selection_text_scroll);
eula_selection_box.append(&eula_accept_checkbutton);
// / eula_header_box appends
@ -159,15 +156,17 @@ pub fn eula_page(content_stack: &gtk::Stack) {
// / Content stack appends
//// Add the eula_main_box as page: eula_page, Give it nice title
content_stack.add_titled(&eula_main_box, Some("eula_page"), "EULA");
content_stack.add_titled(&eula_main_box, Some("eula_page"), &gettext("eula"));
eula_accept_checkbutton.connect_toggled(clone!(@weak eula_accept_checkbutton, @weak bottom_next_button => move |_| {
eula_accept_checkbutton.connect_toggled(
clone!(@weak eula_accept_checkbutton, @weak bottom_next_button => move |_| {
if eula_accept_checkbutton.is_active() == true {
bottom_next_button.set_sensitive(true);
} else {
bottom_next_button.set_sensitive(false)
}
}));
}),
);
bottom_next_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("timezone_page")
@ -175,5 +174,4 @@ pub fn eula_page(content_stack: &gtk::Stack) {
bottom_back_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("language_page")
}));
}

View File

@ -1,531 +0,0 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
use vte::prelude::*;
use vte::*;
use std::fs;
use std::path::Path;
use crate::done_page;
pub fn install_page(done_main_box: &gtk::Box, install_main_box: &gtk::Box ,content_stack: &gtk::Stack, window: &adw::ApplicationWindow) {
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.valign(gtk::Align::End)
.vexpand(true)
.build();
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label("Back")
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.halign(gtk::Align::Start)
.hexpand(true)
.build();
// / bottom_box appends
//// Add the next and back buttons
bottom_box.append(&bottom_back_button);
let install_nested_stack = gtk::Stack::builder()
.transition_type(StackTransitionType::SlideLeftRight)
.build();
let install_confirm_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
// the header box for the install page
let install_confirm_header_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.build();
// the header text for the install page
let install_confirm_header_text = gtk::Label::builder()
.label("Sit back, Relax, and watch the show.")
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(5)
.build();
install_confirm_header_text.add_css_class("header_sized_text");
// the header icon for the install icon
let install_confirm_header_icon = gtk::Spinner::builder()
.halign(gtk::Align::Start)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(0)
.margin_end(15)
.build();
install_confirm_header_icon.start();
// make install selection box for choosing installation or live media
let install_confirm_selection_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.halign(gtk::Align::Fill)
.valign(gtk::Align::Center)
.vexpand(true)
.hexpand(true)
.build();
let install_confirm_details_boxed_list = gtk::ListBox::builder()
.margin_top(15)
.margin_bottom(15)
.margin_start(256)
.margin_end(256)
.halign(gtk::Align::Fill)
.valign(gtk::Align::Center)
.hexpand(true)
.build();
install_confirm_details_boxed_list.add_css_class("boxed-list");
let install_confirm_detail_language = adw::ActionRow::builder()
.title("Language:")
.subtitle(fs::read_to_string("/tmp/pika-installer-gtk4-lang.txt").expect("Unable to read file"))
.build();
install_confirm_detail_language.add_css_class("property");
let install_confirm_detail_timezone = adw::ActionRow::builder()
.title("Time zone:")
.subtitle(fs::read_to_string("/tmp/pika-installer-gtk4-timezone.txt").expect("Unable to read file"))
.build();
install_confirm_detail_timezone.add_css_class("property");
let install_confirm_detail_keyboard = adw::ActionRow::builder()
.title("Keyboard layout:")
.subtitle(fs::read_to_string("/tmp/pika-installer-gtk4-keyboard.txt").expect("Unable to read file"))
.build();
install_confirm_detail_keyboard.add_css_class("property");
let install_confirm_detail_target = adw::ActionRow::builder()
.title("Install Target:")
.build();
if Path::new("/tmp/pika-installer-gtk4-target-manual.txt").exists() {
install_confirm_detail_target.set_subtitle(&fs::read_to_string("/tmp/pika-installer-gtk4-target-manual.txt").expect("Unable to read file"));
} else {
install_confirm_detail_target.set_subtitle(&fs::read_to_string("/tmp/pika-installer-gtk4-target-auto.txt").expect("Unable to read file"));
}
install_confirm_detail_target.add_css_class("property");
let install_confirm_button = gtk::Button::builder()
.label("Confirm & Install PikaOS")
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.build();
install_confirm_button.add_css_class("destructive-action");
// / install_confirm_header_box appends
//// Add the install page header text and icon
install_confirm_header_box.append(&install_confirm_header_text);
install_confirm_header_box.append(&install_confirm_header_icon);
// / install_confirm_box appends
//// Add the install header to install main box
install_confirm_box.append(&install_confirm_header_box);
//// Add the install selection/page content box to install main box
install_confirm_box.append(&install_confirm_selection_box);
// Start Appending widgets to boxes
// / install_confirm_selection_box appends
//// add live and install media button to install page selections
install_confirm_details_boxed_list.append(&install_confirm_detail_language);
install_confirm_details_boxed_list.append(&install_confirm_detail_timezone);
install_confirm_details_boxed_list.append(&install_confirm_detail_keyboard);
install_confirm_details_boxed_list.append(&install_confirm_detail_target);
//
install_confirm_selection_box.append(&install_confirm_details_boxed_list);
install_confirm_selection_box.append(&install_confirm_button);
// / install_confirm_header_box appends
//// Add the install page header text and icon
install_confirm_header_box.append(&install_confirm_header_text);
install_confirm_header_box.append(&install_confirm_header_icon);
// / install_confirm_box appends
//// Add the install header to install main box
install_confirm_box.append(&install_confirm_header_box);
//// Add the install selection/page content box to install main box
install_confirm_box.append(&install_confirm_selection_box);
install_main_box.append(&install_nested_stack);
install_confirm_box.append(&bottom_box);
///
let install_progress_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
let install_progress_log_stack = gtk::Stack::builder()
.transition_type(StackTransitionType::SlideUpDown)
.build();
let install_progress_log_terminal = vte::Terminal::builder()
.vexpand(true)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.input_enabled(false)
.build();
let placeholder_icon = gtk::Image::builder()
.icon_name("debian-swirl")
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.hexpand(true)
.vexpand(true)
.pixel_size(512)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
let progress_bar_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.margin_start(15)
.margin_end(15)
.build();
let install_progress_bar = gtk::ProgressBar::builder()
.hexpand(true)
.margin_start(15)
.margin_end(15)
.margin_top(15)
.margin_bottom(15)
.show_text(true)
.build();
let progress_log_button_content = adw::ButtonContent::builder()
.label("View Logs")
.icon_name("terminal")
.build();
let progress_log_button = gtk::Button::builder()
.child(&progress_log_button_content)
.margin_start(15)
.margin_end(15)
.margin_top(15)
.margin_bottom(15)
.build();
progress_bar_box.append(&install_progress_bar);
progress_bar_box.append(&progress_log_button);
install_progress_log_stack.add_titled(&placeholder_icon, Some("slideshow_page"), "slideshow_page");
install_progress_log_stack.add_titled(&install_progress_log_terminal, Some("terminal_log_page"), "terminal_log_page");
install_progress_box.append(&install_progress_log_stack);
install_progress_box.append(&progress_bar_box);
install_nested_stack.add_titled(&install_confirm_box, Some("confirm_page"), "confirm_page");
install_nested_stack.add_titled(&install_progress_box, Some("progress_page"), "progress_page");
//
//
install_confirm_button.connect_clicked(clone!(@weak install_nested_stack, @weak install_progress_log_terminal, @weak install_progress_bar, @weak done_main_box, @weak content_stack, @weak window => move |_| {
install_nested_stack.set_visible_child_name("progress_page");
begin_install(&install_progress_log_terminal, &install_progress_bar, &done_main_box, &content_stack, &window);
}));
progress_log_button.connect_clicked(clone!(@weak install_progress_log_stack => move |_| {
if install_progress_log_stack.visible_child_name() == Some(GString::from_string_unchecked("slideshow_page".into())) {
install_progress_log_stack.set_visible_child_name("terminal_log_page");
} else {
install_progress_log_stack.set_visible_child_name("slideshow_page");
}
}));
bottom_back_button.connect_clicked(clone!(@weak content_stack, @weak install_main_box, @weak install_nested_stack => move |_| {
content_stack.set_visible_child_name("partitioning_page");
install_main_box.remove(&install_nested_stack)
}));
}
fn begin_install(install_progress_log_terminal: &vte::Terminal, install_progress_bar: &gtk::ProgressBar, done_main_box: &gtk::Box, content_stack: &gtk::Stack, window: &adw::ApplicationWindow) {
// SPAWN TERMINAL WITH PIKAINSTALL PROCESS
install_progress_log_terminal.spawn_async(
PtyFlags::DEFAULT,
Some(""),
&["/usr/lib/pika/pika-installer-gtk4/scripts/begin-install.sh"],
&[],
SpawnFlags::DEFAULT,
|| {},
-1,
None::<&gio::Cancellable>,
move |result| {
match result {
Ok(_) => { eprintln!("could not spawn terminal")}
Err(err) => {
eprintln!("could not spawn terminal: {}", err);
}
}
},
);
// wait till /tmp/pika-installer-gtk4-status-parting.txt to change progressbar
let (parting_status_sender, parting_status_receiver) = async_channel::unbounded();
let parting_status_sender = parting_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let parting_status = true;
while parting_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-parting.txt").exists() == true {
parting_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let parting_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
parting_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(parting_status_state) = parting_status_receiver.recv().await {
if parting_status_state == true {
println!("Installation status: Parting");
install_progress_bar.set_fraction(0.20);
install_progress_bar.set_text(Some("Partitioning The Disk Target."));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-image.txt to change progressbar
let (image_status_sender, image_status_receiver) = async_channel::unbounded();
let image_status_sender = image_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let image_status = true;
while image_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-image.txt").exists() == true {
image_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let image_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
image_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(image_status_state) = image_status_receiver.recv().await {
if image_status_state == true {
println!("Installation status: Imaging");
install_progress_bar.set_fraction(0.60);
install_progress_bar.set_text(Some("Writing image to target."));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-flag1.txt to change progressbar
let (flag1_status_sender, flag1_status_receiver) = async_channel::unbounded();
let flag1_status_sender = flag1_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let flag1_status = true;
while flag1_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-flag1.txt").exists() == true {
flag1_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let flag1_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
flag1_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(flag1_status_state) = flag1_status_receiver.recv().await {
if flag1_status_state == true {
println!("Installation status: Flag1");
install_progress_bar.set_fraction(0.65);
install_progress_bar.set_text(Some("Enabling bls_boot flag on /boot"));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-flag2.txt to change progressbar
let (flag2_status_sender, flag2_status_receiver) = async_channel::unbounded();
let flag2_status_sender = flag2_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let flag2_status = true;
while flag2_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-flag2.txt").exists() == true {
flag2_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let flag2_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
flag2_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(flag2_status_state) = flag2_status_receiver.recv().await {
if flag2_status_state == true {
println!("Installation status: Flag2");
install_progress_bar.set_fraction(0.70);
install_progress_bar.set_text(Some("Enabling efi flag on /boot/efi"));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-crypt.txt to change progressbar
let (crypt_status_sender, crypt_status_receiver) = async_channel::unbounded();
let crypt_status_sender = crypt_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let crypt_status = true;
while crypt_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-crypt.txt").exists() == true {
crypt_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let crypt_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
crypt_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(crypt_status_state) = crypt_status_receiver.recv().await {
if crypt_status_state == true {
println!("Installation status: Crypttab");
install_progress_bar.set_fraction(0.75);
install_progress_bar.set_text(Some("Setting up encryption crypttab"));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-lang.txt to change progressbar
let (lang_status_sender, lang_status_receiver) = async_channel::unbounded();
let lang_status_sender = lang_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let lang_status = true;
while lang_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-lang.txt").exists() == true {
lang_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let lang_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
lang_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(lang_status_state) = lang_status_receiver.recv().await {
if lang_status_state == true {
println!("Installation status: Language");
install_progress_bar.set_fraction(0.80);
install_progress_bar.set_text(Some("Setting Up Language and Keyboard."));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-boot.txt to change progressbar
let (boot_status_sender, boot_status_receiver) = async_channel::unbounded();
let boot_status_sender = boot_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let boot_status = true;
while boot_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-boot.txt").exists() == true {
boot_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let boot_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
boot_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(boot_status_state) = boot_status_receiver.recv().await {
if boot_status_state == true {
println!("Installation status: Bootloader");
install_progress_bar.set_fraction(0.85);
install_progress_bar.set_text(Some("Configuring bootloader"));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-post.txt to change progressbar
let (post_status_sender, post_status_receiver) = async_channel::unbounded();
let post_status_sender = post_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let post_status = true;
while post_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-post.txt").exists() == true {
post_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let post_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
post_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(post_status_state) = post_status_receiver.recv().await {
if post_status_state == true {
println!("Installation status: Post Install");
install_progress_bar.set_fraction(0.90);
install_progress_bar.set_text(Some("Running post installation script."));
}
}
}));
// wait till /tmp/pika-installer-gtk4-successful.txt to change progressbar
let (done_status_sender, done_status_receiver) = async_channel::unbounded();
let done_status_sender = done_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let done_status = true;
while done_status == true {
if Path::new("/tmp/pika-installer-gtk4-successful.txt").exists() == true || Path::new("/tmp/pika-installer-gtk4-fail.txt").exists() == true {
done_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break
}
}
});
let done_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
done_status_main_context.spawn_local(clone!(@weak done_main_box, @weak content_stack, @weak window => async move {
while let Ok(done_status_state) = done_status_receiver.recv().await {
if done_status_state == true {
println!("Installation status: Done");
done_page(&done_main_box ,&content_stack, &window);
content_stack.set_visible_child_name("done_page");
}
}
}));
}

790
src/install_page/mod.rs Normal file
View File

@ -0,0 +1,790 @@
use crate::config::DISTRO_ICON;
use std::cell::RefCell;
// Use libraries
use adw::prelude::*;
use adw::*;
use glib::*;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use vte::prelude::*;
use vte::*;
use gettextrs::{gettext};
use crate::done_page::done_page;
use std::process::Command;
use std::fs;
use std::path::Path;
use std::rc::Rc;
use crate::manual_partitioning::DriveMount;
use serde::*;
use duct::*;
#[derive(PartialEq, Debug, Eq, Hash, Clone, Serialize, Deserialize)]
struct CrypttabEntry {
partition: String,
password: String,
}
pub fn install_page(
done_main_box: &gtk::Box,
install_main_box: &gtk::Box,
content_stack: &gtk::Stack,
window: &adw::ApplicationWindow,
manual_drive_mount_array: &Rc<RefCell<Vec<DriveMount>>>,
) {
let mut _iter_count = 0;
_iter_count = 0;
let mut unlocked_array: Vec<String> = Default::default();
manual_drive_mount_array.borrow_mut().sort_by_key(|p| p.clone().mountpoint);
for partitions in manual_drive_mount_array.borrow_mut().iter() {
let new_crypt = if partitions.mountpoint != "/"
&& !unlocked_array.contains(&partitions.partition)
&& Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("has_encryption")
.arg(&partitions.partition)
.output()
.expect("failed to execute process")
.status
.success()
{
let crypttab_password_listbox = gtk::ListBox::builder()
.margin_top(10)
.margin_bottom(10)
.margin_start(10)
.margin_end(10)
.build();
crypttab_password_listbox.add_css_class("boxed-list");
let crypttab_password = adw::PasswordEntryRow::builder()
.title(gettext("luks_password_for") + &partitions.partition)
.build();
crypttab_password.set_show_apply_button(true);
crypttab_password_listbox.append(&crypttab_password);
let crypttab_dialog = adw::MessageDialog::builder()
.transient_for(window)
.hide_on_close(true)
.extra_child(&crypttab_password_listbox)
.width_request(400)
.height_request(200)
.heading(
gettext("luks_how_should")
+ &partitions.partition
+ &gettext("be_added_crypttab"),
)
.build();
crypttab_dialog.add_response("crypttab_dialog_boot", &gettext("unlock_boot_manually"));
crypttab_dialog
.add_response("crypttab_dialog_auto", &gettext("unlock_boot_manual"));
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", false);
crypttab_password.connect_apply(clone!(@weak crypttab_password, @strong partitions, @weak crypttab_dialog => move |_| {
let (luks_manual_password_sender, luks_manual_password_receiver) = async_channel::unbounded();
let luks_manual_password_sender = luks_manual_password_sender.clone();
let luks_password = crypttab_password.text().to_string();
gio::spawn_blocking(clone!(@strong crypttab_password, @strong partitions => move || {
let result = cmd!("sudo", "/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh", "test_luks_passwd", &partitions.partition, luks_password).run();
if result.is_ok() {
luks_manual_password_sender
.send_blocking(false)
.expect("The channel needs to be open.");
} else {
luks_manual_password_sender
.send_blocking(true)
.expect("The channel needs to be open.");
}
}));
let luks_manual_password_main_context = MainContext::default();
// The main loop executes the asynchronous block
luks_manual_password_main_context.spawn_local(clone!(@weak crypttab_dialog => async move {
while let Ok(state) = luks_manual_password_receiver.recv().await {
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", !state);
}
}));
}));
let partition_final = partitions.partition.clone();
let partition_final2 = partitions.partition.clone();
crypttab_dialog.choose(None::<&gio::Cancellable>, move |choice| {
if choice == "crypttab_dialog_auto" {
let crypttab_entry = CrypttabEntry {
partition: partition_final2,
password: (&crypttab_password.text()).to_string(),
};
fs::write(
"/tmp/pika-installer-gtk4-target-manual-luks-p".to_owned()
+ &_iter_count.to_string()
+ ".json",
serde_json::to_string(&crypttab_entry).unwrap(),
)
.expect("Unable to write file");
} else {
let crypttab_entry = CrypttabEntry {
partition: partition_final2,
password: (&"").to_string(),
};
fs::write(
"/tmp/pika-installer-gtk4-target-manual-luks-p".to_owned()
+ &_iter_count.to_string()
+ ".json",
serde_json::to_string(&crypttab_entry).unwrap(),
)
.expect("Unable to write file");
}
});
partition_final
} else {
String::from("")
};
fs::write(
"/tmp/pika-installer-gtk4-target-manual-p".to_owned()
+ &_iter_count.to_string()
+ ".json",
serde_json::to_string(partitions).unwrap(),
)
.expect("Unable to write file");
if !new_crypt.is_empty() {
unlocked_array.push(new_crypt);
}
dbg!(&unlocked_array);
_iter_count += 1;
}
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.valign(gtk::Align::End)
.vexpand(true)
.build();
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label(gettext("back"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.halign(gtk::Align::Start)
.hexpand(true)
.build();
// / bottom_box appends
//// Add the next and back buttons
bottom_box.append(&bottom_back_button);
let install_nested_stack = gtk::Stack::builder()
.transition_type(StackTransitionType::SlideLeftRight)
.build();
let install_confirm_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
// the header box for the install page
let install_confirm_header_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.build();
// the header text for the install page
let install_confirm_header_text = gtk::Label::builder()
.label(gettext("sit_back_relax"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(5)
.build();
install_confirm_header_text.add_css_class("header_sized_text");
// the header icon for the install icon
let install_confirm_header_icon = gtk::Spinner::builder()
.halign(gtk::Align::Start)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(0)
.margin_end(15)
.build();
install_confirm_header_icon.start();
// make install selection box for choosing installation or live media
let install_confirm_selection_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.halign(gtk::Align::Fill)
.valign(gtk::Align::Center)
.vexpand(true)
.hexpand(true)
.build();
let install_confirm_details_boxed_list = gtk::ListBox::builder()
.margin_top(15)
.margin_bottom(15)
.margin_start(256)
.margin_end(256)
.halign(gtk::Align::Fill)
.valign(gtk::Align::Center)
.hexpand(true)
.build();
install_confirm_details_boxed_list.add_css_class("boxed-list");
let install_confirm_detail_language = adw::ActionRow::builder()
.title(gettext("language_detail"))
.subtitle(
fs::read_to_string("/tmp/pika-installer-gtk4-lang.txt").expect("Unable to read file"),
)
.build();
install_confirm_detail_language.add_css_class("property");
let install_confirm_detail_timezone = adw::ActionRow::builder()
.title(gettext("timezone_detail"))
.subtitle(
fs::read_to_string("/tmp/pika-installer-gtk4-timezone.txt")
.expect("Unable to read file"),
)
.build();
install_confirm_detail_timezone.add_css_class("property");
let install_confirm_detail_keyboard = adw::ActionRow::builder()
.title(gettext("keyboard_detail"))
.subtitle(
fs::read_to_string("/tmp/pika-installer-gtk4-keyboard.txt")
.expect("Unable to read file"),
)
.build();
install_confirm_detail_keyboard.add_css_class("property");
if Path::new("/tmp/pika-installer-gtk4-target-manual.txt").exists() {
//install_confirm_detail_target.set_subtitle(&fs::read_to_string("/tmp/pika-installer-gtk4-target-manual.txt").expect("Unable to read file"));
install_confirm_details_boxed_list.append(&install_confirm_detail_language);
install_confirm_details_boxed_list.append(&install_confirm_detail_timezone);
install_confirm_details_boxed_list.append(&install_confirm_detail_keyboard);
for partitions in manual_drive_mount_array.borrow_mut().iter() {
let confirm_row = adw::ActionRow::builder()
.title(
"/dev/".to_owned()
+ &partitions.partition
+ &gettext("mounted_on_detail")
+ &partitions.mountpoint
)
.build();
install_confirm_details_boxed_list.append(&confirm_row);
}
} else {
let install_confirm_detail_target =
adw::ActionRow::builder().title(gettext("install_target_detail")).build();
install_confirm_detail_target.set_subtitle(
&fs::read_to_string("/tmp/pika-installer-gtk4-target-auto.txt")
.expect("Unable to read file"),
);
install_confirm_detail_target.add_css_class("property");
let target_block_device = &fs::read_to_string("/tmp/pika-installer-gtk4-target-auto.txt")
.expect("Unable to read file");
let target_size_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_block_size")
.arg(target_block_device)
.output()
.expect("failed to execute process");
let target_size = String::from_utf8(target_size_cli.stdout)
.expect("Failed to create float")
.trim()
.parse::<f64>()
.unwrap();
let mut _target_p3_size = 0.0;
if (target_size * 40.0) / 100.0 >= 150000000000.0 {
_target_p3_size = 150000000000.0;
} else if (target_size * 40.0) / 100.0 <= 36507222016.0 {
_target_p3_size = 36507222016.0
} else {
_target_p3_size = (target_size * 40.0) / 100.0;
}
let target_p4_size = target_size - (_target_p3_size + 1536.0);
if Path::new("/tmp/pika-installer-p3-size.txt").exists() {
fs::remove_file("/tmp/pika-installer-p3-size.txt")
.expect("Bad permissions on /tmp/pika-installer-p3-size.txt");
}
let target_p3_sector = _target_p3_size + 1537.0;
fs::write(
"/tmp/pika-installer-p3-size.txt",
target_p3_sector.to_string(),
)
.expect("Unable to write file");
let mut _p1_row_text = String::new();
let mut _p2_row_text = String::new();
let mut _p3_row_text = String::new();
let mut _p4_row_text = String::new();
if target_block_device.contains("nvme") {
_p1_row_text =
"512 MB ".to_owned() + target_block_device + "p1" + " as fat32" + " on /boot/efi";
_p2_row_text =
"1 GB ".to_owned() + target_block_device + "p2" + " as ext4" + " on /boot";
_p3_row_text = pretty_bytes::converter::convert(_target_p3_size)
+ " "
+ target_block_device
+ "p3"
+ " as btrfs"
+ " on /";
_p4_row_text = pretty_bytes::converter::convert(target_p4_size)
+ " "
+ target_block_device
+ "p4"
+ " as btrfs"
+ " on /home";
} else {
_p1_row_text =
"512 MB ".to_owned() + target_block_device + "1" + " as fat32" + " on /boot/efi";
_p2_row_text = "1 GB ".to_owned() + target_block_device + "2" + " as ext4" + " on /boot";
_p3_row_text = pretty_bytes::converter::convert(_target_p3_size)
+ " "
+ target_block_device
+ "3"
+ " as btrfs"
+ " on /";
_p4_row_text = pretty_bytes::converter::convert(target_p4_size)
+ " "
+ target_block_device
+ "4"
+ " as btrfs"
+ " on /home";
}
let install_confirm_p1 = adw::ActionRow::builder().title(_p1_row_text.clone()).build();
let install_confirm_p2 = adw::ActionRow::builder().title(_p2_row_text.clone()).build();
let install_confirm_p3 = adw::ActionRow::builder().title(_p3_row_text.clone()).build();
let install_confirm_p4 = adw::ActionRow::builder().title(_p4_row_text.clone()).build();
// / install_confirm_selection_box appends
//// add live and install media button to install page selections
install_confirm_details_boxed_list.append(&install_confirm_detail_language);
install_confirm_details_boxed_list.append(&install_confirm_detail_timezone);
install_confirm_details_boxed_list.append(&install_confirm_detail_keyboard);
install_confirm_details_boxed_list.append(&install_confirm_detail_target);
install_confirm_details_boxed_list.append(&install_confirm_p1);
install_confirm_details_boxed_list.append(&install_confirm_p2);
install_confirm_details_boxed_list.append(&install_confirm_p3);
install_confirm_details_boxed_list.append(&install_confirm_p4);
}
let install_confirm_button = gtk::Button::builder()
.label(gettext("confirm_install_pika"))
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.build();
install_confirm_button.add_css_class("destructive-action");
// / install_confirm_header_box appends
//// Add the install page header text and icon
install_confirm_header_box.append(&install_confirm_header_text);
install_confirm_header_box.append(&install_confirm_header_icon);
// / install_confirm_box appends
//// Add the install header to install main box
install_confirm_box.append(&install_confirm_header_box);
//// Add the install selection/page content box to install main box
install_confirm_box.append(&install_confirm_selection_box);
// Start Appending widgets to boxes
//
install_confirm_selection_box.append(&install_confirm_details_boxed_list);
install_confirm_selection_box.append(&install_confirm_button);
// / install_confirm_header_box appends
//// Add the install page header text and icon
install_confirm_header_box.append(&install_confirm_header_text);
install_confirm_header_box.append(&install_confirm_header_icon);
// / install_confirm_box appends
//// Add the install header to install main box
install_confirm_box.append(&install_confirm_header_box);
//// Add the install selection/page content box to install main box
install_confirm_box.append(&install_confirm_selection_box);
install_main_box.append(&install_nested_stack);
install_confirm_box.append(&bottom_box);
let install_progress_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
let install_progress_log_stack = gtk::Stack::builder()
.transition_type(StackTransitionType::SlideUpDown)
.build();
let install_progress_log_terminal = vte::Terminal::builder()
.vexpand(true)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.input_enabled(false)
.build();
let placeholder_icon = gtk::Image::builder()
.icon_name(DISTRO_ICON)
.halign(gtk::Align::Center)
.valign(gtk::Align::Center)
.hexpand(true)
.vexpand(true)
.pixel_size(512)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
let progress_bar_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.margin_start(15)
.margin_end(15)
.build();
let install_progress_bar = gtk::ProgressBar::builder()
.hexpand(true)
.margin_start(15)
.margin_end(15)
.margin_top(15)
.margin_bottom(15)
.show_text(true)
.build();
let progress_log_button_content = adw::ButtonContent::builder()
.label(gettext("view_logs"))
.icon_name("terminal")
.build();
let progress_log_button = gtk::Button::builder()
.child(&progress_log_button_content)
.margin_start(15)
.margin_end(15)
.margin_top(15)
.margin_bottom(15)
.build();
progress_bar_box.append(&install_progress_bar);
progress_bar_box.append(&progress_log_button);
install_progress_log_stack.add_titled(
&placeholder_icon,
Some("slideshow_page"),
"slideshow_page",
);
install_progress_log_stack.add_titled(
&install_progress_log_terminal,
Some("terminal_log_page"),
"terminal_log_page",
);
install_progress_box.append(&install_progress_log_stack);
install_progress_box.append(&progress_bar_box);
install_nested_stack.add_titled(&install_confirm_box, Some("confirm_page"), "confirm_page");
install_nested_stack.add_titled(
&install_progress_box,
Some("progress_page"),
"progress_page",
);
//
//
install_confirm_button.connect_clicked(clone!(@weak install_nested_stack, @weak install_progress_log_terminal, @weak install_progress_bar, @weak done_main_box, @weak content_stack, @weak window => move |_| {
install_nested_stack.set_visible_child_name("progress_page");
begin_install(&install_progress_log_terminal, &install_progress_bar, &done_main_box, &content_stack, &window);
}));
progress_log_button.connect_clicked(clone!(@weak install_progress_log_stack => move |_| {
if install_progress_log_stack.visible_child_name() == Some(GString::from_string_unchecked("slideshow_page".into())) {
install_progress_log_stack.set_visible_child_name("terminal_log_page");
} else {
install_progress_log_stack.set_visible_child_name("slideshow_page");
}
}));
bottom_back_button.connect_clicked(
clone!(@weak content_stack, @weak install_main_box, @weak install_nested_stack => move |_| {
content_stack.set_visible_child_name("partitioning_page");
install_main_box.remove(&install_nested_stack)
}),
);
}
fn begin_install(
install_progress_log_terminal: &vte::Terminal,
install_progress_bar: &gtk::ProgressBar,
done_main_box: &gtk::Box,
content_stack: &gtk::Stack,
window: &adw::ApplicationWindow,
) {
// SPAWN TERMINAL WITH PIKAINSTALL PROCESS
install_progress_log_terminal.spawn_async(
PtyFlags::DEFAULT,
Some(""),
&["/usr/lib/pika/pika-installer-gtk4/scripts/begin-install.sh"],
&[],
SpawnFlags::DEFAULT,
|| {},
-1,
None::<&gio::Cancellable>,
move |result| match result {
Ok(_) => {
eprintln!("could not spawn terminal")
}
Err(err) => {
eprintln!("could not spawn terminal: {}", err);
}
},
);
// wait till /tmp/pika-installer-gtk4-status-parting.txt to change progressbar
let (parting_status_sender, parting_status_receiver) = async_channel::unbounded();
let parting_status_sender = parting_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let parting_status = true;
while parting_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-parting.txt").exists() == true {
parting_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let parting_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
parting_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(parting_status_state) = parting_status_receiver.recv().await {
if parting_status_state == true {
println!("Installation status: Parting");
install_progress_bar.set_fraction(0.20);
install_progress_bar.set_text(Some(&gettext("parting_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-image.txt to change progressbar
let (image_status_sender, image_status_receiver) = async_channel::unbounded();
let image_status_sender = image_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let image_status = true;
while image_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-image.txt").exists() == true {
image_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let image_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
image_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(image_status_state) = image_status_receiver.recv().await {
if image_status_state == true {
println!("Installation status: Imaging");
install_progress_bar.set_fraction(0.60);
install_progress_bar.set_text(Some(&gettext("image_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-flag1.txt to change progressbar
let (flag1_status_sender, flag1_status_receiver) = async_channel::unbounded();
let flag1_status_sender = flag1_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let flag1_status = true;
while flag1_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-flag1.txt").exists() == true {
flag1_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let flag1_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
flag1_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(flag1_status_state) = flag1_status_receiver.recv().await {
if flag1_status_state == true {
println!("Installation status: Flag1");
install_progress_bar.set_fraction(0.65);
install_progress_bar.set_text(Some(&gettext("flag1_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-flag2.txt to change progressbar
let (flag2_status_sender, flag2_status_receiver) = async_channel::unbounded();
let flag2_status_sender = flag2_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let flag2_status = true;
while flag2_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-flag2.txt").exists() == true {
flag2_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let flag2_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
flag2_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(flag2_status_state) = flag2_status_receiver.recv().await {
if flag2_status_state == true {
println!("Installation status: Flag2");
install_progress_bar.set_fraction(0.70);
install_progress_bar.set_text(Some(&gettext("flag2_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-crypt.txt to change progressbar
let (crypt_status_sender, crypt_status_receiver) = async_channel::unbounded();
let crypt_status_sender = crypt_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let crypt_status = true;
while crypt_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-crypt.txt").exists() == true {
crypt_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let crypt_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
crypt_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(crypt_status_state) = crypt_status_receiver.recv().await {
if crypt_status_state == true {
println!("Installation status: Crypttab");
install_progress_bar.set_fraction(0.75);
install_progress_bar.set_text(Some(&gettext("crypt_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-lang.txt to change progressbar
let (lang_status_sender, lang_status_receiver) = async_channel::unbounded();
let lang_status_sender = lang_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let lang_status = true;
while lang_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-lang.txt").exists() == true {
lang_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let lang_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
lang_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(lang_status_state) = lang_status_receiver.recv().await {
if lang_status_state == true {
println!("Installation status: Language");
install_progress_bar.set_fraction(0.80);
install_progress_bar.set_text(Some(&gettext("lang_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-boot.txt to change progressbar
let (boot_status_sender, boot_status_receiver) = async_channel::unbounded();
let boot_status_sender = boot_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let boot_status = true;
while boot_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-boot.txt").exists() == true {
boot_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let boot_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
boot_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(boot_status_state) = boot_status_receiver.recv().await {
if boot_status_state == true {
println!("Installation status: Bootloader");
install_progress_bar.set_fraction(0.85);
install_progress_bar.set_text(Some(&gettext("boot_status_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-status-post.txt to change progressbar
let (post_status_sender, post_status_receiver) = async_channel::unbounded();
let post_status_sender = post_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let post_status = true;
while post_status == true {
if Path::new("/tmp/pika-installer-gtk4-status-post.txt").exists() == true {
post_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let post_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
post_status_main_context.spawn_local(clone!(@weak install_progress_bar => async move {
while let Ok(post_status_state) = post_status_receiver.recv().await {
if post_status_state == true {
println!("Installation status: Post Install");
install_progress_bar.set_fraction(0.90);
install_progress_bar.set_text(Some(&gettext("post_status_text")));
}
}
}));
// wait till /tmp/pika-installer-gtk4-successful.txt to change progressbar
let (done_status_sender, done_status_receiver) = async_channel::unbounded();
let done_status_sender = done_status_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || {
let done_status = true;
while done_status == true {
if Path::new("/tmp/pika-installer-gtk4-successful.txt").exists() == true
|| Path::new("/tmp/pika-installer-gtk4-fail.txt").exists() == true
{
done_status_sender
.send_blocking(true)
.expect("The channel needs to be open.");
break;
}
}
});
let done_status_main_context = MainContext::default();
// The main loop executes the asynchronous block
done_status_main_context.spawn_local(
clone!(@weak done_main_box, @weak content_stack, @weak window => async move {
while let Ok(done_status_state) = done_status_receiver.recv().await {
if done_status_state == true {
println!("Installation status: Done");
done_page(&done_main_box, &window);
content_stack.set_visible_child_name("done_page");
}
}
}),
);
}

View File

@ -1,26 +1,23 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
use std::io::BufRead;
use std::io::BufReader;
use std::process::Command;
use std::process::Stdio;
use std::time::Instant;
use std::str;
use std::fs;
use std::path::Path;
pub fn keyboard_page(content_stack: &gtk::Stack) {
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
@ -30,7 +27,7 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label("Back")
.label(gettext("back"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -39,7 +36,7 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
.hexpand(true)
.build();
let bottom_next_button = gtk::Button::builder()
.label("Next")
.label(gettext("next"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -69,7 +66,7 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
// the header text for the keyboard page
let keyboard_header_text = gtk::Label::builder()
.label("Select a keyboard")
.label(gettext("select_a_keyboard"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
@ -109,7 +106,7 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
// text above keyboard selection box
let keyboard_selection_text = gtk::Label::builder()
.label("Please select a Keyboard layout for the system to use")
.label(gettext("please_select_keyboard"))
.halign(gtk::Align::Center)
.hexpand(true)
.margin_top(15)
@ -120,16 +117,15 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
keyboard_selection_text.add_css_class("medium_sized_text");
let keyboard_selection_expander_row = adw::ExpanderRow::builder()
.title("No Keyboard Layout selected")
.title(gettext("no_keyboard_selected"))
.build();
let null_checkbutton = gtk::CheckButton::builder()
.label("No Keyboard Layout selected")
.label(gettext("no_keyboard_selected"))
.build();
let keyboard_selection_expander_row_viewport = gtk::ScrolledWindow::builder()
.height_request(200)
.build();
let keyboard_selection_expander_row_viewport =
gtk::ScrolledWindow::builder().height_request(200).build();
let keyboard_selection_expander_row_viewport_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
@ -145,7 +141,8 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
keyboard_selection_expander_row_viewport_listbox.add_css_class("boxed-list");
keyboard_selection_expander_row_viewport_listbox.append(&keyboard_selection_expander_row);
keyboard_selection_expander_row_viewport.set_child(Some(&keyboard_selection_expander_row_viewport_box));
keyboard_selection_expander_row_viewport
.set_child(Some(&keyboard_selection_expander_row_viewport_box));
keyboard_selection_expander_row.add_row(&keyboard_selection_expander_row_viewport);
@ -170,7 +167,9 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
.unwrap();
let current_keyboard_output = current_keyboard_cut.wait_with_output().unwrap();
let current_keyboard = str::from_utf8(&current_keyboard_output.stdout).unwrap().trim();
let current_keyboard = str::from_utf8(&current_keyboard_output.stdout)
.unwrap()
.trim();
let keyboard_layout_cli = Command::new("localectl")
.arg("list-x11-keymap-layouts")
@ -182,8 +181,7 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
let keyboard_layout_stdout = keyboard_layout_cli.stdout.expect("could not get stdout");
let keyboard_layout_reader = BufReader::new(keyboard_layout_stdout);
let keyboard_data_buffer = gtk::TextBuffer::builder()
.build();
let keyboard_data_buffer = gtk::TextBuffer::builder().build();
for keyboard_layout in keyboard_layout_reader.lines() {
let keyboard_layout = keyboard_layout.unwrap();
@ -198,6 +196,11 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
keyboard_selection_expander_row.set_title(&keyboard_layout);
bottom_next_button.set_sensitive(true);
keyboard_data_buffer.set_text(&keyboard_layout);
Command::new("setxkbmap")
.arg("-layout")
.arg(keyboard_layout.clone())
.spawn()
.expect("keyboard failed to start");
}
}));
if current_keyboard.contains(&(keyboard_layout_clone)) {
@ -221,11 +224,25 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
//// Add the keyboard selection/page content box to keyboard main box
keyboard_main_box.append(&keyboard_selection_box);
//// Add the keyboard selection/page content box to keyboard main box
keyboard_main_box.append(
&gtk::Entry::builder()
.hexpand(true)
.valign(Align::End)
.vexpand(false)
.margin_bottom(15)
.margin_top(15)
.margin_end(15)
.margin_start(15)
.placeholder_text(gettext("test_your_keyboard"))
.build(),
);
keyboard_main_box.append(&bottom_box);
// / Content stack appends
//// Add the keyboard_main_box as page: keyboard_page, Give it nice title
content_stack.add_titled(&keyboard_main_box, Some("keyboard_page"), "Keyboard");
content_stack.add_titled(&keyboard_main_box, Some("keyboard_page"), &gettext("keyboard"));
let keyboard_data_buffer_clone = keyboard_data_buffer.clone();
@ -240,5 +257,4 @@ pub fn keyboard_page(content_stack: &gtk::Stack) {
bottom_back_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("timezone_page")
}));
}

View File

@ -1,27 +1,23 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext, LocaleCategory};
use std::env;
use std::io::BufRead;
use std::io::BufReader;
use std::process::Command;
use std::process::Stdio;
use std::time::Instant;
use std::env;
use std::fs;
use std::path::Path;
pub fn language_page(content_stack: &gtk::Stack) {
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
@ -31,7 +27,7 @@ pub fn language_page(content_stack: &gtk::Stack) {
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label("Back")
.label(gettext("back"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -40,7 +36,7 @@ pub fn language_page(content_stack: &gtk::Stack) {
.hexpand(true)
.build();
let bottom_next_button = gtk::Button::builder()
.label("Next")
.label(gettext("next"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -70,7 +66,7 @@ pub fn language_page(content_stack: &gtk::Stack) {
// the header text for the language page
let language_header_text = gtk::Label::builder()
.label("Select a language")
.label(gettext("select_a_language"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
@ -110,7 +106,7 @@ pub fn language_page(content_stack: &gtk::Stack) {
// text above language selection box
let language_selection_text = gtk::Label::builder()
.label("Please select a locale for the system to use")
.label(gettext("please_select_locale"))
.halign(gtk::Align::Center)
.hexpand(true)
.margin_top(15)
@ -121,22 +117,22 @@ pub fn language_page(content_stack: &gtk::Stack) {
language_selection_text.add_css_class("medium_sized_text");
let language_selection_expander_row = adw::ExpanderRow::builder()
.title("No locale selected")
.title(gettext("no_locale_selected"))
.build();
let null_checkbutton = gtk::CheckButton::builder()
.label("No locale selected")
.label(gettext("no_locale_selected"))
.build();
let language_selection_expander_row_viewport = gtk::ScrolledWindow::builder()
.height_request(200)
.build();
let language_selection_expander_row_viewport =
gtk::ScrolledWindow::builder().height_request(200).build();
let language_selection_expander_row_viewport_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
language_selection_expander_row_viewport.set_child(Some(&language_selection_expander_row_viewport_box));
language_selection_expander_row_viewport
.set_child(Some(&language_selection_expander_row_viewport_box));
let language_selection_expander_row_viewport_listbox = gtk::ListBox::builder()
.selection_mode(SelectionMode::None)
@ -152,7 +148,7 @@ pub fn language_page(content_stack: &gtk::Stack) {
let current_locale = match env::var_os("LANG") {
Some(v) => v.into_string().unwrap(),
None => panic!("$LANG is not set")
None => panic!("$LANG is not set"),
};
let locale_cli = Command::new("locale")
@ -177,15 +173,12 @@ pub fn language_page(content_stack: &gtk::Stack) {
let locale_reader = BufReader::new(locale_cli_sort.stdout.expect("could not get stdout"));
let lang_data_buffer = gtk::TextBuffer::builder()
.build();
let lang_data_buffer = gtk::TextBuffer::builder().build();
for locale in locale_reader.lines() {
let locale = locale.unwrap();
let locale_clone = locale.clone();
let locale_checkbutton = gtk::CheckButton::builder()
.label(locale.clone())
.build();
let locale_checkbutton = gtk::CheckButton::builder().label(locale.clone()).build();
locale_checkbutton.set_group(Some(&null_checkbutton));
language_selection_expander_row_viewport_box.append(&locale_checkbutton);
locale_checkbutton.connect_toggled(clone!(@weak locale_checkbutton, @weak language_selection_expander_row, @weak bottom_next_button, @weak lang_data_buffer => move |_| {
@ -220,7 +213,7 @@ pub fn language_page(content_stack: &gtk::Stack) {
// / Content stack appends
//// Add the language_main_box as page: language_page, Give it nice title
content_stack.add_titled(&language_main_box, Some("language_page"), "Language");
content_stack.add_titled(&language_main_box, Some("language_page"), &gettext("language"));
let lang_data_buffer_clone = lang_data_buffer.clone();
@ -229,6 +222,17 @@ pub fn language_page(content_stack: &gtk::Stack) {
fs::remove_file("/tmp/pika-installer-gtk4-lang.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-lang.txt");
}
fs::write("/tmp/pika-installer-gtk4-lang.txt", lang_data_buffer_clone.text(&lang_data_buffer_clone.bounds().0, &lang_data_buffer_clone.bounds().1, true).to_string()).expect("Unable to write file");
Command::new("sudo")
.arg("localectl")
.arg("set-locale")
.arg("LANG=".to_owned() + &lang_data_buffer_clone.text(&lang_data_buffer_clone.bounds().0, &lang_data_buffer_clone.bounds().1, true).to_string() + ".UTF-8")
.spawn()
.expect("locale failed to start");
gettextrs::setlocale(LocaleCategory::LcAll, lang_data_buffer_clone.text(&lang_data_buffer_clone.bounds().0, &lang_data_buffer_clone.bounds().1, true).to_string() + ".UTF-8");
if gettext("pikaos_installer") == "pikaos_installer" {
println!("Warning: Current LANG is not supported, using fallback Locale.");
gettextrs::setlocale(LocaleCategory::LcAll, "en_US.UTF8");
}
content_stack.set_visible_child_name("eula_page")
}));
bottom_back_button.connect_clicked(clone!(@weak content_stack => move |_| {

View File

@ -1,40 +1,37 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use crate::build_ui::build_ui;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
mod config;
use gettextrs::{gettext, LocaleCategory};
use config::{GETTEXT_PACKAGE, LOCALEDIR, APP_ID};
mod automatic_partitioning;
mod build_ui;
use crate::build_ui::build_ui;
mod save_window_size;
mod welcome_page;
mod efi_error_page;
mod language_page;
mod eula_page;
mod timezone_page;
mod keyboard_page;
mod partitioning_page;
mod install_page;
mod done_page;
use crate::save_window_size::save_window_size;
use crate::welcome_page::welcome_page;
use crate::efi_error_page::efi_error_page;
use crate::language_page::language_page;
use crate::eula_page::eula_page;
use crate::timezone_page::timezone_page;
use crate::keyboard_page::keyboard_page;
use crate::partitioning_page::partitioning_page;
use crate::install_page::install_page;
use crate::done_page::done_page;
mod drive_mount_row;
mod efi_error_page;
mod eula_page;
mod install_page;
mod keyboard_page;
mod language_page;
mod manual_partitioning;
mod partitioning_page;
mod save_window_size;
mod timezone_page;
mod welcome_page;
/// main function
fn main() {
let application = adw::Application::new(Some("com.github.pikaos-linux.pikainstallergtk4"), Default::default());
let application = adw::Application::new(
Some(APP_ID),
Default::default(),
);
application.connect_startup(|app| {
// The CSS "magic" happens here.
let provider = CssProvider::new();
@ -46,8 +43,18 @@ fn main() {
&provider,
STYLE_PROVIDER_PRIORITY_APPLICATION,
);
// Prepare i18n
gettextrs::setlocale(LocaleCategory::LcAll, "");
gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain");
gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain");
// Fallback if no translation present
if gettext("pikaos_installer") == "pikaos_installer" {
println!("Warning: Current LANG is not supported, using fallback Locale.");
gettextrs::setlocale(LocaleCategory::LcAll, "en_US.UTF8");
}
app.connect_activate(build_ui);
});
application.run();
}

View File

@ -0,0 +1,708 @@
// Use libraries
use adw::prelude::*;
use adw::*;
use glib::*;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use std::thread;
use gettextrs::{gettext};
use std::cell::{RefCell};
use std::rc::Rc;
use duct::cmd;
use std::{
collections::HashSet,
hash::Hash,
io::{BufRead, BufReader},
process::{Command},
time::{Duration},
};
use crate::drive_mount_row::DriveMountRow;
use serde::*;
#[derive(PartialEq, Debug, Eq, Hash, Clone, Serialize, Deserialize)]
pub struct DriveMount {
pub partition: String,
pub mountpoint: String,
pub mountopt: String,
}
fn create_mount_row(
listbox: &gtk::ListBox,
partition_method_manual_error_label: &gtk::Label,
partition_method_manual_valid_label: &gtk::Label,
manual_drive_mount_array: &Rc<RefCell<Vec<DriveMount>>>,
part_table_array: &Rc<RefCell<Vec<String>>>,
_check_part_unique: &Rc<RefCell<bool>>,
) -> DriveMountRow {
let partition_scroll_child = gtk::ListBox::builder().build();
let partitions_scroll = gtk::ScrolledWindow::builder()
.hexpand(true)
.vexpand(true)
.child(&partition_scroll_child)
.build();
// Create row
let row = DriveMountRow::new_with_scroll(&partitions_scroll);
let null_checkbutton = gtk::CheckButton::builder().build();
let part_table_array_ref = part_table_array.borrow_mut();
for partition in part_table_array_ref.iter() {
let partition_size_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_part_size")
.arg(partition.clone())
.output()
.expect("failed to execute process");
let partition_fs_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_part_fs")
.arg(partition.clone().replace("mapper/", ""))
.output()
.expect("failed to execute process");
let partition_size = String::from_utf8(partition_size_cli.stdout)
.expect("Failed to create float")
.trim()
.parse::<f64>()
.unwrap();
let partition_fs = String::from_utf8(partition_fs_cli.stdout).expect("Failed read stdout");
let partition_button = gtk::CheckButton::builder()
.valign(Align::Center)
.can_focus(false)
.build();
partition_button.set_group(Some(&null_checkbutton));
let partition_row: adw::ActionRow =
if partition_fs.contains("crypto_LUKS") || partition_fs.contains("lvm") {
let prow = adw::ActionRow::builder()
.activatable_widget(&partition_button)
.title(partition.clone())
.name(partition.clone())
.subtitle(gettext("part_need_mapper"))
.build();
prow
} else {
let prow = adw::ActionRow::builder()
.activatable_widget(&partition_button)
.title(partition.clone())
.name(partition.clone())
.subtitle(partition_fs + &pretty_bytes::converter::convert(partition_size))
.build();
prow
};
partition_row.add_prefix(&partition_button);
partition_button.connect_toggled(clone!(@weak row, @weak listbox, @weak partition_button, @strong manual_drive_mount_array, @strong partition=> move |_| {
let mut manual_drive_mount_array_ref = RefCell::borrow_mut(&manual_drive_mount_array);
if partition_button.is_active() == true {
row.set_partition(partition.clone());
} else {
let manual_drive_mount_array_ref_index = manual_drive_mount_array_ref.iter().position(|x| x.partition == partition.clone()).unwrap();
manual_drive_mount_array_ref.remove(manual_drive_mount_array_ref_index);
}
}));
partition_scroll_child.append(&partition_row);
}
let listbox_clone = listbox.clone();
row.connect_closure(
"row-deleted",
false,
closure_local!(@strong partition_method_manual_error_label ,@strong partition_method_manual_valid_label, @strong row as _row => move |_row: DriveMountRow| {
listbox_clone.remove(&_row);
partition_method_manual_error_label.set_label("");
partition_method_manual_error_label.set_widget_name("");
partition_method_manual_error_label.set_visible(false);
partition_method_manual_valid_label.set_label("");
partition_method_manual_valid_label.set_visible(false);
}),
);
// Return row
row
}
//pub fn manual_partitioning(window: &adw::ApplicationWindow, partitioning_stack: &gtk::Stack, bottom_next_button: &gtk::Button) -> (gtk::TextBuffer, gtk::TextBuffer, adw::PasswordEntryRow) {
pub fn manual_partitioning(
partitioning_stack: &gtk::Stack,
bottom_next_button: &gtk::Button,
manual_drive_mount_array: &Rc<RefCell<Vec<DriveMount>>>,
) {
let part_table_array: Rc<RefCell<Vec<String>>> = Default::default();
let check_part_unique = Rc::new(RefCell::new(true));
let partition_method_manual_main_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.margin_bottom(15)
.margin_top(15)
.margin_end(15)
.margin_start(15)
.build();
let partition_method_manual_header_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.build();
// the header text for the partitioning page
let partition_method_manual_header_text = gtk::Label::builder()
.label(gettext("manual_part_installer"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(5)
.build();
partition_method_manual_header_text.add_css_class("header_sized_text");
// the header icon for the partitioning icon
let partition_method_manual_header_icon = gtk::Image::builder()
.icon_name("org.gnome.Settings")
.halign(gtk::Align::Start)
.hexpand(true)
.pixel_size(78)
.margin_top(15)
.margin_bottom(15)
.margin_start(0)
.margin_end(15)
.build();
let partition_method_manual_selection_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
let partition_method_manual_gparted_button_content_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
let partition_method_manual_gparted_button_content_text = gtk::Label::builder()
.label(gettext("use_utility_manual"))
.build();
let partition_method_manual_gparted_button_content = adw::ButtonContent::builder()
.label(gettext("open_gparted"))
.icon_name("gparted")
.build();
let partition_method_manual_gparted_button = gtk::Button::builder()
.child(&partition_method_manual_gparted_button_content_box)
.halign(Align::Center)
.valign(Align::Start)
.build();
let drive_mounts_adw_listbox = gtk::ListBox::builder().hexpand(true).vexpand(true).build();
drive_mounts_adw_listbox.add_css_class("boxed-list");
let drive_mounts_viewport = gtk::ScrolledWindow::builder()
.halign(Align::Center)
.valign(Align::Center)
.margin_top(30)
.margin_bottom(30)
.margin_start(30)
.margin_end(30)
.propagate_natural_height(true)
.propagate_natural_width(true)
.min_content_height(200)
.min_content_width(200)
.hexpand(true)
.vexpand(true)
.child(&drive_mounts_adw_listbox)
.build();
let partition_method_manual_selection_text = gtk::Label::builder()
.label(gettext("manual_part_note"))
.halign(gtk::Align::Center)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
partition_method_manual_selection_text.add_css_class("medium_sized_text");
let partition_refresh_button = gtk::Button::builder()
.label(gettext("refresh_part_table"))
.halign(gtk::Align::End)
.build();
partition_refresh_button.add_css_class("destructive-action");
let fstab_valid_check = gtk::Button::builder()
.label(gettext("validate_fs_table"))
.halign(gtk::Align::Start)
.build();
fstab_valid_check.add_css_class("valid-action");
let drive_mount_add_button = gtk::Button::builder()
.icon_name("list-add")
.vexpand(true)
.hexpand(true)
.build();
let partition_method_manual_error_label = gtk::Label::builder()
.halign(Align::Start)
.valign(Align::End)
.vexpand(true)
.visible(false)
.build();
partition_method_manual_error_label.add_css_class("small_error_text");
let partition_method_manual_valid_label = gtk::Label::builder()
.halign(Align::Start)
.valign(Align::End)
.vexpand(true)
.visible(false)
.label(gettext("fstab_status_valid"))
.build();
partition_method_manual_valid_label.add_css_class("small_valid_text");
let partition_method_manual_warn_label = gtk::Label::builder()
.halign(Align::Start)
.valign(Align::End)
.vexpand(true)
.visible(false)
.build();
partition_method_manual_warn_label.add_css_class("small_warn_text");
partition_method_manual_header_box.append(&partition_method_manual_header_text);
partition_method_manual_header_box.append(&partition_method_manual_header_icon);
partition_method_manual_selection_box.append(&partition_method_manual_selection_text);
partition_method_manual_selection_box.append(&partition_refresh_button);
partition_method_manual_main_box.append(&partition_method_manual_header_box);
partition_method_manual_main_box.append(&partition_method_manual_selection_box);
partition_method_manual_gparted_button_content_box
.append(&partition_method_manual_gparted_button_content);
partition_method_manual_gparted_button_content_box
.append(&partition_method_manual_gparted_button_content_text);
partition_method_manual_main_box.append(&partition_method_manual_gparted_button);
drive_mounts_adw_listbox.append(&drive_mount_add_button);
partition_method_manual_main_box.append(&drive_mounts_viewport);
partition_method_manual_main_box.append(&fstab_valid_check);
partition_method_manual_main_box.append(&partition_method_manual_error_label);
partition_method_manual_main_box.append(&partition_method_manual_valid_label);
partition_method_manual_main_box.append(&partition_method_manual_warn_label);
fstab_valid_check.connect_clicked(clone!(@weak partition_method_manual_error_label, @weak partition_method_manual_valid_label, @strong manual_drive_mount_array, @strong check_part_unique => move |_| {
partition_err_check(&partition_method_manual_error_label, &partition_method_manual_valid_label, &manual_drive_mount_array);
}));
partition_refresh_button.connect_clicked(clone!(@weak drive_mounts_adw_listbox,@strong part_table_array, @strong manual_drive_mount_array => move |_| {
while let Some(row) = drive_mounts_adw_listbox.last_child() {
if row.widget_name() == "DriveMountRow" {
drive_mounts_adw_listbox.remove(&row);
} else {
break
}
}
let partition_method_manual_get_partitions_lines = BufReader::new(cmd!("bash", "-c", "sudo /usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh get_partitions").reader().unwrap()).lines();
let mut part_table_array_ref = part_table_array.borrow_mut();
part_table_array_ref.clear();
let mut manual_drive_mount_array_ref = manual_drive_mount_array.borrow_mut();
manual_drive_mount_array_ref.clear();
for partition in partition_method_manual_get_partitions_lines {
part_table_array_ref.push(partition.unwrap());
}
}));
partition_refresh_button.emit_clicked();
partition_method_manual_gparted_button.connect_clicked(move |_| {
Command::new("gparted")
.spawn()
.expect("gparted failed to start");
});
drive_mount_add_button.connect_clicked(clone!(@weak partition_method_manual_error_label, @weak partition_method_manual_valid_label ,@weak drive_mounts_adw_listbox, @strong manual_drive_mount_array, @strong part_table_array, @strong check_part_unique => move |_| {
drive_mounts_adw_listbox.append(&create_mount_row(&drive_mounts_adw_listbox, &partition_method_manual_error_label, &partition_method_manual_valid_label, &manual_drive_mount_array, &part_table_array,&check_part_unique))
}));
let (anti_dup_partition_sender, anti_dup_partition_receiver) = async_channel::unbounded();
let anti_dup_partition_sender = anti_dup_partition_sender.clone();
// The long running operation runs now in a separate thread
gio::spawn_blocking(move || loop {
thread::sleep(Duration::from_millis(400));
anti_dup_partition_sender
.send_blocking(true)
.expect("The channel needs to be open.");
});
let anti_dup_partition_loop_context = MainContext::default();
anti_dup_partition_loop_context.spawn_local(clone!(@weak partition_method_manual_error_label, @weak partition_method_manual_valid_label ,@weak drive_mounts_adw_listbox, @weak partitioning_stack, @strong manual_drive_mount_array,@weak bottom_next_button, @strong check_part_unique => async move {
while let Ok(_state) = anti_dup_partition_receiver.recv().await {
let mut counter = drive_mounts_adw_listbox.first_child();
let mut manual_drive_mount_array_ref = manual_drive_mount_array.borrow_mut();
// usage of while loop
manual_drive_mount_array_ref.clear();
while let Some(row) = counter {
if row.widget_name() == "DriveMountRow" {
let row_mount = DriveMount {
partition: row.clone().property("partition"),
mountpoint: row.clone().property("mountpoint"),
mountopt: row.clone().property("mountopt"),
};
manual_drive_mount_array_ref.push(row_mount);
}
counter = row.next_sibling();
}
let mut counter = drive_mounts_adw_listbox.first_child();
while let Some(ref row) = counter {
if row.widget_name() == "DriveMountRow" {
let mut counter_scrw = row.property::<gtk::ScrolledWindow>("partitionscroll").child().unwrap().first_child().unwrap().first_child();
while let Some(ref row_scrw) = counter_scrw {
if manual_drive_mount_array_ref.iter().any(|e| {
if !e.partition.is_empty() {
row_scrw.widget_name().contains(&e.partition)
} else {
return false
}
}) {
if *check_part_unique.borrow_mut() == true {
row_scrw.set_sensitive(false)
} else if row_scrw.property::<String>("subtitle").contains(&gettext("part_need_mapper")) {
row_scrw.set_sensitive(false)
} else {
row_scrw.set_sensitive(true)
}
}
else if row_scrw.property::<String>("subtitle").contains(&gettext("part_need_mapper")) {
row_scrw.set_sensitive(false)
} else {
row_scrw.set_sensitive(true)
}
counter_scrw = row_scrw.next_sibling();
}
}
counter = row.next_sibling();
}
let manual_drive_mount_array_ref_clone = manual_drive_mount_array_ref.clone();
*check_part_unique.borrow_mut() = true;
for mountopts in manual_drive_mount_array_ref
.iter()
.map(|x| x.mountopt.as_str())
.collect::<HashSet<&str>>()
{
if mountopts.contains("subvol") {
*check_part_unique.borrow_mut() = false
}
}
if *check_part_unique.borrow_mut() == false {
partition_method_manual_warn_label
.set_label(&gettext("fstab_subvol_warn"));
partition_method_manual_warn_label.set_visible(true);
} else {
partition_method_manual_warn_label.set_visible(false);
}
if partitioning_stack.visible_child_name() == Some(GString::from_string_unchecked("partition_method_manual_page".into())) {
if manual_drive_mount_array_ref_clone.iter().any(|x| {if x.mountpoint == "/" {return true} else {return false}}) && manual_drive_mount_array_ref_clone.iter().any(|x| {if x.mountpoint == "/boot" {return true} else {return false}}) && manual_drive_mount_array_ref_clone.iter().any(|x| {if x.mountpoint == "/boot/efi" {return true} else {return false}}) && !partition_method_manual_error_label.is_visible() && partition_method_manual_valid_label.is_visible() {
if !bottom_next_button.is_sensitive() {
bottom_next_button.set_sensitive(true);
}
} else {
if bottom_next_button.is_sensitive() {
bottom_next_button.set_sensitive(false);
}
}
}
}
}));
partitioning_stack.add_titled(
&partition_method_manual_main_box,
Some("partition_method_manual_page"),
"partition_method_manual_page",
);
//return(partition_method_manual_target_buffer, partition_method_manual_luks_buffer, partition_method_manual_luks_password_entry)
}
fn partition_err_check(
partition_method_manual_error_label: &gtk::Label,
partition_method_manual_valid_label: &gtk::Label,
manual_drive_mount_array: &Rc<RefCell<Vec<DriveMount>>>,
) {
let mut empty_mountpoint = false;
let manual_drive_mount_array_ref = manual_drive_mount_array.borrow_mut();
for mountpoint in manual_drive_mount_array_ref
.iter()
.map(|x| x.mountpoint.as_str())
.collect::<HashSet<&str>>()
{
if empty_mountpoint == false {
if mountpoint.is_empty() {
empty_mountpoint = true
}
}
}
let mut empty_partition = false;
for partition in manual_drive_mount_array_ref
.iter()
.map(|x| x.partition.as_str())
.collect::<HashSet<&str>>()
{
if empty_partition == false {
if partition.is_empty() {
empty_partition = true
}
}
}
if empty_mountpoint == false {
if &partition_method_manual_error_label.widget_name()
== "err1"
{
partition_method_manual_error_label.set_visible(false);
}
if manual_drive_mount_array_ref.len()
- manual_drive_mount_array_ref
.iter()
.map(|x| x.mountpoint.as_str())
.collect::<HashSet<&str>>()
.len()
> 0
{
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label
.set_label(&gettext("fstab_multiple_part_mountpoint_err"));
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err0");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err0" {
partition_method_manual_error_label.set_visible(false);
}
}
} else {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label
.set_label(&gettext("fstab_no_mountpoint_err"));
partition_method_manual_error_label.set_widget_name("err1");
partition_method_manual_error_label.set_visible(true);
}
}
if empty_partition == true {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label
.set_label(&gettext("fstab_no_partition_err"));
partition_method_manual_error_label.set_widget_name("err2");
partition_method_manual_error_label.set_visible(true);
}
} else {
if partition_method_manual_error_label.widget_name() == "err2"
{
partition_method_manual_error_label.set_visible(false);
}
}
for drivemounts in manual_drive_mount_array_ref
.iter()
.map(|x| x)
.collect::<HashSet<&DriveMount>>()
{
if !drivemounts.partition.is_empty() {
let partition_size_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_part_size")
.arg(drivemounts.partition.clone())
.output()
.expect("failed to execute process");
let partition_fs_cli = Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_part_fs")
.arg(drivemounts.partition.replace("mapper/", ""))
.output()
.expect("failed to execute process");
let partition_size = String::from_utf8(partition_size_cli.stdout)
.expect("Failed to create float")
.trim()
.parse::<f64>()
.unwrap();
let partition_fs = String::from_utf8(partition_fs_cli.stdout)
.expect("Failed to create string")
.trim()
.parse::<String>()
.unwrap();
if drivemounts.mountpoint == "/boot/efi" {
if partition_size < 500000000.0 {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_small_efi_err")
+ &drivemounts.partition
+ &gettext("fstab_small_efi_size")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err3");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err3" {
partition_method_manual_error_label.set_visible(false);
}
}
if partition_fs != "vfat" {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_badfs")
+ &drivemounts.partition
+ &gettext("fstab_badfs_efi")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err4");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err4" {
partition_method_manual_error_label.set_visible(false);
}
}
}
if drivemounts.mountpoint == "/boot" {
if partition_size < 1000000000.0 {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_small_boot_err")
+ &drivemounts.partition
+ &gettext("fstab_small_boot_size")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err5");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err5" {
partition_method_manual_error_label.set_visible(false);
}
}
if partition_fs == "vfat" {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_badfs")
+ &drivemounts.partition
+ &gettext("fstab_badfs_boot")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err6");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err6" {
partition_method_manual_error_label.set_visible(false);
}
}
}
if drivemounts.mountpoint == "/" {
if partition_size < 25000000000.0 {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_small_root_err")
+ &drivemounts.partition
+ &gettext("fstab_small_root_size")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err7")
}
} else {
if &partition_method_manual_error_label.widget_name() == "err7" {
partition_method_manual_error_label.set_visible(false);
}
}
if partition_fs == "vfat" || partition_fs == "ntfs" || partition_fs == "swap" || partition_fs == "exfat" {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_badfs")
+ &drivemounts.partition
+ &gettext("fstab_badfs_root")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err8");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err8" {
partition_method_manual_error_label.set_visible(false);
}
}
}
if drivemounts.mountpoint == "/home" {
if partition_size < 10000000000.0 {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_small_home_err")
+ &drivemounts.partition
+ &gettext("fstab_small_home_size")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err9");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err9" {
partition_method_manual_error_label.set_visible(false);
}
}
if partition_fs == "vfat" || partition_fs == "ntfs" || partition_fs == "swap" || partition_fs == "exfat" {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_badfs")
+ &drivemounts.partition
+ &gettext("fstab_badfs_home")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err10");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err10" {
partition_method_manual_error_label.set_visible(false);
}
}
}
if drivemounts.mountpoint == "[SWAP]" {
if partition_fs != "swap" {
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_badfs")
+ &drivemounts.partition
+ &gettext("fstab_badfs_swap")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err11");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err11" {
partition_method_manual_error_label.set_visible(false);
}
}
}
if empty_mountpoint == false
&& !drivemounts.mountpoint.starts_with("/")
&& drivemounts.mountpoint != "[SWAP]"
{
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_error_label.set_label(
&(gettext("fstab_bad_mountpoint")
+ &drivemounts.mountpoint
+ &gettext("fstab_bad_mountpoint_msg")),
);
partition_method_manual_error_label.set_visible(true);
partition_method_manual_error_label.set_widget_name("err12");
}
} else {
if &partition_method_manual_error_label.widget_name() == "err12" {
partition_method_manual_error_label.set_visible(false);
}
}
if !partition_method_manual_error_label.is_visible() {
partition_method_manual_valid_label.set_visible(true)
} else {
partition_method_manual_valid_label.set_visible(false)
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,301 @@
// Use libraries
use adw::prelude::*;
use adw::*;
use glib::*;
use glob::glob;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
use crate::automatic_partitioning::automatic_partitioning;
use crate::install_page::install_page;
use crate::manual_partitioning::manual_partitioning;
use std::fs;
use std::path::Path;
use std::cell::RefCell;
use std::rc::Rc;
use duct::*;
use crate::{manual_partitioning};
use manual_partitioning::DriveMount;
pub fn partitioning_page(
done_main_box: &gtk::Box,
install_main_box: &gtk::Box,
content_stack: &gtk::Stack,
window: &adw::ApplicationWindow,
) {
let manual_drive_mount_array: Rc<RefCell<Vec<DriveMount>>> = Default::default();
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.valign(gtk::Align::End)
.vexpand(true)
.build();
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label(gettext("back"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.halign(gtk::Align::Start)
.hexpand(true)
.build();
let bottom_next_button = gtk::Button::builder()
.label(gettext("next"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.halign(gtk::Align::End)
.hexpand(true)
.sensitive(false)
.build();
// Start Applying css classes
bottom_next_button.add_css_class("suggested-action");
// / bottom_box appends
//// Add the next and back buttons
bottom_box.append(&bottom_back_button);
bottom_box.append(&bottom_next_button);
// the header box for the partitioning page
let partitioning_main_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
// the header box for the partitioning page
let partitioning_header_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.build();
// the header text for the partitioning page
let partitioning_header_text = gtk::Label::builder()
.label(gettext("choose_install_method"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(5)
.build();
partitioning_header_text.add_css_class("header_sized_text");
// the header icon for the partitioning icon
let partitioning_header_icon = gtk::Image::builder()
.icon_name("media-floppy")
.halign(gtk::Align::Start)
.hexpand(true)
.pixel_size(78)
.margin_top(15)
.margin_bottom(15)
.margin_start(0)
.margin_end(15)
.build();
// a stack for the 2 partitioning methods
let partitioning_stack = gtk::Stack::builder()
.transition_type(StackTransitionType::SlideLeftRight)
.build();
let partitioning_method_main_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.build();
// make partitioning selection box for choosing installation or live media
let partitioning_selection_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.spacing(200)
.build();
let manual_method_button_content_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.margin_top(30)
.margin_bottom(30)
.build();
let manual_method_button_content_image = gtk::Image::builder()
.icon_name("org.gnome.Settings")
.pixel_size(128)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
let manual_method_button_content_text = gtk::Label::builder()
.label(gettext("manual_partition_drive"))
.margin_top(0)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
manual_method_button_content_text.add_css_class("medium_sized_text");
let automatic_method_button_content_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
.margin_top(20)
.margin_bottom(20)
.margin_end(15)
.margin_start(15)
.build();
let automatic_method_button_content_image = gtk::Image::builder()
.icon_name("builder")
.pixel_size(128)
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
let automatic_method_button_content_text = gtk::Label::builder()
.label(gettext("auto_partition_drive"))
.margin_top(0)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.build();
automatic_method_button_content_text.add_css_class("medium_sized_text");
let manual_method_button = gtk::Button::builder()
.child(&manual_method_button_content_box)
.vexpand(true)
.hexpand(true)
.halign(gtk::Align::End)
.valign(gtk::Align::Center)
.build();
let automatic_method_button = gtk::Button::builder()
.child(&automatic_method_button_content_box)
.vexpand(true)
.hexpand(true)
.halign(gtk::Align::Start)
.valign(gtk::Align::Center)
.build();
// / manual_method_button_content_box appends
//// add image and text to the manual_method_button
manual_method_button_content_box.append(&manual_method_button_content_image);
manual_method_button_content_box.append(&manual_method_button_content_text);
// / automatic_method_button_content_box appends
//// add image and text to the automatic_method_button
automatic_method_button_content_box.append(&automatic_method_button_content_image);
automatic_method_button_content_box.append(&automatic_method_button_content_text);
// / partitioning_selection_box appends
//// add live and install media button to partitioning page selections
partitioning_selection_box.append(&manual_method_button);
partitioning_selection_box.append(&automatic_method_button);
// / partitioning_header_box appends
//// Add the partitioning page header text and icon
partitioning_header_box.append(&partitioning_header_text);
partitioning_header_box.append(&partitioning_header_icon);
partitioning_method_main_box.append(&partitioning_header_box);
partitioning_method_main_box.append(&partitioning_selection_box);
manual_method_button_content_box.append(&manual_method_button_content_image);
partitioning_stack.add_titled(
&partitioning_method_main_box,
Some("partition_method_select_page"),
"partition_method_select_page",
);
let partitioning_page_automatic_partitioning =
automatic_partitioning(&partitioning_stack, &bottom_next_button);
let _partitioning_page_manual_partitioning = manual_partitioning(
&partitioning_stack,
&bottom_next_button,
&manual_drive_mount_array,
);
// add everything to the main box
partitioning_main_box.append(&partitioning_stack);
partitioning_main_box.append(&bottom_box);
// / Content stack appends
//// Add the partitioning_main_box as page: partitioning_page, Give it nice title
content_stack.add_titled(
&partitioning_main_box,
Some("partitioning_page"),
&gettext("partitioning"),
);
automatic_method_button.connect_clicked(clone!(@weak partitioning_stack => move |_| partitioning_stack.set_visible_child_name("partition_method_automatic_page")));
manual_method_button.connect_clicked(clone!(@weak partitioning_stack => move |_| partitioning_stack.set_visible_child_name("partition_method_manual_page")));
let partition_method_automatic_target_buffer_clone =
partitioning_page_automatic_partitioning.0.clone();
let partition_method_automatic_luks_buffer_clone =
partitioning_page_automatic_partitioning.1.clone();
bottom_next_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("install_page")
}));
bottom_back_button.connect_clicked(clone!(@weak content_stack, @weak partitioning_stack, @weak partitioning_main_box, @weak bottom_next_button => move |_| {
content_stack.set_visible_child_name("keyboard_page");
partitioning_stack.set_visible_child_name("partition_method_select_page");
bottom_next_button.set_sensitive(false);
}));
bottom_next_button.connect_clicked(clone!(@weak content_stack, @weak partitioning_stack, @weak install_main_box, @weak window, @weak done_main_box => move |_| {
if Path::new("/tmp/pika-installer-gtk4-target-auto.txt").exists() {
fs::remove_file("/tmp/pika-installer-gtk4-target-auto.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-target-auto.txt");
}
if Path::new("/tmp/pika-installer-gtk4-target-manual.txt").exists() {
fs::remove_file("/tmp/pika-installer-gtk4-target-manual.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
}
if Path::new("/tmp/pika-installer-gtk4-target-automatic-luks.txt").exists() {
fs::remove_file("/tmp/pika-installer-gtk4-target-automatic-luks.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
}
if Path::new("/tmp/pika-installer-gtk4-target-manual-luks.txt").exists() {
fs::remove_file("/tmp/pika-installer-gtk4-target-manual-luks.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-target-manual.txt");
}
if Path::new("/tmp/pika-installer-gtk4-fail.txt").exists() {
let _ = cmd!("bash","-c","sudo rm -rfv /tmp/pika-installer-gtk4-fail.txt").run();
}
if Path::new("/tmp/pika-installer-gtk4-successful.txt").exists() {
let _ = cmd!("bash","-c","sudo rm -rfv /tmp/pika-installer-gtk4-successful.txt").run();
}
for _status_file in glob("/tmp/pika-installer-gtk4-status*").expect("Failed to read glob pattern") {
let _ = cmd!("bash","-c","sudo rm -rfv /tmp/pika-installer-gtk4-status*").run();
}
for partition_file in glob("/tmp/pika-installer-gtk4-target-manual-p*").expect("Failed to read glob pattern") {
let partition_file = partition_file.unwrap();
fs::remove_file(&partition_file).expect(&partition_file.to_str().unwrap());
}
for luks_file in glob("/tmp/pika-installer-gtk4-target-manual-luks-p*").expect("Failed to read glob pattern") {
let luks_file = luks_file.unwrap();
fs::remove_file(&luks_file).expect(&luks_file.to_str().unwrap());
}
if partitioning_stack.visible_child_name() == Some(GString::from_string_unchecked("partition_method_automatic_page".into())) {
fs::write("/tmp/pika-installer-gtk4-target-auto.txt", partition_method_automatic_target_buffer_clone.text(&partition_method_automatic_target_buffer_clone.bounds().0, &partition_method_automatic_target_buffer_clone.bounds().1, true).to_string()).expect("Unable to write file");
let automatic_luks_result = partition_method_automatic_luks_buffer_clone.text(&partition_method_automatic_luks_buffer_clone.bounds().0, &partition_method_automatic_luks_buffer_clone.bounds().1, true).to_string();
if automatic_luks_result.is_empty() {
//
} else {
let _ = fs::write("/tmp/pika-installer-gtk4-target-automatic-luks.txt", automatic_luks_result);
}
install_page(&done_main_box, &install_main_box, &content_stack, &window, &manual_drive_mount_array);
content_stack.set_visible_child_name("install_page");
} else {
fs::write("/tmp/pika-installer-gtk4-target-manual.txt", "").expect("Unable to write file");
install_page(&done_main_box, &install_main_box, &content_stack, &window, &manual_drive_mount_array);
content_stack.set_visible_child_name("install_page");
}
}));
}

View File

@ -1,16 +1,15 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
#[allow(unused_imports)]
use gtk::prelude::*;
#[allow(unused_imports)]
use gtk::*;
// Save current window size to glib
pub fn save_window_size(window: &adw::ApplicationWindow, glib_settings: &gio::Settings) {
let size = window.default_size();
let _ = glib_settings.set_int("window-width", size.0);

View File

@ -3,6 +3,16 @@
color: red;
}
.small_warn_text {
font-size: 14px;
color: orange;
}
.small_valid_text {
font-size: 14px;
color: green;
}
.big_error_text {
font-size: 32px;
color: red;
@ -15,3 +25,8 @@
.medium_sized_text {
font-size: 18px;
}
.valid-action {
background-color:green;
color: white;
}

View File

@ -1,26 +1,23 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
use std::io::BufRead;
use std::io::BufReader;
use std::process::Command;
use std::process::Stdio;
use std::time::Instant;
use std::str;
use std::fs;
use std::path::Path;
pub fn timezone_page(content_stack: &gtk::Stack) {
// create the bottom box for next and back buttons
let bottom_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
@ -30,7 +27,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
// Next and back button
let bottom_back_button = gtk::Button::builder()
.label("Back")
.label(gettext("back"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -39,7 +36,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
.hexpand(true)
.build();
let bottom_next_button = gtk::Button::builder()
.label("Next")
.label(gettext("next"))
.margin_top(15)
.margin_bottom(15)
.margin_start(15)
@ -69,7 +66,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
// the header text for the timezone page
let timezone_header_text = gtk::Label::builder()
.label("Select a timezone")
.label(gettext("select_a_timezone"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
@ -81,7 +78,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
// the header icon for the timezone icon
let timezone_header_icon = gtk::Image::builder()
.icon_name("clock")
.icon_name("alarm-clock")
.halign(gtk::Align::Start)
.hexpand(true)
.pixel_size(78)
@ -109,7 +106,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
// text above timezone selection box
let timezone_selection_text = gtk::Label::builder()
.label("Please select a Time Zone for the system to use")
.label(gettext("please_select_timezone"))
.halign(gtk::Align::Center)
.hexpand(true)
.margin_top(15)
@ -120,16 +117,15 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
timezone_selection_text.add_css_class("medium_sized_text");
let timezone_selection_expander_row = adw::ExpanderRow::builder()
.title("No Time Zone selected")
.title(gettext("no_timezone_select"))
.build();
let null_checkbutton = gtk::CheckButton::builder()
.label("No Time Zone selected")
.label(gettext("no_timezone_select"))
.build();
let timezone_selection_expander_row_viewport = gtk::ScrolledWindow::builder()
.height_request(200)
.build();
let timezone_selection_expander_row_viewport =
gtk::ScrolledWindow::builder().height_request(200).build();
let timezone_selection_expander_row_viewport_box = gtk::Box::builder()
.orientation(Orientation::Vertical)
@ -145,7 +141,8 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
timezone_selection_expander_row_viewport_listbox.add_css_class("boxed-list");
timezone_selection_expander_row_viewport_listbox.append(&timezone_selection_expander_row);
timezone_selection_expander_row_viewport.set_child(Some(&timezone_selection_expander_row_viewport_box));
timezone_selection_expander_row_viewport
.set_child(Some(&timezone_selection_expander_row_viewport_box));
timezone_selection_expander_row.add_row(&timezone_selection_expander_row_viewport);
@ -160,7 +157,9 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
.unwrap_or_else(|e| panic!("failed {}", e));
let current_timezone_output = current_timezone_cli.wait_with_output().unwrap();
let current_timezone = str::from_utf8(&current_timezone_output.stdout).unwrap().trim();
let current_timezone = str::from_utf8(&current_timezone_output.stdout)
.unwrap()
.trim();
let timezone_layout_cli = Command::new("timedatectl")
.arg("list-timezones")
@ -172,8 +171,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
let timezone_layout_stdout = timezone_layout_cli.stdout.expect("could not get stdout");
let timezone_layout_reader = BufReader::new(timezone_layout_stdout);
let timezone_data_buffer = gtk::TextBuffer::builder()
.build();
let timezone_data_buffer = gtk::TextBuffer::builder().build();
for timezone_layout in timezone_layout_reader.lines() {
let timezone_layout = timezone_layout.unwrap();
@ -215,7 +213,7 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
// / Content stack appends
//// Add the timezone_main_box as page: timezone_page, Give it nice title
content_stack.add_titled(&timezone_main_box, Some("timezone_page"), "Time Zone");
content_stack.add_titled(&timezone_main_box, Some("timezone_page"), &gettext("timezone"));
let timezone_data_buffer_clone = timezone_data_buffer.clone();
@ -224,10 +222,15 @@ pub fn timezone_page(content_stack: &gtk::Stack) {
fs::remove_file("/tmp/pika-installer-gtk4-timezone.txt").expect("Bad permissions on /tmp/pika-installer-gtk4-timezone.txt");
}
fs::write("/tmp/pika-installer-gtk4-timezone.txt", timezone_data_buffer_clone.text(&timezone_data_buffer_clone.bounds().0, &timezone_data_buffer_clone.bounds().1, true).to_string()).expect("Unable to write file");
Command::new("sudo")
.arg("timedatectl")
.arg("set-timezone")
.arg(&timezone_data_buffer_clone.text(&timezone_data_buffer_clone.bounds().0, &timezone_data_buffer_clone.bounds().1, true).to_string())
.spawn()
.expect("timezone failed to start");
content_stack.set_visible_child_name("keyboard_page")
}));
bottom_back_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("eula_page")
}));
}

View File

@ -1,13 +1,13 @@
// Use libraries
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::prelude::*;
use gtk::*;
use crate::config::DISTRO_ICON;
use adw::prelude::*;
use adw::*;
use glib::*;
use gdk::Display;
use gtk::subclass::layout_child;
/// Use all gtk4 libraries (gtk4 -> gtk because cargo)
/// Use all libadwaita libraries (libadwaita -> adw because cargo)
use gtk::*;
use gettextrs::{gettext};
pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack) {
// the header box for the welcome page
@ -22,7 +22,7 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
// the header text for the welcome page
let welcome_header_text = gtk::Label::builder()
.label("Welcome to PikaOS")
.label(gettext("welcome_to_pikaos"))
.halign(gtk::Align::End)
.hexpand(true)
.margin_top(15)
@ -34,7 +34,7 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
// the header icon for the welcome icon
let welcome_header_icon = gtk::Image::builder()
.icon_name("debian-swirl")
.icon_name(DISTRO_ICON)
.halign(gtk::Align::Start)
.hexpand(true)
.pixel_size(78)
@ -64,7 +64,7 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
.build();
let live_media_button_content_text = gtk::Label::builder()
.label("Use PikaOS in Live media")
.label(gettext("use_pikaos_in_live_media"))
.margin_top(0)
.margin_bottom(15)
.margin_start(15)
@ -86,7 +86,7 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
.build();
let install_media_button_content_text = gtk::Label::builder()
.label("Install Distro to System")
.label(gettext("install_distro_to_system"))
.margin_top(0)
.margin_bottom(15)
.margin_start(15)
@ -102,7 +102,6 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
.valign(gtk::Align::Center)
.build();
let install_media_button = gtk::Button::builder()
.child(&install_media_button_content_box)
.vexpand(true)
@ -143,7 +142,6 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
//// add image and text to the live_media_button
live_media_button_content_box.append(&live_media_button_content_image);
// / welcome_selection_box appends
//// add live and install media button to welcome page selections
welcome_selection_box.append(&live_media_button);
@ -162,7 +160,7 @@ pub fn welcome_page(window: &adw::ApplicationWindow, content_stack: &gtk::Stack)
// / Content stack appends
//// Add the welcome_main_box as page: welcome_page, Give it nice title
content_stack.add_titled(&welcome_main_box, Some("welcome_page"), "Welcome");
content_stack.add_titled(&welcome_main_box, Some("welcome_page"), &gettext("welcome"));
install_media_button.connect_clicked(clone!(@weak content_stack => move |_| content_stack.set_visible_child_name("language_page")));
live_media_button.connect_clicked(clone!(@weak window => move |_| window.close()));