├── .gitignore
├── .gitlab-ci.yml
├── Changelog
├── LICENSE
├── README.md
├── ReleaseNotes
├── TODO
├── backgrounds
├── BlurryBlob.png
├── BlurryBlob.svg
├── BurningDesire.svg
├── Camel.Sunset.svg
├── Christmas.svg
├── Hexagons.svg
├── LayeredBlobsDark.svg
├── LayeredBlobsLight.svg
├── Mountains.Sunset.svg
├── Rectangles.svg
├── Rings.svg
├── Sailboats.svg
├── SmoothGradient.png
├── SmoothGradient.svg
├── Squares.svg
├── Sunrise.svg
├── Tree.svg
└── Water.svg
├── configs
├── config.ini
├── config.toml
├── greetd
├── sway.cfg
├── users.conf
└── wayfire.ini
├── meson.build
├── meson_options.txt
├── screenshots
├── 1.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
└── 5.jpg
├── scripts
├── postinst
└── postrm
├── src
├── Global.hpp
├── Main.cpp
├── QtGreet.qrc
├── backends
│ ├── LoginManager.cpp
│ ├── LoginManager.hpp
│ └── greetd
│ │ ├── GreetdManager.cpp
│ │ └── GreetdManager.hpp
├── compositor
│ ├── main.cpp
│ ├── tinywl.c
│ └── tinywl.h
├── customlogin
│ ├── customlogin.hjson
│ └── customlogin.qss
├── icons
│ ├── QtGreet.png
│ ├── QtGreet.svg
│ ├── acpower.png
│ ├── arrow-down.png
│ ├── arrow-left.png
│ ├── arrow-right.png
│ ├── battery.png
│ ├── edit.png
│ ├── hibernate.png
│ ├── logout.png
│ ├── reboot.png
│ ├── session.png
│ ├── shutdown.png
│ ├── suspend.png
│ └── user.png
├── layoutmanager
│ ├── CMakeLists.txt
│ ├── LayoutManager.cpp
│ ├── LayoutManager.hpp
│ ├── LayoutUtils.cpp
│ ├── LayoutUtils.hpp
│ ├── main.cpp
│ └── parser
│ │ ├── LICENSE
│ │ ├── hjson.h
│ │ ├── hjson_decode.cpp
│ │ ├── hjson_encode.cpp
│ │ ├── hjson_parsenumber.cpp
│ │ └── hjson_value.cpp
├── protocols
│ ├── meson.build
│ ├── wlr-layer-shell-unstable-v1.xml
│ └── xdg-shell.xml
├── thememanager
│ ├── ThemeManager.cpp
│ └── ThemeManager.hpp
├── ui
│ ├── QtGreet.cpp
│ ├── QtGreet.hpp
│ ├── ScreenManager.cpp
│ └── ScreenManager.hpp
└── widgets
│ ├── buttons
│ ├── buttons.cpp
│ └── buttons.hpp
│ ├── clock
│ ├── ClockWidget.cpp
│ └── ClockWidget.hpp
│ ├── container
│ ├── Container.cpp
│ └── Container.hpp
│ ├── factory
│ ├── WidgetFactory.cpp
│ └── WidgetFactory.hpp
│ ├── key
│ ├── labels
│ ├── labels.cpp
│ └── labels.hpp
│ ├── power
│ ├── power.cpp
│ └── power.hpp
│ ├── session
│ ├── session.cpp
│ └── session.hpp
│ ├── user
│ ├── user.cpp
│ └── user.hpp
│ └── videobg
│ ├── MpvHelper.hpp
│ ├── MpvWidget.cpp
│ └── MpvWidget.hpp
└── themes
├── LytMgr.py
├── aerial
├── 4k.m3u
├── all_sd.m3u
├── day.m3u
├── index.theme
├── layout.hjson
├── night.m3u
└── style.qss
├── compact
├── index.theme
├── layout.hjson
└── style.qss
├── default
├── index.theme
├── layout.hjson
└── style.qss
└── sidebar
├── index.theme
├── layout.hjson
└── style.qss
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | .build
3 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | debian_sid_amd64:
2 | stage: build
3 | image: debian:sid
4 | before_script:
5 | - apt-get update -yq
6 | - apt-get install -y g++ git ca-certificates make cmake ninja-build build-essential fakeroot debhelper-compat meson pkg-config
7 | - apt-get install -y cmake qttools5-dev g++ make libarchive-dev liblzma-dev libbz2-dev zlib1g-dev liblz-dev
8 |
9 | script:
10 | - dpkg-buildpackage -rfakeroot -uc -us
11 | - mv ../archiver_2.0.8_amd64.deb ./archiver_2.0.8_sid_amd64.deb
12 | - mv ../libarchiveqt_2.0.8_amd64.deb ./libarchiveqt_2.0.8_sid_amd64.deb
13 | - mv ../libarchiveqt-dev_2.0.8_amd64.deb ./libarchiveqt-dev_2.0.8_sid_amd64.deb
14 |
15 | artifacts:
16 | paths:
17 | - archiver_2.0.8_sid_amd64.deb
18 | - libarchiveqt_2.0.8_sid_amd64.deb
19 | - libarchiveqt-dev_2.0.8_sid_amd64.deb
20 |
21 | debian_testing_amd64:
22 | stage: build
23 | image: debian:testing
24 | before_script:
25 | - apt-get update -yq
26 | - apt-get install -y g++ git ca-certificates make cmake ninja-build build-essential fakeroot debhelper-compat meson pkg-config
27 | - apt-get install -y cmake qttools5-dev g++ make libarchive-dev liblzma-dev libbz2-dev zlib1g-dev liblz-dev
28 |
29 | script:
30 | - dpkg-buildpackage -rfakeroot -uc -us
31 | - mv ../archiver_2.0.8_amd64.deb ./archiver_2.0.8_testing_amd64.deb
32 | - mv ../libarchiveqt_2.0.8_amd64.deb ./libarchiveqt_2.0.8_testing_amd64.deb
33 | - mv ../libarchiveqt-dev_2.0.8_amd64.deb ./libarchiveqt-dev_2.0.8_testing_amd64.deb
34 |
35 | artifacts:
36 | paths:
37 | - archiver_2.0.8_testing_amd64.deb
38 | - libarchiveqt_2.0.8_testing_amd64.deb
39 | - libarchiveqt-dev_2.0.8_testing_amd64.deb
40 |
41 | debian_stable_amd64:
42 | stage: build
43 | image: debian:stable
44 | before_script:
45 | - apt-get update -yq
46 | - apt-get install -y g++ git ca-certificates make cmake ninja-build build-essential fakeroot debhelper-compat meson pkg-config
47 | - apt-get install -y cmake qttools5-dev g++ make libarchive-dev liblzma-dev libbz2-dev zlib1g-dev liblz-dev
48 |
49 | script:
50 | - dpkg-buildpackage -rfakeroot -uc -us
51 | - mv ../archiver_2.0.8_amd64.deb ./archiver_2.0.8_stable_amd64.deb
52 | - mv ../libarchiveqt_2.0.8_amd64.deb ./libarchiveqt_2.0.8_stable_amd64.deb
53 | - mv ../libarchiveqt-dev_2.0.8_amd64.deb ./libarchiveqt-dev_2.0.8_stable_amd64.deb
54 |
55 | artifacts:
56 | paths:
57 | - archiver_2.0.8_stable_amd64.deb
58 | - libarchiveqt_2.0.8_stable_amd64.deb
59 | - libarchiveqt-dev_2.0.8_stable_amd64.deb
60 |
--------------------------------------------------------------------------------
/Changelog:
--------------------------------------------------------------------------------
1 | Version 2.0.0
2 | - Deprecate the use of layer-shell: not all compositors support it, and we do not require it either.
3 | - Show all windows as full-screens, and place them on various screens using the wlr-foreign-toplevel protocol.
4 | - You can customize the appearance of the greeter to your heart's content using themes.
5 | - Some instructions and config files are provided (see the folder configs) to run QtGreet on wayfire and sway.
6 | - Introducing greetwl - a single screen compositor to display QtGreet.
7 | - Inbuilt support for Suspend, Hibernate, Shutdown and Reboot via (e)logind, using DFL::Login1.
8 |
9 | Version 1.0
10 | - Inital Release
11 | - Some working parts
12 | - Few bugs
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # QtGreet
2 |
3 | #### Note: Github is a read-only mirror. You can open PRs and issues at [GitLab](https://gitlab.com/marcusbritanicus/QtGreet.git).
4 |
5 | Qt based greeter for [greetd](https://git.sr.ht/~kennylevinsen/greetd), to be run under wayfire or similar wlr-based compositors.
6 |
7 | Connect with us via [Matrix/IRC](https://app.element.io/#/room/#qtgreet:matrix.org) (#qtgreet:matrix.org)
8 |
9 | 
10 | 
11 |
12 |
13 | ### Dependencies:
14 | - Qt5 or Qt6 (duh...)
15 | - WayQt (https://gitlab.com/desktop-frameworks/wayqt.git)
16 | - DFL::Applications (https://gitlab.com/desktop-frameworks/applications.git)
17 | - DFL::IPC (https://gitlab.com/desktop-frameworks/ipc.git)
18 | - DFL::Utils (https://gitlab.com/desktop-frameworks/utils.git)
19 | - DFL::Login1 (https://gitlab.com/desktop-frameworks/login1.git)
20 | - wlroots (https://gitlab.freedesktop.org/wlroots/wlroots.git)
21 | - A wayland based compositor (wayfire, sway, labwc etc..) - Optional
22 | - Meson (to build this project)
23 | - Ninja (to compile this project)
24 |
25 | **Note:** wlroots is needed only if you are compiling `greetwl`. If you want to skip the compilation of `greetwl`,
26 | pass `-Dbuild_greetwl=false` to `meson`
27 |
28 | ### Compiling and installing
29 |
30 | - Get the sources of QtGreet
31 | * Git: `git clone https://gitlab.com/marcusbritanicus/QtGreet.git`
32 | - Enter the `QtGreet` folder
33 | * `cd QtGreet`
34 | - Configure the project - we use meson for project management
35 | * `meson .build --prefix=/usr --buildtype=release`
36 | - Compile and install - we use ninja
37 | * `ninja -C .build -k 0 -j $(nproc) && sudo ninja -C .build install`
38 |
39 | ### Configure greetd to run QtGreet
40 |
41 | If you wish to make use of greetd, then you will have to configure it to use QtGreet.
42 | You can either use the *inbuilt* `greetwl` compositor (a fork of `tinywl`), or use a full-fledged compositor like wayfire or sway.
43 |
44 | - To use `greetwl` compositor,
45 | * Open `/etc/greetd/config.toml` for editing with your favorite editor.
46 | * Under `[default_session]`, set `command = "greetwl"`
47 |
48 | - To use wayfire,
49 | * Open `/etc/greetd/config.toml` for editing with your favorite editor.
50 | * Under `[default_session]`, set `command = "wayfire --config /etc/qtgreet/wayfire.ini"`
51 |
52 | - Similarly for sway,
53 | * Open `/etc/greetd/config.toml` for editing with your favorite editor.
54 | * Under `[default_session]`, set `command = "sway --config /etc/qtgreet/sway.cfg"`
55 |
56 | - For labwc,
57 | * Open `/etc/greetd/config.toml` for editing with your favorite editor.
58 | * Under `[default_session]`, set `command = "labwc -s 'qtgreet && wayland-logout'"`
59 |
60 | Most compositors print debug messages to the terminal. You can hide them by redirecting the debug output. Add ` > /dev/null 2>&1` at the end of
61 | each command (ex. `command = "greetwl > /dev/null 2>&1"`).
62 |
63 | Custom login prompt can be activated by pressing `[Ctrl] - [Alt] - [X]` key combination.
64 |
65 | ### CLI Options
66 | Following command-line options are available:
67 | ```
68 | -h, --help Displays help on commandline options.
69 | -v, --version Displays version information.
70 | -c, --config Configuration file (Default: /etc/qtgreet/config.ini)
71 | -d, --data-path Path to store dynamic data (Default: /var/lib/qtgreet/)
72 | -w, --wl-session-path Path(s) containing wayland session desktops (Default: /usr/share/wayland-sessions)
73 | -x, --x-session-path Path(s) containing x11 session desktops (Default: /usr/share/xsessions)
74 | -p, --passwd-path Path to passwd (Default: /etc/passwd)
75 | -l, --login-defs-path Path to login.defs (Default: /etc/login.defs)
76 | -r, --xserver-path Path to xserverrc (Default: /etc/X11/xinit/xserverrc)
77 | -t, --tmp-path System temp folder (Default: /tmp)
78 | -n, --vt-number VT number where the session is started (Default: 1; applicable for X11 only)
79 | -o, --log-path Path to store log files (Default: /var/tmp/qtgreet)
80 | ```
81 |
82 | If you're using `greetwl` as the compositor, you can pass these options to `greetwl` which will forward them to `qtgreet`.
83 |
84 | ### Configuring the keyboard layout for wayfire
85 | Sometimes, it would be easier if the keyboard layout was not the default `us`. For wayfire, simply add the following line at the end of
86 | `/etc/qtgreet/wayfire.ini` file:
87 |
88 | ```ini
89 | [input]
90 | xkb_layout = us
91 | ```
92 | ``
93 |
--------------------------------------------------------------------------------
/ReleaseNotes:
--------------------------------------------------------------------------------
1 | Version 2.0
2 | - Deprecate the use of layer-shell: not all compositors support it, and we do not require it either.
3 | - Show all windows as full-screens, and place them on various screens using the wlr-foreign-toplevel protocol.
4 | - You can customize the appearance of the greeter to your heart's content using themes.
5 | - Some instructions and config files are provided (see the folder configs) to run QtGreet on wayfire and sway.
6 | - Introducing greetwl - a single screen compositor to display QtGreet.
7 | - Inbuilt support for Suspend, Hibernate, Shutdown and Reboot via (e)logind, using DFL::Login1.
8 |
9 | Version 1.0
10 | - Wayland sessions run smoothly, Custom sessions can be easily started.
11 | - We still do not have a way to start a new session when an existing session is running.
12 | - We cannot launch an X11 Session.
13 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | QtGreet v2.0.0
2 |
3 | 1. Custom User Icons
4 | We will use ~/.face or ~/.face.icon file to get the user icon failing which we will use the default image.
5 | To make the image have rounded corners use: Use the image as a brush, then draw a rounded rect with no pen.
6 |
7 | 2. QtGreet Widegt Factory
8 | Generate a widget given the name and type. Read the properties, and request the widget to apply the properties by itself.
9 | Following are the list of the widgets:
10 | 1. UserName
11 | 2. SessionName
12 | 3. Password
13 | 4. LoginButton
14 | 5. Date/Time
15 | 6.
16 | 7.
17 | 8.
18 | 9.
19 | 10.
20 |
21 | Every layout.hjson file should contain the first 4 widgets. Without them, you'll not be able to login properly.
22 |
23 | 3. Layout Manager using HJSON
24 | A simple HJSON file with a predefined set of keys will define the layout. We will use QBoxLayout to perform the actual layout of the
25 | widgets. Trials with default and sidebar themes have proved that this method is very effective.
26 |
27 | 4. Decouple GUI from Backends
28 | Currently, the greetd code in integrated with the GUI class. We have to decouple it and use a generic QtGreetBackend class to perform the
29 | various authenticaion/session lauching work.
30 |
31 | 5. Develop Backends
32 | We have to develop two backends, one for QGreetd and the other for LightDM.
33 |
34 | 6. Build a few default themes
35 | Currently, we have the following 4 themes
36 | 1. Default
37 | 2. Aerial
38 | 3. Compact
39 | 4. SideBar
40 |
41 | 7. Write a complete Theme and Layout Guide
42 |
43 | 8. Refactor all the widgets. Currently WidgetFactory applies all the widget properties. Each of the widgets should handle the properties by
44 | themselves.
45 |
--------------------------------------------------------------------------------
/backgrounds/BlurryBlob.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/backgrounds/BlurryBlob.png
--------------------------------------------------------------------------------
/backgrounds/BlurryBlob.svg:
--------------------------------------------------------------------------------
1 |
2 |
239 |
--------------------------------------------------------------------------------
/backgrounds/LayeredBlobsDark.svg:
--------------------------------------------------------------------------------
1 |
2 |
26 |
--------------------------------------------------------------------------------
/backgrounds/LayeredBlobsLight.svg:
--------------------------------------------------------------------------------
1 |
2 |
25 |
--------------------------------------------------------------------------------
/backgrounds/SmoothGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/backgrounds/SmoothGradient.png
--------------------------------------------------------------------------------
/backgrounds/SmoothGradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
23 |
--------------------------------------------------------------------------------
/backgrounds/Water.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/configs/config.ini:
--------------------------------------------------------------------------------
1 | [General]
2 | Backend = GreetD
3 | Theme = default
4 | BlurBackground = true
5 | IconTheme = breeze
6 |
7 | [Overrides]
8 | Background = Theme
9 | BaseColor = Theme
10 | TextColor = Theme
11 | FontFamily = Theme
12 |
13 | [Environment]
14 |
15 | [PowerCommands]
16 | Suspend = dbus
17 | Hibernate = dbus
18 | Shutdown = dbus
19 | Reboot = dbus
20 |
--------------------------------------------------------------------------------
/configs/config.toml:
--------------------------------------------------------------------------------
1 | [terminal]
2 | # The VT to run the greeter on. Can be "next", "current" or a number
3 | # designating the VT.
4 | vt = 7
5 |
6 | # The default session, also known as the greeter.
7 | [default_session]
8 | command = "dbus-run-session wayfire --config /etc/qtgreet/wayfire.ini > /dev/null 2>&1"
9 |
10 | # The user to run the command as. The privileges this user must have depends
11 | # on the greeter. A graphical greeter may for example require the user to be
12 | # in the `video` group.
13 | user = "greeter"
14 |
--------------------------------------------------------------------------------
/configs/greetd:
--------------------------------------------------------------------------------
1 | #%PAM-1.0
2 |
3 | # Block login if they are globally disabled
4 | auth requisite pam_nologin.so
5 | auth required pam_succeed_if.so user != root quiet_success
6 |
7 | # auth sufficient pam_succeed_if.so user ingroup nopasswdlogin
8 | @include common-auth
9 | # gnome_keyring breaks QProcess
10 | auth optional pam_gnome_keyring.so
11 | auth optional pam_kwallet5.so
12 |
13 | @include common-account
14 |
15 | # SELinux needs to be the first session rule. This ensures that any
16 | # lingering context has been cleared. Without this it is possible that a
17 | # module could execute code in the wrong domain.
18 | session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close
19 | # Create a new session keyring.
20 | session optional pam_keyinit.so force revoke
21 | session required pam_limits.so
22 | session required pam_loginuid.so
23 | @include common-session
24 | # SELinux needs to intervene at login time to ensure that the process starts
25 | # in the proper default security context. Only sessions which are intended
26 | # to run in the user's context should be run after this.
27 | session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
28 | session optional pam_gnome_keyring.so auto_start
29 | session optional pam_kwallet5.so auto_start
30 |
31 | @include common-password
32 |
33 | # From the pam_env man page
34 | # Since setting of PAM environment variables can have side effects to other modules, this module should be the last one on the stack.
35 |
36 | # Load environment from /etc/environment
37 | session required pam_env.so
38 |
39 | # Load environment from /etc/default/locale and ~/.pam_environment
40 | session required pam_env.so envfile=/etc/default/locale user_readenv=1
41 |
--------------------------------------------------------------------------------
/configs/sway.cfg:
--------------------------------------------------------------------------------
1 | exec "qtgreet; swaymsg exit"
2 |
3 | bindsym Mod4+shift+e exec swaynag \
4 | -t warning \
5 | -m 'What do you want to do?' \
6 | -b 'Poweroff' 'systemctl poweroff' \
7 | -b 'Reboot' 'systemctl reboot'
8 |
9 | include /etc/sway/config.d/*
10 |
--------------------------------------------------------------------------------
/configs/users.conf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/configs/users.conf
--------------------------------------------------------------------------------
/configs/wayfire.ini:
--------------------------------------------------------------------------------
1 | [autostart]
2 | autostart_wf_shell = false
3 | dm = qtgreet && wayland-logout
4 |
5 | [core]
6 | plugins = autostart
7 | vheight = 1
8 | vwidth = 1
9 | xwayland = false
10 | preferred_decoration_mode = server
11 |
--------------------------------------------------------------------------------
/meson.build:
--------------------------------------------------------------------------------
1 | project(
2 | 'QtGreet',
3 | 'c',
4 | 'cpp',
5 | version: '2.0.0',
6 | license: 'MIT',
7 | meson_version: '>=0.60.0',
8 | default_options: [
9 | 'cpp_std=c++17',
10 | 'c_std=c11',
11 | 'warning_level=2',
12 | 'werror=false',
13 | ],
14 | )
15 |
16 | add_global_arguments( '-DPROJECT_VERSION="v@0@"'.format( meson.project_version() ), language : 'cpp' )
17 | add_project_link_arguments( ['-rdynamic','-fPIC'], language:'cpp' )
18 |
19 | if get_option( 'nodynpath' ) == false
20 | add_global_arguments( '-DDYNPATH="@0@"'.format( get_option( 'dynpath' ) ), language : 'cpp' )
21 | else
22 | add_global_arguments( '-DDYNPATH=""', language : 'cpp' )
23 | endif
24 |
25 | add_global_arguments( '-DLOGPATH="@0@"'.format( get_option( 'logpath' ) ), language : 'cpp' )
26 |
27 | # If use_qt_version is 'auto', we will first search for Qt6.
28 | # If all Qt6 packages are available, we'll use it. Otherwise,
29 | # we'll switch to Qt5.
30 | if get_option('use_qt_version') == 'auto'
31 | # Check if Qt6 is available
32 | QtDeps = dependency( 'qt6', modules: [ 'Core', 'Gui', 'Widgets', 'DBus', 'OpenGLWidgets' ], required: false )
33 | wayqt = dependency( 'wayqt-qt6', required: false )
34 | DFApp = dependency( 'df6application', required: false )
35 | DFIpc = dependency( 'df6ipc', required: false )
36 | DFUtl = dependency( 'df6utils', required: false )
37 | DFLgn = dependency( 'df6login1', required: false )
38 |
39 | Qt6_is_Found = QtDeps.found() and wayqt.found() and DFApp.found() and DFIpc.found() and DFUtl.found() and DFLgn.found()
40 |
41 | if Qt6_is_Found
42 | Qt = import( 'qt6' )
43 |
44 | else
45 | QtDeps = dependency( 'qt5', modules: [ 'Core', 'Gui', 'Widgets', 'DBus' ], required: true )
46 | Qt = import( 'qt5' )
47 |
48 | wayqt = dependency( 'wayqt', required: true )
49 | DFApp = dependency( 'df5application', required: true )
50 | DFIpc = dependency( 'df5ipc', required: true )
51 | DFUtl = dependency( 'df5utils', required: true )
52 | DFLgn = dependency( 'df5login1', required: true )
53 | endif
54 |
55 | # User specifically wants to user Qt5
56 | elif get_option('use_qt_version') == 'qt5'
57 | QtDeps = dependency( 'qt5', modules: [ 'Core', 'Gui', 'Widgets', 'DBus' ], required: true )
58 | Qt = import( 'qt5' )
59 |
60 | wayqt = dependency( 'wayqt', required: true )
61 | DFApp = dependency( 'df5application', required: true )
62 | DFIpc = dependency( 'df5ipc', required: true )
63 | DFUtl = dependency( 'df5utils', required: true )
64 | DFLgn = dependency( 'df5login1', required: true )
65 |
66 | # User specifically wants to user Qt6
67 | elif get_option('use_qt_version') == 'qt6'
68 | QtDeps = dependency( 'qt6', modules: [ 'Core', 'Gui', 'Widgets', 'DBus', 'OpenGLWidgets' ], required: false )
69 | Qt = import( 'qt6' )
70 |
71 | wayqt = dependency( 'wayqt-qt6', required: true )
72 | DFApp = dependency( 'df6application', required: true )
73 | DFIpc = dependency( 'df6ipc', required: true )
74 | DFUtl = dependency( 'df6utils', required: true )
75 | DFLgn = dependency( 'df6login1', required: true )
76 | endif
77 |
78 | # MPV for video bg
79 | Mpv = dependency( 'mpv' )
80 |
81 | Includes = [
82 | 'src',
83 | 'src/backends',
84 | 'src/backends/greetd',
85 | 'src/layoutmanager',
86 | 'src/layoutmanager/parser',
87 | 'src/thememanager',
88 | 'src/ui',
89 | 'src/widgets',
90 | 'src/widgets/buttons',
91 | 'src/widgets/clock',
92 | 'src/widgets/container',
93 | 'src/widgets/labels',
94 | 'src/widgets/power',
95 | 'src/widgets/session',
96 | 'src/widgets/user',
97 | 'src/widgets/videobg',
98 | 'src/widgets/factory',
99 | ]
100 |
101 | Headers = [
102 | 'src/Global.hpp',
103 | 'src/backends/LoginManager.hpp',
104 | 'src/backends/greetd/GreetdManager.hpp',
105 | 'src/layoutmanager/parser/hjson.h',
106 | 'src/layoutmanager/LayoutManager.hpp',
107 | 'src/layoutmanager/LayoutUtils.hpp',
108 | 'src/thememanager/ThemeManager.hpp',
109 | 'src/ui/QtGreet.hpp',
110 | 'src/ui/ScreenManager.hpp',
111 | 'src/widgets/factory/WidgetFactory.hpp',
112 | 'src/widgets/buttons/buttons.hpp',
113 | 'src/widgets/clock/ClockWidget.hpp',
114 | 'src/widgets/container/Container.hpp',
115 | 'src/widgets/labels/labels.hpp',
116 | 'src/widgets/power/power.hpp',
117 | 'src/widgets/session/session.hpp',
118 | 'src/widgets/user/user.hpp',
119 | 'src/widgets/videobg/MpvWidget.hpp',
120 | 'src/widgets/videobg/MpvHelper.hpp',
121 | ]
122 |
123 | Sources = [
124 | 'src/backends/LoginManager.cpp',
125 | 'src/backends/greetd/GreetdManager.cpp',
126 | 'src/layoutmanager/LayoutManager.cpp',
127 | 'src/layoutmanager/LayoutUtils.cpp',
128 | 'src/layoutmanager/parser/hjson_decode.cpp',
129 | 'src/layoutmanager/parser/hjson_encode.cpp',
130 | 'src/layoutmanager/parser/hjson_parsenumber.cpp',
131 | 'src/layoutmanager/parser/hjson_value.cpp',
132 | 'src/thememanager/ThemeManager.cpp',
133 | 'src/Main.cpp',
134 | 'src/ui/QtGreet.cpp',
135 | 'src/ui/ScreenManager.cpp',
136 | 'src/widgets/factory/WidgetFactory.cpp',
137 | 'src/widgets/buttons/buttons.cpp',
138 | 'src/widgets/clock/ClockWidget.cpp',
139 | 'src/widgets/container/Container.cpp',
140 | 'src/widgets/labels/labels.cpp',
141 | 'src/widgets/power/power.cpp',
142 | 'src/widgets/session/session.cpp',
143 | 'src/widgets/user/user.cpp',
144 | 'src/widgets/videobg/MpvWidget.cpp',
145 | ]
146 |
147 | Mocs = Qt.compile_moc(
148 | headers : Headers,
149 | dependencies: QtDeps
150 | )
151 |
152 | Resources = Qt.compile_resources(
153 | name: 'QtGreetRes',
154 | sources: 'src/QtGreet.qrc'
155 | )
156 |
157 | qtgreet = executable(
158 | 'qtgreet', [ Sources, Mocs, Resources ],
159 | dependencies: [ QtDeps, wayqt, DFApp, DFIpc, DFUtl, DFLgn, Mpv ],
160 | include_directories: [ Includes ],
161 | install: true
162 | )
163 |
164 | if ( get_option( 'build_greetwl' ) == true )
165 | # Required for greetwl
166 | wlr = dependency( 'wlroots', version: '>= 0.17.0' )
167 | wayland_server = dependency( 'wayland-server' )
168 | wayland_client = dependency( 'wayland-client' )
169 | xkbcommon = dependency( 'xkbcommon' )
170 | rt = meson.get_compiler( 'cpp' ).find_library( 'rt' )
171 |
172 | subdir( 'src/protocols' )
173 |
174 | greetwl = executable(
175 | 'greetwl', [ 'src/compositor/main.cpp', 'src/compositor/tinywl.c' ],
176 | dependencies: [ QtDeps, wlr, wayland_server, wayland_client, xkbcommon, rt, protos ],
177 | include_directories: [ 'src/compositor' ],
178 | install: true
179 | )
180 | endif
181 |
182 | # Backgrounds
183 | install_subdir(
184 | 'backgrounds',
185 | install_dir : get_option( 'datadir' ) / 'qtgreet'
186 | )
187 |
188 | # Backgrounds
189 | install_subdir(
190 | 'themes',
191 | install_dir : get_option( 'datadir' ) / 'qtgreet'
192 | )
193 |
194 | # Readme, Changelog, etc
195 | install_data(
196 | [ 'README.md', 'Changelog', 'ReleaseNotes' ],
197 | install_dir : get_option( 'datadir' ) / 'qtgreet'
198 | )
199 |
200 | # Configuration files
201 | install_data(
202 | [ 'configs/config.ini', 'configs/wayfire.ini', 'configs/users.conf', 'configs/sway.cfg' ],
203 | install_dir : join_paths( get_option( 'sysconfdir' ), 'qtgreet' )
204 | )
205 |
206 | # Icons
207 | install_data(
208 | 'src/icons/QtGreet.svg',
209 | install_dir : join_paths(get_option('prefix'), 'share', 'icons', 'hicolor', 'scalable', 'apps'),
210 | )
211 |
212 | install_data(
213 | 'src/icons/QtGreet.png',
214 | install_dir : join_paths(get_option('prefix'), 'share', 'icons', 'hicolor', '512x512', 'apps'),
215 | )
216 |
217 | # Configuration file path: create it only if it's not disabled
218 | if get_option( 'nodynpath' ) == false
219 | install_emptydir(
220 | get_option( 'dynpath' ),
221 | install_mode: [ 'rwxr-xr-x', get_option( 'username' ), get_option( 'username' ) ],
222 | )
223 | endif
224 |
225 | summary = [
226 | '',
227 | '--------------',
228 | 'QtGreet v@0@'.format( meson.project_version() ),
229 | '--------------',
230 | ''
231 | ]
232 | message( '\n'.join( summary ) )
233 |
--------------------------------------------------------------------------------
/meson_options.txt:
--------------------------------------------------------------------------------
1 | option(
2 | 'use_qt_version',
3 | type: 'combo',
4 | choices: ['auto', 'qt5', 'qt6'],
5 | value: 'auto',
6 | description: 'Select the Qt version to use'
7 | )
8 |
9 | option(
10 | 'build_greetwl',
11 | type: 'boolean',
12 | value: true,
13 | description: 'Build greetwl compositor'
14 | )
15 |
16 | option(
17 | 'dynpath',
18 | type: 'string',
19 | value: '/var/lib/qtgreet',
20 | description: 'Location where dynamic data can be stored',
21 | )
22 |
23 | option(
24 | 'username',
25 | type: 'string',
26 | value: 'greeter',
27 | description: 'Set the username',
28 | )
29 |
30 | option(
31 | 'nodynpath',
32 | type: 'boolean',
33 | value: false,
34 | description: 'Don\'t create the dynpath directory',
35 | )
36 |
37 | option(
38 | 'logpath',
39 | type: 'string',
40 | value: '/var/tmp/qtgreet',
41 | description: 'Location where user session logs can be stored',
42 | )
43 |
--------------------------------------------------------------------------------
/screenshots/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/screenshots/1.jpg
--------------------------------------------------------------------------------
/screenshots/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/screenshots/2.jpg
--------------------------------------------------------------------------------
/screenshots/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/screenshots/3.jpg
--------------------------------------------------------------------------------
/screenshots/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/screenshots/4.jpg
--------------------------------------------------------------------------------
/screenshots/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/screenshots/5.jpg
--------------------------------------------------------------------------------
/scripts/postinst:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 | /bin/egrep -i "^greeter:" /etc/passwd
5 | if [ $? -neq 0 ]; then
6 | # Create the system user: greeter
7 | useradd -r -M -G video greeter
8 | fi
9 |
10 | # Create the default
11 | chown -R greeter:greeter /etc/xdg/greetd/
12 | chown -R greeter:greeter /etc/xdg/qtgreet/
13 |
14 | # Enable greetd as the display manager - we need it
15 | systemctl enable greetd
16 |
--------------------------------------------------------------------------------
/scripts/postrm:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Delete the system user: greeter
4 | userdel -d greeter
5 |
6 | # Create the default
7 | rm -rf /etc/greetd/ /etc/qtgreet
8 | rm /etc/systemd/system/greetd.service
9 |
10 | # Enable greetd as the display manager
11 | systemctl disable greetd
12 |
--------------------------------------------------------------------------------
/src/Global.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | /** Multiple classes require these */
28 | extern QSettings *sett;
29 | extern QSettings *users;
30 |
31 | extern QString configPath;
32 | extern QString dynDataPath;
33 |
34 | extern QString wlSessPath;
35 | extern QString xSessPath;
36 |
37 | extern QString passwdPath;
38 | extern QString loginPath;
39 |
40 | extern QString xrcPath;
41 | extern QString tmpPath;
42 |
43 | extern QString vtNum;
44 | extern QString logPath;
45 |
46 | extern QString themeName;
47 |
48 | extern QMap paths;
49 |
--------------------------------------------------------------------------------
/src/QtGreet.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icons/arrow-down.png
4 | icons/arrow-left.png
5 | icons/arrow-right.png
6 | icons/session.png
7 | icons/user.png
8 | icons/edit.png
9 | icons/battery.png
10 | icons/acpower.png
11 | icons/shutdown.png
12 | icons/reboot.png
13 | icons/suspend.png
14 | icons/hibernate.png
15 | icons/logout.png
16 | icons/QtGreet.png
17 |
18 | customlogin/customlogin.hjson
19 | customlogin/customlogin.qss
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/backends/LoginManager.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include "LoginManager.hpp"
22 |
23 | LoginManager::LoginManager() {
24 | /** Nothing much */
25 | }
26 |
--------------------------------------------------------------------------------
/src/backends/LoginManager.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include "Global.hpp"
24 |
25 | class LoginManager : public QObject {
26 | Q_OBJECT;
27 |
28 | public:
29 | LoginManager();
30 |
31 | /** Make an attempt to authenticate the user @user using the password @passwd */
32 | virtual bool authenticate( QString user, QString passwd ) = 0;
33 |
34 | /** User authentication was successful. Try to start the session */
35 | virtual bool startSession( QString command, QString type ) = 0;
36 |
37 | /**
38 | * If authenticate/startSession failed, retrieve the error message.
39 | * The error message will be reset if another command is issued.
40 | */
41 | virtual QString errorMessage() = 0;
42 | };
43 |
--------------------------------------------------------------------------------
/src/backends/greetd/GreetdManager.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include "LoginManager.hpp"
24 |
25 | class Response {
26 | public:
27 | enum Type {
28 | Invalid = 0, /* Response was invalid */
29 | Success = 1, /* Request was a success */
30 | Error = 2, /* Request failed */
31 | AuthMessage = 3, /* Request succeeded, auth required */
32 | };
33 |
34 | enum AuthType {
35 | AuthTypeInvalid = 0, /* Not an Authentication Response */
36 | AuthTypeVisible = 1, /* Authentication in visible form */
37 | AuthTypeSecret = 2, /* Authentication in secret form */
38 | AuthTypeInfo = 3, /* Authentication request was Information */
39 | AuthTypeError = 4, /* Authentication failed */
40 | };
41 |
42 | enum ErrorType {
43 | ErrorTypeNone = 0, /* No Error */
44 | ErrorTypeGeneric = 1, /* Generic error */
45 | ErrorTypeAuthError = 2, /* Authentication error, typically bad credentials */
46 | };
47 |
48 | /** We will be given a json string. Parse it */
49 | Response( QByteArray );
50 |
51 | /** Get the response from greetd server */
52 | Response::Type responseType();
53 |
54 | /**
55 | * Auth type and message
56 | * If responseType() != Response::Type::AuthMessage,
57 | * authType() will return AuthTypeNone and authMessage()
58 | * will return empty string.
59 | */
60 | Response::AuthType authType();
61 | QString authMessage();
62 |
63 | /**
64 | * Error type and message
65 | * If responseType() != Response::Type::Error,
66 | * errorType() will return ErrorTypeNone and errorMessage()
67 | * will return empty string.
68 | */
69 | Response::ErrorType errorType();
70 | QString errorMessage();
71 |
72 | private:
73 | Response::Type mType = Invalid;
74 | Response::AuthType mAuthType = AuthTypeInvalid;
75 | Response::ErrorType mErrorType = ErrorTypeNone;
76 |
77 | QString mAuthMsg;
78 | QString mErrorMsg;
79 | };
80 |
81 | class GreetdLogin : public LoginManager {
82 | Q_OBJECT;
83 |
84 | public:
85 | GreetdLogin();
86 |
87 | virtual bool authenticate( QString user, QString passwd ) override;
88 | virtual bool startSession( QString command, QString type ) override;
89 | virtual QString errorMessage() override;
90 |
91 | private:
92 | /** Send create_session message to greetd-ipc */
93 | Response createSession( QString username );
94 |
95 | /** Send post_auth_message_response message to greetd-ipc */
96 | Response postResponse( QString response = QString() );
97 |
98 | /** Send start_session message to greetd-ipc */
99 | Response startSession( QString cmd, QStringList );
100 |
101 | /** Send cancel_session message to greetd-ipc */
102 | Response cancelSession();
103 |
104 | bool connectToServer();
105 | QByteArray roundtrip( QByteArray );
106 |
107 | /** Get the X11 Session String */
108 | QString getX11Session( QString command );
109 |
110 | /** Prepare the environment variables */
111 | QStringList prepareEnv();
112 |
113 | /** GreetD socket FD */
114 | int mFD = -1;
115 |
116 | /** Error message */
117 | QString mErrorMsg;
118 | };
119 |
--------------------------------------------------------------------------------
/src/compositor/main.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include
27 |
28 | extern "C" {
29 | #include "tinywl.h"
30 | }
31 |
32 | TinyWlServer *server = NULL;
33 |
34 | static const char *COLOR_WARN = "\033[01;33m";
35 | static const char *COLOR_CRITICAL = "\033[01;31m";
36 | static const char *COLOR_FATAL = "\033[01;41m";
37 | static const char *COLOR_RESET = "\033[00;00m";
38 |
39 | void handleSignals( int signum ) {
40 | switch ( signum ) {
41 | case SIGINT: {
42 | printf( "%sInterrupt signalled.%s\n", COLOR_WARN, COLOR_RESET );
43 | break;
44 | }
45 |
46 | case SIGTERM: {
47 | printf( "%sPolite term request received.%s\n", COLOR_WARN, COLOR_RESET );
48 | break;
49 | }
50 |
51 | case SIGQUIT: {
52 | printf( "%sSigQuit received.%s\n", COLOR_WARN, COLOR_RESET );
53 | break;
54 | }
55 |
56 | default: {
57 | return;
58 | }
59 | }
60 |
61 | printf( "%sClosing down the server.%s\n", COLOR_CRITICAL, COLOR_RESET );
62 | haltWlEventLoop();
63 | }
64 |
65 |
66 | static void startQtGreet( int argc, char *argv[] ) {
67 | QCoreApplication app( argc, argv );
68 |
69 | QProcess *proc = new QProcess();
70 |
71 | QObject::connect(
72 | proc, &QProcess::readyReadStandardError, [ = ] () {
73 | /** Redirect the stderr of qtgreet to our stderr */
74 | qDebug() << proc->readAllStandardError().trimmed().data();
75 | }
76 | );
77 |
78 | QObject::connect(
79 | proc, &QProcess::readyReadStandardOutput, [ = ] () {
80 | /** Redirect the stdout of qtgreet to our stderr */
81 | qDebug() << proc->readAllStandardOutput().trimmed().data();
82 | }
83 | );
84 |
85 | /**
86 | * Pass the arguments sent to greetwl to qtgreet.
87 | * This way we can quite easily use the cli args of qtgreet while using greetwl
88 | */
89 | proc->start( "qtgreet", app.arguments().mid( 1 ) );
90 | proc->waitForFinished( -1 );
91 | }
92 |
93 |
94 | int main( int argc, char **argv ) {
95 | /** Init TinyWlServer */
96 | server = new TinyWlServer();
97 |
98 | /** Start the compositor */
99 | if ( !startCompositor() ) {
100 | printf( "%sFailed to start TinyWL Compositor%s\n", COLOR_FATAL, COLOR_RESET );
101 | return -1;
102 | }
103 |
104 | /** Setup the environment variables for Qt to start properly */
105 | setupEnv();
106 |
107 | if ( fork() == 0 ) {
108 | startQtGreet( argc, argv );
109 |
110 | /** Request the parent to shutdown */
111 | kill( getppid(), SIGTERM );
112 | }
113 |
114 | signal( SIGINT, handleSignals );
115 | signal( SIGTERM, handleSignals );
116 | signal( SIGQUIT, handleSignals );
117 |
118 | /** Run the wayland event loop instead of QApplication. Will this work? */
119 | runWlEventLoop();
120 |
121 | closeCompositor();
122 |
123 | delete server;
124 |
125 | return 0;
126 | }
127 |
--------------------------------------------------------------------------------
/src/compositor/tinywl.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | enum tinywl_cursor_mode {
28 | TINYWL_CURSOR_PASSTHROUGH,
29 | TINYWL_CURSOR_MOVE,
30 | TINYWL_CURSOR_RESIZE,
31 | };
32 |
33 | typedef struct tinywl_server {
34 | struct wl_display *display;
35 | struct wlr_backend *backend;
36 | struct wlr_session *session;
37 | struct wlr_renderer *renderer;
38 | struct wlr_allocator *allocator;
39 | struct wlr_scene *scene;
40 |
41 | struct wlr_xdg_shell *xdg_shell;
42 | struct wl_listener new_xdg_surface;
43 | struct wl_list views;
44 |
45 | struct wlr_cursor *cursor;
46 | struct wlr_xcursor_manager *cursor_mgr;
47 | struct wl_listener cursor_motion;
48 | struct wl_listener cursor_motion_absolute;
49 | struct wl_listener cursor_button;
50 | struct wl_listener cursor_axis;
51 | struct wl_listener cursor_frame;
52 |
53 | struct wlr_seat *seat;
54 | struct wl_listener new_input;
55 | struct wl_listener request_cursor;
56 | struct wl_listener request_set_selection;
57 | struct wl_list keyboards;
58 | enum tinywl_cursor_mode cursor_mode;
59 | struct tinywl_view *grabbed_view;
60 | double grab_x, grab_y;
61 | struct wlr_box grab_geobox;
62 | uint32_t resize_edges;
63 |
64 | struct wlr_output_layout *output_layout;
65 | struct wl_list outputs;
66 | struct wl_listener new_output;
67 | } TinyWlServer;
68 |
69 | struct tinywl_output {
70 | struct wl_list link;
71 | struct tinywl_server *server;
72 | struct wlr_output *wlr_output;
73 | struct wl_listener frame;
74 | struct wl_listener destroy;
75 | };
76 |
77 | struct tinywl_view {
78 | struct wl_list link;
79 | struct tinywl_server *server;
80 | struct wlr_xdg_toplevel *xdg_toplevel;
81 | struct wlr_scene_tree *scene_tree;
82 | struct wl_listener map;
83 | struct wl_listener unmap;
84 | struct wl_listener destroy;
85 | struct wl_listener request_move;
86 | struct wl_listener request_resize;
87 | struct wl_listener request_maximize;
88 | struct wl_listener request_fullscreen;
89 | int x, y;
90 | };
91 |
92 | struct tinywl_keyboard {
93 | struct wl_list link;
94 | struct tinywl_server *server;
95 | struct wlr_keyboard *wlr_keyboard;
96 |
97 | struct wl_listener modifiers;
98 | struct wl_listener key;
99 | struct wl_listener destroy;
100 | };
101 |
102 | /** Start the tinywl compositor */
103 | int startCompositor();
104 |
105 | /** Start the wayland event loop */
106 | void runWlEventLoop();
107 |
108 | /** Halt the wayland event loop */
109 | void haltWlEventLoop();
110 |
111 | /** Close compositor: sends the terminate signal */
112 | void closeCompositor();
113 |
114 | /**
115 | * Setup the environment to start QtGreet.
116 | * Set XCURSOR_THEME
117 | * Set XCURSOR_SIZE
118 | * Set QT_QPA_PLATFORM
119 | * Set QT_SCALE_FACTOR
120 | */
121 | void setupEnv();
122 |
123 | extern TinyWlServer *server;
124 |
--------------------------------------------------------------------------------
/src/customlogin/customlogin.hjson:
--------------------------------------------------------------------------------
1 | {
2 | Layout: {
3 | Direction: Vertical
4 | Keys: [ "C1" ]
5 | C1: [ "C2" ]
6 | C2: [ "R1", "R2", "R3", "R4", "Stretch", "R5" ]
7 | R1: [ "QLabel-1", "UserName" ]
8 | R2: [ "QLabel-2", "Password" ]
9 | R3: [ "QLabel-3" ]
10 | R4: [ "QLabel-4", "SessionEdit" ]
11 | R5: [ "Stretch", "Button", "LoginButton" ]
12 | Margins: 0.25
13 | Spacing: 10
14 | }
15 |
16 | Properties: {
17 | C1: {
18 | Height: 1.0
19 | Width: 1.0
20 | BGColor: {
21 | Red: 0.0
22 | Green: 0.0
23 | Blue: 0.0
24 | Alpha: 0.25
25 | }
26 | }
27 |
28 | C2: {
29 | Height: 0.15
30 | Width: 0.3
31 | Margins: 0.05
32 | Spacing: 10
33 | BGColor: {
34 | Red: 0.0
35 | Green: 0.0
36 | Blue: 0.0
37 | Alpha: 0.72
38 | }
39 | }
40 |
41 | R1: {
42 | Height: 36
43 | }
44 |
45 | R2: {
46 | Height: 36
47 | }
48 |
49 | R3: {
50 | Height: 36
51 | }
52 |
53 | R4: {
54 | Height: 36
55 | }
56 |
57 | R5: {
58 | Height: 36
59 | Spacing: 10
60 | }
61 |
62 | QLabel-1: {
63 | Text: "Username:"
64 | }
65 |
66 | QLabel-2: {
67 | Text: "Password:"
68 | }
69 |
70 | QLabel-3: {
71 | Text:
72 | }
73 |
74 | QLabel-4: {
75 | Text: "Session:"
76 | }
77 |
78 | UserName: {
79 | Type: LineEdit
80 | Width: 0.18
81 | Height: 36
82 | TextAlign: Center
83 | },
84 |
85 | Password: {
86 | Width: 0.18
87 | Height: 36
88 | },
89 |
90 | Button: {
91 | Width: 36
92 | Height: 36
93 | Type: ToolButton
94 | ObjectName: BackButton
95 | TextAlign: Center
96 | IconSize: 24
97 | ThemeIcon: arrow-left
98 | },
99 |
100 | LoginButton: {
101 | Width: 150
102 | Height: 36
103 | Type: PushButton
104 | ObjectName: CustomLogin
105 | TextAlign: Center
106 | IconSize: 16
107 | },
108 |
109 | SessionEdit: {
110 | Width: 0.18
111 | Height: 36
112 | TextAlign: Center
113 | },
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/customlogin/customlogin.qss:
--------------------------------------------------------------------------------
1 | QWidget {
2 | color: #ffffff;
3 | }
4 |
5 | #CustomLogin {
6 | border: 1px solid gray;
7 | border-radius: 18px;
8 | }
9 |
10 | #CustomLogin:hover {
11 | background-color: rgba(255, 255, 255, 30);
12 | border: 1px solid cornflowerblue;
13 | border-radius: 18px;
14 | }
15 |
16 | #CustomLogin:pressed {
17 | background-color: rgba(255, 255, 255, 10);
18 | padding-top: 1px;
19 | padding-left: 1px;
20 | border: 2px solid cornflowerblue;
21 | border-radius: 18px;
22 | }
23 |
24 | #CustomLogin:focus {
25 | border: 2px solid cornflowerblue;
26 | border-radius: 18px;
27 | }
28 |
29 | #BackButton:focus {
30 | border: 2px solid cornflowerblue;
31 | border-radius: 18px;
32 | }
33 |
34 | #BackButton:hover {
35 | background-color: rgba(255, 255, 255, 30);
36 | border-radius: 18px;
37 | }
38 |
39 | #BackButton:pressed {
40 | background-color: rgba(255, 255, 255, 10);
41 | padding-top: 2px;
42 | padding-left: 2px;
43 | border-radius: 18px;
44 | }
45 |
46 | #CustomLogin:focus {
47 | border: 1px solid cornflowerblue;
48 | border-radius: 18px;
49 | }
50 |
51 | #BackButton {
52 | border: 1px solid gray;
53 | border-radius: 18px;
54 | padding-top: 1px;
55 | padding-left: 1px;
56 | }
57 |
58 | QLineEdit {
59 | background-color: transparent;
60 | border: 1px solid gray;
61 | border-radius: 18px;
62 | padding-left: 10px;
63 | padding-right: 10px;
64 | }
65 |
66 | QLineEdit:focus {
67 | border: 2px solid cornflowerblue;
68 | }
69 |
70 | QLineEdit:edit-focus {
71 | border: 2px solid cornflowerblue;
72 | }
73 |
74 | #OverLay {
75 | background-color: rgba(10, 10, 10, 250);
76 | }
77 |
--------------------------------------------------------------------------------
/src/icons/QtGreet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/QtGreet.png
--------------------------------------------------------------------------------
/src/icons/acpower.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/acpower.png
--------------------------------------------------------------------------------
/src/icons/arrow-down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/arrow-down.png
--------------------------------------------------------------------------------
/src/icons/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/arrow-left.png
--------------------------------------------------------------------------------
/src/icons/arrow-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/arrow-right.png
--------------------------------------------------------------------------------
/src/icons/battery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/battery.png
--------------------------------------------------------------------------------
/src/icons/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/edit.png
--------------------------------------------------------------------------------
/src/icons/hibernate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/hibernate.png
--------------------------------------------------------------------------------
/src/icons/logout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/logout.png
--------------------------------------------------------------------------------
/src/icons/reboot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/reboot.png
--------------------------------------------------------------------------------
/src/icons/session.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/session.png
--------------------------------------------------------------------------------
/src/icons/shutdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/shutdown.png
--------------------------------------------------------------------------------
/src/icons/suspend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/suspend.png
--------------------------------------------------------------------------------
/src/icons/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcusbritanicus/QtGreet/35ff6aa1b44e1c3f52b920c619b171bc8a5ee1df/src/icons/user.png
--------------------------------------------------------------------------------
/src/layoutmanager/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project( LytParser )
2 |
3 | cmake_minimum_required(VERSION 3.10)
4 |
5 | set( CMAKE_CXX_STANDARD 17 )
6 | set( CMAKE_INCLUDE_CURRENT_DIR ON )
7 | set( CMAKE_BUILD_TYPE Release )
8 |
9 | add_definitions ( -Wall )
10 |
11 | set( CMAKE_AUTOMOC ON )
12 | set( CMAKE_AUTORCC ON )
13 | set( CMAKE_AUTOUIC ON )
14 | cmake_policy( SET CMP0071 NEW )
15 |
16 | find_package ( Qt5Widgets REQUIRED )
17 | find_package ( Qt5Core REQUIRED )
18 | find_package ( Qt5Gui REQUIRED )
19 |
20 | include_directories(
21 | parser
22 | ../widgetfactory
23 | )
24 |
25 | set ( SRCS
26 | ../widgetfactory/WidgetFactory.cpp
27 | ../widgetfactory/WidgetFactory.hpp
28 | parser/hjson_decode.cpp
29 | parser/hjson_encode.cpp
30 | parser/hjson_parsenumber.cpp
31 | parser/hjson_value.cpp
32 | LayoutManager.cpp
33 | LayoutManager.hpp
34 | main.cpp
35 | )
36 |
37 | add_executable( parser ${SRCS} )
38 | target_link_libraries( parser Qt5::Core Qt5::Gui Qt5::Widgets )
39 |
--------------------------------------------------------------------------------
/src/layoutmanager/LayoutManager.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 |
23 | #include "LayoutManager.hpp"
24 | #include "WidgetFactory.hpp"
25 |
26 | #include "Container.hpp"
27 | #include "LayoutUtils.hpp"
28 |
29 | QtGreet::LayoutManager::LayoutManager( QScreen *scrn ) {
30 | mScreenSize = scrn->size();
31 | }
32 |
33 |
34 | QBoxLayout * QtGreet::LayoutManager::generateLayout( QString lytFile ) {
35 | Hjson::Value layout;
36 |
37 | /** Simple hack to load customlogin.hjson */
38 | if ( lytFile.startsWith( ":/" ) ) {
39 | QFile hjson( lytFile );
40 | hjson.open( QFile::ReadOnly );
41 | layout = Hjson::Unmarshal( QString::fromUtf8( hjson.readAll() ).toStdString() );
42 | hjson.close();
43 | }
44 |
45 | /** Other files */
46 | else {
47 | layout = Hjson::UnmarshalFromFile( lytFile.toStdString() );
48 | }
49 |
50 | mLayout = layout[ "Layout" ];
51 | mProperties = layout[ "Properties" ];
52 |
53 | Hjson::Value layoutItems( mLayout[ "Keys" ] );
54 |
55 | /** Do we have a row? If yes, we will be expanding the size vertically */
56 | QRegularExpression rows = QRegularExpression( "^R[0-9]+$" );
57 |
58 | /** Do we have a column? If yes, we will be expanding the size horizontally */
59 | QRegularExpression cols = QRegularExpression( "^C[0-9]+$" );
60 |
61 | QBoxLayout *topLyt;
62 |
63 | /** Vertical Layout */
64 | if ( mLayout[ "Direction" ].to_string() == "Vertical" ) {
65 | topLyt = new QBoxLayout( QBoxLayout::TopToBottom );
66 | }
67 |
68 | else {
69 | topLyt = new QBoxLayout( QBoxLayout::LeftToRight );
70 | }
71 |
72 | topLyt->setContentsMargins( getMargins( mLayout[ "Margins" ], mScreenSize ) );
73 | topLyt->setSpacing( getSpacing( mLayout[ "Spacing" ], mScreenSize ) );
74 |
75 | topLyt->setGeometry( QRect( QPoint( 0, 0 ), mScreenSize ) );
76 |
77 | for ( int idx = 0; idx < (int)layoutItems.size(); ++idx ) {
78 | QString key( layoutItems[ idx ].to_string().c_str() );
79 |
80 | /** Vertical Layout: Each key will lead to new rows */
81 | if ( rows.match( key ).hasMatch() ) {
82 | Hjson::Value row = mLayout[ key.toUtf8().data() ];
83 | topLyt->addWidget( addRow( row, key, mProperties[ key.toStdString() ] ) );
84 | }
85 |
86 | /** Horizontal Layout: Each key will lead to new columns */
87 | else if ( cols.match( key ).hasMatch() ) {
88 | Hjson::Value col = mLayout[ key.toUtf8().data() ];
89 | topLyt->addWidget( addColumn( col, key, mProperties[ key.toStdString() ] ) );
90 | }
91 |
92 | /** Should not have come here */
93 | else {
94 | return topLyt;
95 | }
96 | }
97 |
98 | return topLyt;
99 | }
100 |
101 |
102 | QWidget * QtGreet::LayoutManager::addRow( Hjson::Value row, QString name, Hjson::Value props ) {
103 | /** Do we have a row? If yes, we will be expanding the size vertically */
104 | QRegularExpression rows = QRegularExpression( "^R[0-9]+$" );
105 | /** Do we have a column? If yes, we will be expanding the size horizontally */
106 | QRegularExpression cols = QRegularExpression( "^C[0-9]+$" );
107 |
108 | QBoxLayout *lyt = new QBoxLayout( QBoxLayout::LeftToRight );
109 |
110 | lyt->setContentsMargins( getMargins( props[ "Margins" ], mScreenSize ) );
111 | lyt->setSpacing( getSpacing( props[ "Spacing" ], mScreenSize ) );
112 |
113 | double height = getHeight( props[ "Height" ], mScreenSize );
114 |
115 | if ( height ) {
116 | if ( height < 1.0 ) {
117 | lyt->addStrut( height * mScreenSize.height() );
118 | }
119 |
120 | else {
121 | lyt->addStrut( (int)height );
122 | }
123 | }
124 |
125 | for ( int idx = 0; idx < (int)row.size(); ++idx ) {
126 | QString key( row[ idx ].to_string().c_str() );
127 | Hjson::Value properties( mProperties[ key.toStdString() ] );
128 |
129 | /** Vertical Layout: Each key will leat to new rows */
130 | if ( rows.match( key ).hasMatch() ) {
131 | Hjson::Value row = mLayout[ key.toUtf8().data() ];
132 | lyt->addWidget( addRow( row, key, properties ) );
133 | }
134 |
135 | /** Horizontal Layout: Each key will leat to new columns */
136 | else if ( cols.match( key ).hasMatch() ) {
137 | Hjson::Value col = mLayout[ key.toUtf8().data() ];
138 | lyt->addWidget( addColumn( col, key, properties ) );
139 | }
140 |
141 | /** Initialize the widget */
142 | else {
143 | if ( key == "Stretch" ) {
144 | lyt->addStretch();
145 | continue;
146 | }
147 |
148 | /** We can have multiple widgets with same name (ex: Clock(Time), Clock(Date)) */
149 | QString widget = key.split( "-" ).at( 0 );
150 |
151 | QWidget *w = WidgetFactory::createWidget( widget, getType( properties[ "Type" ] ), properties, mScreenSize );
152 | lyt->addWidget( w, 0, getAlignment( props[ "Alignment" ] ) );
153 | }
154 | }
155 |
156 | Container *cw = new Container( props[ "BGColor" ], name );
157 |
158 | cw->setLayout( lyt );
159 |
160 | return cw;
161 | }
162 |
163 |
164 | QWidget * QtGreet::LayoutManager::addColumn( Hjson::Value col, QString name, Hjson::Value props ) {
165 | /** Do we have a row? If yes, we will be expanding the size vertically */
166 | QRegularExpression rows = QRegularExpression( "^R[0-9]+$" );
167 | /** Do we have a column? If yes, we will be expanding the size horizontally */
168 | QRegularExpression cols = QRegularExpression( "^C[0-9]+$" );
169 |
170 | QBoxLayout *lyt = new QBoxLayout( QBoxLayout::TopToBottom );
171 |
172 | lyt->setContentsMargins( getMargins( props[ "Margins" ], mScreenSize ) );
173 | lyt->setSpacing( getSpacing( props[ "Spacing" ], mScreenSize ) );
174 |
175 | double width = getWidth( props[ "Width" ], mScreenSize );
176 |
177 | lyt->addStrut( (int)width );
178 |
179 | for ( int idx = 0; idx < (int)col.size(); ++idx ) {
180 | QString key( col[ idx ].to_string().c_str() );
181 | Hjson::Value properties = mProperties[ key.toStdString() ];
182 |
183 | /** Vertical Layout: Each key will leat to new rows */
184 | if ( rows.match( key ).hasMatch() ) {
185 | Hjson::Value row = mLayout[ key.toUtf8().data() ];
186 | lyt->addWidget( addRow( row, key, properties ) );
187 | }
188 |
189 | /** Horizontal Layout: Each key will leat to new columns */
190 | else if ( cols.match( key ).hasMatch() ) {
191 | Hjson::Value col = mLayout[ key.toUtf8().data() ];
192 | lyt->addWidget( addColumn( col, key, properties ) );
193 | }
194 |
195 | /** Initialize the widget */
196 | else {
197 | if ( key == "Stretch" ) {
198 | lyt->addStretch();
199 | continue;
200 | }
201 |
202 | QString widget = key.split( "-" ).at( 0 );
203 |
204 | QWidget *w = WidgetFactory::createWidget( widget, getType( properties[ "Type" ] ), properties, mScreenSize );
205 | lyt->addWidget( w, 0, getAlignment( props[ "Alignment" ] ) );
206 | }
207 | }
208 |
209 | Container *cw = new Container( props[ "BGColor" ], name );
210 |
211 | cw->setLayout( lyt );
212 |
213 | return cw;
214 | }
215 |
--------------------------------------------------------------------------------
/src/layoutmanager/LayoutManager.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | #include "hjson.h"
28 |
29 | namespace QtGreet {
30 | class LayoutManager;
31 | }
32 |
33 | class QtGreet::LayoutManager {
34 | public:
35 | LayoutManager( QScreen *scrn );
36 |
37 | QBoxLayout * generateLayout( QString layoutFile );
38 |
39 | private:
40 | /** Screen size */
41 | QSize mScreenSize;
42 |
43 | /** Parsed layout file */
44 | Hjson::Value mLayout;
45 | Hjson::Value mProperties;
46 |
47 | /** Parse the layout */
48 | void readLayout( Hjson::Value layout );
49 |
50 | /** Initialize a row and it's widgets */
51 | QWidget * addRow( Hjson::Value row, QString name, Hjson::Value props );
52 |
53 | /** Initialize a column and it's widgets */
54 | QWidget * addColumn( Hjson::Value row, QString name, Hjson::Value props );
55 | };
56 |
--------------------------------------------------------------------------------
/src/layoutmanager/LayoutUtils.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 |
23 | #include "LayoutUtils.hpp"
24 | #include "WidgetFactory.hpp"
25 |
26 | bool isNumeric( Hjson::Value val ) {
27 | switch ( val.type() ) {
28 | case Hjson::Type::Double:
29 | case Hjson::Type::Int64: {
30 | return true;
31 | }
32 |
33 | default: {
34 | return false;
35 | }
36 | }
37 |
38 | return false;
39 | }
40 |
41 |
42 | QMargins getMargins( Hjson::Value margins, QSize screenSize ) {
43 | if ( margins.empty() or not margins.defined() ) {
44 | return QMargins();
45 | }
46 |
47 | double left = 0;
48 | double right = 0;
49 | double top = 0;
50 | double bottom = 0;
51 |
52 | if ( isNumeric( margins ) ) {
53 | left = right = top = bottom = margins.to_double();
54 | }
55 |
56 | else if ( margins.type() == Hjson::Type::Vector ) {
57 | if ( margins.size() < 4 ) {
58 | left = right = top = bottom = margins.to_double();
59 | }
60 |
61 | else {
62 | left = margins[ 0 ];
63 | right = margins[ 1 ];
64 | top = margins[ 2 ];
65 | bottom = margins[ 3 ];
66 | }
67 | }
68 |
69 | else {
70 | if ( isNumeric( margins[ "Left" ] ) ) {
71 | left = margins[ "Left" ];
72 | }
73 |
74 | if ( isNumeric( margins[ "Right" ] ) ) {
75 | right = margins[ "Right" ];
76 | }
77 |
78 | if ( isNumeric( margins[ "Top" ] ) ) {
79 | top = margins[ "Top" ];
80 | }
81 |
82 | if ( isNumeric( margins[ "Bottom" ] ) ) {
83 | bottom = margins[ "Bottom" ];
84 | }
85 | }
86 |
87 | if ( left < 1.0 ) {
88 | left *= screenSize.width();
89 | }
90 |
91 | if ( right < 1.0 ) {
92 | right *= screenSize.width();
93 | }
94 |
95 | if ( top < 1.0 ) {
96 | top *= screenSize.height();
97 | }
98 |
99 | if ( bottom < 1.0 ) {
100 | bottom *= screenSize.height();
101 | }
102 |
103 | return QMargins( left, top, right, bottom );
104 | }
105 |
106 |
107 | int getSpacing( Hjson::Value value, QSize ) {
108 | if ( value.empty() or not value.defined() ) {
109 | return 0;
110 | }
111 |
112 | if ( value.type() != Hjson::Type::Int64 ) {
113 | return 0;
114 | }
115 |
116 | return value.to_int64();
117 | }
118 |
119 |
120 | Qt::Alignment getAlignment( Hjson::Value value ) {
121 | QString align( value.to_string().c_str() );
122 | Qt::Alignment XX;
123 |
124 | /** We'll manage the alignment externally */
125 | if ( align.isEmpty() ) {
126 | return XX;
127 | }
128 |
129 | if ( align.at( 0 ) == QChar( 'T' ) ) {
130 | XX = Qt::AlignTop;
131 | }
132 |
133 | else if ( align.at( 0 ) == QChar( 'M' ) ) {
134 | XX = Qt::AlignVCenter;
135 | }
136 |
137 | else if ( align.at( 0 ) == QChar( 'B' ) ) {
138 | XX = Qt::AlignBottom;
139 | }
140 |
141 | if ( align.size() == 2 ) {
142 | if ( align.at( 1 ) == QChar( 'L' ) ) {
143 | XX |= Qt::AlignLeft;
144 | }
145 |
146 | else if ( align.at( 1 ) == QChar( 'M' ) ) {
147 | XX |= Qt::AlignHCenter;
148 | }
149 |
150 | else if ( align.at( 1 ) == QChar( 'R' ) ) {
151 | XX |= Qt::AlignRight;
152 | }
153 | }
154 |
155 | else {
156 | XX |= Qt::AlignLeft;
157 | }
158 |
159 | return XX;
160 | }
161 |
162 |
163 | int getWidth( Hjson::Value obj, QSize screenSize ) {
164 | double width = obj.to_double();
165 |
166 | if ( width <= 1.0 ) {
167 | width *= screenSize.width();
168 | }
169 |
170 | if ( width < 0 ) {
171 | width = 0;
172 | }
173 |
174 | return (int)width;
175 | }
176 |
177 |
178 | int getHeight( Hjson::Value obj, QSize screenSize ) {
179 | double height = obj.to_double();
180 |
181 | if ( height <= 1.0 ) {
182 | height *= screenSize.height();
183 | }
184 |
185 | if ( height < 0 ) {
186 | height = 0;
187 | }
188 |
189 | return (int)height;
190 | }
191 |
192 |
193 | QString getType( Hjson::Value type ) {
194 | return type.to_string().c_str();
195 | }
196 |
197 |
198 | QFont::Weight getFontWeight( Hjson::Value weight ) {
199 | if ( weight.type() == Hjson::Type::String ) {
200 | std::string w( weight );
201 |
202 | if ( w == "Thin" ) {
203 | return QFont::Thin;
204 | }
205 |
206 | else if ( w == "ExtraLight" ) {
207 | return QFont::ExtraLight;
208 | }
209 |
210 | else if ( w == "Light" ) {
211 | return QFont::Light;
212 | }
213 |
214 | else if ( w == "Normal" ) {
215 | return QFont::Normal;
216 | }
217 |
218 | else if ( w == "Medium" ) {
219 | return QFont::Medium;
220 | }
221 |
222 | else if ( w == "DemiBold" ) {
223 | return QFont::DemiBold;
224 | }
225 |
226 | else if ( w == "Bold" ) {
227 | return QFont::Bold;
228 | }
229 |
230 | else if ( w == "ExtraBold" ) {
231 | return QFont::ExtraBold;
232 | }
233 |
234 | else if ( w == "Black" ) {
235 | return QFont::Black;
236 | }
237 |
238 | else {
239 | return QFont::Normal;
240 | }
241 | }
242 |
243 | else if ( weight.type() == Hjson::Type::Int64 ) {
244 | int w( weight );
245 |
246 | if ( w >= 87 ) {
247 | return QFont::Black;
248 | }
249 |
250 | else if ( w >= 81 ) {
251 | return QFont::ExtraBold;
252 | }
253 |
254 | else if ( w >= 75 ) {
255 | return QFont::Bold;
256 | }
257 |
258 | else if ( w >= 63 ) {
259 | return QFont::DemiBold;
260 | }
261 |
262 | else if ( w >= 57 ) {
263 | return QFont::Medium;
264 | }
265 |
266 | else if ( w >= 50 ) {
267 | return QFont::Normal;
268 | }
269 |
270 | else if ( w >= 25 ) {
271 | return QFont::Light;
272 | }
273 |
274 | else if ( w >= 12 ) {
275 | return QFont::ExtraLight;
276 | }
277 |
278 | else {
279 | return QFont::Thin;
280 | }
281 | }
282 |
283 | return QFont::Normal;
284 | }
285 |
--------------------------------------------------------------------------------
/src/layoutmanager/LayoutUtils.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include "Global.hpp"
22 | #include "hjson.h"
23 |
24 | /** Check if the Hjson value is numeric */
25 | bool isNumeric( Hjson::Value val );
26 |
27 | /** Convert Hjson::Value to QMargins */
28 | QMargins getMargins( Hjson::Value margins, QSize screenSize );
29 |
30 | /** Convert Hjson::Value to int */
31 | int getSpacing( Hjson::Value spacing, QSize screenSize );
32 |
33 | /** Convert two-char alignment value to Qt::Alignment */
34 | Qt::Alignment getAlignment( Hjson::Value obj );
35 |
36 | /** Convert Hjson::Value to width */
37 | int getWidth( Hjson::Value obj, QSize screenSize );
38 |
39 | /** Convert Hjson::Value to height */
40 | int getHeight( Hjson::Value obj, QSize screenSize );
41 |
42 | /** Get the widget type */
43 | QString getType( Hjson::Value type );
44 |
45 | /** Get the font weigth from string/number */
46 | QFont::Weight getFontWeight( Hjson::Value weight );
47 |
--------------------------------------------------------------------------------
/src/layoutmanager/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "LayoutManager.hpp"
3 |
4 | int main( int argc, char *argv[] ) {
5 | QApplication app( argc, argv );
6 |
7 | QtGreet::Layout *lyt = new QtGreet::Layout();
8 |
9 | lyt->generateLayout( argv[ 1 ] );
10 |
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/src/layoutmanager/parser/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016, 2017 Christian Zangl, Fredrik Trobro
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/layoutmanager/parser/hjson_parsenumber.cpp:
--------------------------------------------------------------------------------
1 | #include "hjson.h"
2 | #include
3 | #if HJSON_USE_CHARCONV
4 | # include
5 | #elif HJSON_USE_STRTOD
6 | # include
7 | # include
8 | #else
9 | # include
10 | #endif
11 |
12 |
13 | namespace Hjson {
14 | struct Parser {
15 | const unsigned char *data;
16 | size_t dataSize;
17 | int at;
18 | unsigned char ch;
19 | };
20 |
21 |
22 | static bool _parseFloat( double *pNumber, const char *pCh, size_t nCh ) {
23 | #if HJSON_USE_CHARCONV
24 | auto res = std::from_chars( pCh, pCh + nCh, *pNumber );
25 |
26 | return res.ptr == pCh + nCh && res.ec != std::errc::result_out_of_range &&
27 | !std::isinf( *pNumber ) && !std::isnan( *pNumber );
28 |
29 | #elif HJSON_USE_STRTOD
30 | char *endptr;
31 | errno = 0;
32 | *pNumber = std::strtod( pCh, &endptr );
33 |
34 | return !errno && endptr - pCh == nCh && !std::isinf( *pNumber ) && !std::isnan( *pNumber );
35 |
36 | #else
37 | std::string str( pCh, nCh );
38 | std::stringstream ss( str );
39 |
40 | // Make sure we expect dot (not comma) as decimal point.
41 | ss.imbue( std::locale::classic() );
42 |
43 | ss >> *pNumber;
44 |
45 | return ss.eof() && !ss.fail() && !std::isinf( *pNumber ) && !std::isnan( *pNumber );
46 |
47 | #endif
48 | }
49 |
50 |
51 | static bool _parseInt( std::int64_t *pNumber, const char *pCh, size_t nCh ) {
52 | #if HJSON_USE_CHARCONV
53 | auto res = std::from_chars( pCh, pCh + nCh, *pNumber );
54 |
55 | return res.ptr == pCh + nCh && res.ec != std::errc::result_out_of_range;
56 |
57 | #elif HJSON_USE_STRTOD
58 | char *endptr;
59 | errno = 0;
60 | *pNumber = std::strtoll( pCh, &endptr, 0 );
61 |
62 | return !errno && endptr - pCh == nCh;
63 |
64 | #else
65 | std::string str( pCh, nCh );
66 | std::stringstream ss( str );
67 |
68 | // Avoid localization surprises.
69 | ss.imbue( std::locale::classic() );
70 |
71 | ss >> *pNumber;
72 |
73 | return ss.eof() && !ss.fail();
74 |
75 | #endif
76 | }
77 |
78 |
79 | static bool _next( Parser *p ) {
80 | // get the next character.
81 | if ( (size_t)p->at < p->dataSize ) {
82 | p->ch = p->data[ p->at++ ];
83 | return true;
84 | }
85 |
86 | if ( (size_t)p->at == p->dataSize ) {
87 | p->at++;
88 | p->ch = 0;
89 | }
90 |
91 | return false;
92 | }
93 |
94 |
95 | // Parse a number value. The parameter "text" must be zero terminated.
96 | bool tryParseNumber( Value *pValue, const char *text, size_t textSize, bool stopAtNext ) {
97 | Parser p = {
98 | (const unsigned char *)text,
99 | textSize,
100 | 0,
101 | ' '
102 | };
103 |
104 | int leadingZeros = 0;
105 | bool testLeading = true;
106 |
107 | _next( &p );
108 |
109 | if ( p.ch == '-' ) {
110 | _next( &p );
111 | }
112 |
113 | while ( p.ch >= '0' && p.ch <= '9' ) {
114 | if ( testLeading ) {
115 | if ( p.ch == '0' ) {
116 | leadingZeros++;
117 | }
118 | else {
119 | testLeading = false;
120 | }
121 | }
122 |
123 | _next( &p );
124 | }
125 |
126 | if ( testLeading ) {
127 | leadingZeros--;
128 | } // single 0 is allowed
129 |
130 | if ( p.ch == '.' ) {
131 | while ( _next( &p ) && p.ch >= '0' && p.ch <= '9' ) {
132 | }
133 | }
134 |
135 | if ( (p.ch == 'e') || (p.ch == 'E') ) {
136 | _next( &p );
137 |
138 | if ( (p.ch == '-') || (p.ch == '+') ) {
139 | _next( &p );
140 | }
141 |
142 | while ( p.ch >= '0' && p.ch <= '9' ) {
143 | _next( &p );
144 | }
145 | }
146 |
147 | auto end = p.at;
148 |
149 | // skip white/to (newline)
150 | while ( p.ch > 0 && p.ch <= ' ' ) {
151 | _next( &p );
152 | }
153 |
154 | if ( stopAtNext ) {
155 | // end scan if we find a punctuator character like ,}] or a comment
156 | if ( (p.ch == ',') || (p.ch == '}') || (p.ch == ']') ||
157 | (p.ch == '#') || ( (p.ch == '/') && ( (p.data[ p.at ] == '/') || (p.data[ p.at ] == '*') ) ) ) {
158 | p.ch = 0;
159 | }
160 | }
161 |
162 | if ( (p.ch > 0) || (leadingZeros != 0) ) {
163 | // Invalid number.
164 | return false;
165 | }
166 |
167 | std::int64_t i;
168 |
169 | if ( _parseInt( &i, (char *)p.data, end - 1 ) ) {
170 | *pValue = Value( i );
171 | return true;
172 | }
173 | else {
174 | double d;
175 |
176 | if ( _parseFloat( &d, (char *)p.data, end - 1 ) ) {
177 | *pValue = Value( d );
178 | return true;
179 | }
180 | }
181 |
182 | return false;
183 | }
184 |
185 |
186 | bool startsWithNumber( const char *text, size_t textSize ) {
187 | Value number;
188 |
189 | return tryParseNumber( &number, text, textSize, true );
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/protocols/meson.build:
--------------------------------------------------------------------------------
1 | wayland_scanner = find_program( 'wayland-scanner' )
2 |
3 | wayland_scanner_code = generator(
4 | wayland_scanner,
5 | output: '@BASENAME@-protocol.c',
6 | arguments: ['private-code', '@INPUT@', '@OUTPUT@'],
7 | )
8 |
9 | wayland_scanner_server = generator(
10 | wayland_scanner,
11 | output: '@BASENAME@-protocol.h',
12 | arguments: ['server-header', '@INPUT@', '@OUTPUT@'],
13 | )
14 |
15 | protocols = [
16 | 'xdg-shell.xml',
17 | ]
18 |
19 | wl_protos_src = []
20 | wl_protos_headers = []
21 |
22 | foreach p : protocols
23 | xml = join_paths( p )
24 | wl_protos_src += wayland_scanner_code.process( xml )
25 | wl_protos_headers += wayland_scanner_server.process( xml )
26 | endforeach
27 |
28 | lib_wl_protos = static_library(
29 | 'wl_protos', wl_protos_src + wl_protos_headers,
30 | dependencies: [wayland_client],
31 | ) # for the include directory
32 |
33 | protos = declare_dependency(
34 | link_with: lib_wl_protos,
35 | sources: wl_protos_headers,
36 | )
37 |
--------------------------------------------------------------------------------
/src/thememanager/ThemeManager.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | // Local Headers
22 | #include "ThemeManager.hpp"
23 |
24 | static QStringList themePaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "qtgreet/themes", QStandardPaths::LocateDirectory );
25 |
26 | QtGreet::ThemeManager::ThemeManager( QString themeName ) {
27 | /** Read the env variable: QTGREET_THEME_DIRS */
28 | for ( QString themeDir: qEnvironmentVariable( "QTGREET_THEME_DIRS" ).split( ":" ) ) {
29 | if ( not themePaths.contains( QDir( themeDir ).path() ) ) {
30 | themePaths << themeDir;
31 | }
32 | }
33 |
34 | /** If this theme does not exist, use the 'default' theme */
35 | if ( not availableThemes().contains( themeName ) ) {
36 | themeName = "default";
37 | }
38 |
39 | readTheme( themeName );
40 | }
41 |
42 |
43 | QString QtGreet::ThemeManager::getLayout() {
44 | return mLayout;
45 | }
46 |
47 |
48 | QString QtGreet::ThemeManager::getStyleSheet() {
49 | QFile qss( mQSS );
50 |
51 | qss.open( QFile::ReadOnly );
52 | QString ss = QString::fromLocal8Bit( qss.readAll() );
53 |
54 | qss.close();
55 |
56 | return ss;
57 | }
58 |
59 |
60 | QString QtGreet::ThemeManager::background() {
61 | return imageBG;
62 | }
63 |
64 |
65 | bool QtGreet::ThemeManager::isVideoBG() {
66 | return mIsVideoBG;
67 | }
68 |
69 |
70 | QString QtGreet::ThemeManager::video() {
71 | return videoBG;
72 | }
73 |
74 |
75 | QStringList QtGreet::ThemeManager::availableThemes() {
76 | QStringList themes;
77 |
78 | for ( QString path: themePaths ) {
79 | QDirIterator dirIt( path, QStringList(), QDir::Dirs | QDir::NoDotAndDotDot );
80 | while ( dirIt.hasNext() ) {
81 | dirIt.next();
82 |
83 | if ( QFile::exists( dirIt.filePath() + "/index.theme" ) ) {
84 | themes << dirIt.fileName();
85 | }
86 | }
87 | }
88 |
89 | return themes;
90 | }
91 |
92 |
93 | void QtGreet::ThemeManager::readTheme( QString name ) {
94 | QString themePath;
95 |
96 | for ( QString path: themePaths ) {
97 | if ( QFile::exists( path + "/" + name ) ) {
98 | themePath = path + "/" + name + "/";
99 | break;
100 | }
101 | }
102 |
103 | QSettings theme( themePath + "/index.theme", QSettings::IniFormat );
104 |
105 | mIsVideoBG = theme.value( "Theme/Type" ).toString() == "Video";
106 | mLayout = themePath + theme.value( "Files/Layout" ).toString();
107 | mQSS = themePath + theme.value( "Files/StyleSheet" ).toString();
108 |
109 | if ( mIsVideoBG == false ) {
110 | imageBG = QDir( themePath ).filePath( theme.value( "Theme/Background" ).toString() );
111 | }
112 |
113 | else {
114 | if ( theme.value( "videobg/File" ).toString().length() ) {
115 | videoBG = QDir( themePath ).filePath( theme.value( "videobg/File" ).toString() );
116 | }
117 |
118 | else if ( theme.value( "videobg/Playlist" ).toString().length() ) {
119 | videoBG = QDir( themePath ).filePath( theme.value( "videobg/Playlist" ).toString() );
120 | }
121 | }
122 |
123 | mBaseColor = QColor( QString( "#%1" ).arg( theme.value( "Theme/BaseColor" ).toString() ) );
124 | mTextColor = QColor( QString( "#%1" ).arg( theme.value( "Theme/TextColor" ).toString() ) );
125 |
126 | /** Overrides: image */
127 | QString background = sett->value( "Overrides/Background", "Theme" ).toString();
128 |
129 | if ( background != "Theme" ) {
130 | imageBG = background;
131 | }
132 |
133 | /** Overrides: video */
134 | if ( sett->value( "videobg/File" ).toString().length() ) {
135 | videoBG = QDir( themePath ).filePath( sett->value( "videobg/File" ).toString() );
136 | }
137 |
138 | else if ( sett->value( "videobg/Playlist" ).toString().length() ) {
139 | videoBG = QDir( themePath ).filePath( sett->value( "videobg/Playlist" ).toString() );
140 | }
141 |
142 | QString baseColor = sett->value( "Overrides/BaseColor", "Theme" ).toString();
143 |
144 | if ( baseColor != "Theme" ) {
145 | mBaseColor = QColor( QString( "#%1" ).arg( baseColor ) );
146 | }
147 |
148 | QString textColor = sett->value( "Overrides/TextColor", "Theme" ).toString();
149 |
150 | if ( textColor != "Theme" ) {
151 | mTextColor = QColor( QString( "#%1" ).arg( textColor ) );
152 | }
153 |
154 | qDebug() << videoBG;
155 | }
156 |
--------------------------------------------------------------------------------
/src/thememanager/ThemeManager.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include "Global.hpp"
24 |
25 | namespace QtGreet {
26 | class ThemeManager;
27 | }
28 |
29 | class QtGreet::ThemeManager {
30 | public:
31 | ThemeManager( QString themeName );
32 |
33 | /** Get the layout path */
34 | QString getLayout();
35 |
36 | /** Get the stylesheet path */
37 | QString getStyleSheet();
38 |
39 | /** Path to background image/video */
40 | QString background();
41 |
42 | /** Base Color */
43 | QColor baseColor();
44 |
45 | /** Base Color */
46 | QColor textColor();
47 |
48 | /** Does the theme require video bg? */
49 | bool isVideoBG();
50 |
51 | /** Does the theme require video bg? */
52 | QString video();
53 |
54 | /** All the available themes */
55 | static QStringList availableThemes();
56 |
57 | private:
58 | void readTheme( QString );
59 |
60 | QString imageBG;
61 | QString videoBG;
62 | QString mLayout;
63 | QString mQSS;
64 | bool mIsVideoBG;
65 |
66 | QColor mBaseColor;
67 | QColor mTextColor;
68 | };
69 |
--------------------------------------------------------------------------------
/src/ui/QtGreet.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include "Global.hpp"
24 | #include "user.hpp"
25 | #include "session.hpp"
26 |
27 | #include
28 |
29 | class LoginManager;
30 |
31 | namespace QtGreet {
32 | class UI;
33 | class LayoutManager;
34 | class ThemeManager;
35 | }
36 |
37 | class QtGreet::UI : public QMainWindow {
38 | Q_OBJECT;
39 |
40 | public:
41 | UI( QScreen *scrn );
42 | ~UI();
43 |
44 | private:
45 | /* Create UI */
46 | void createUI();
47 |
48 | /* Prepare first use */
49 | void prepareUIforUse();
50 |
51 | /* Update the username on the screen */
52 | void updateUser( User );
53 |
54 | /* Update the session on the screen */
55 | void updateSession( uint );
56 |
57 | /* Show the validating message */
58 | void showValidating();
59 |
60 | /* Show the validating message */
61 | void showCustomLogin();
62 |
63 | /* Show the power message */
64 | void showPowerMessage( bool reboot, bool done );
65 |
66 | User mCurUser;
67 | Session mCurSession;
68 |
69 | /* Background image */
70 | QImage background;
71 |
72 | /* QtGreet theme manager, and layout manager */
73 | QtGreet::ThemeManager *themeMgr;
74 | QtGreet::LayoutManager *lytMgr;
75 |
76 | /* Base to show multiple widgets */
77 | QStackedWidget *base = nullptr;
78 |
79 | /* Login manager backend */
80 | LoginManager *login;
81 |
82 | /* Login1 backend */
83 | DFL::Login1 *login1;
84 |
85 | /* Validation message */
86 | QLabel *validating;
87 | QWidget *cLogin = nullptr;
88 |
89 | /* The screen on which this will be shown */
90 | QScreen *mScreen;
91 |
92 | protected:
93 | /** Draw background image */
94 | void paintEvent( QPaintEvent *pEvent );
95 |
96 | /** To detect Caps/Num lock */
97 | void keyPressEvent( QKeyEvent *kEvent );
98 |
99 | private Q_SLOTS:
100 | // Try to login: If successful, store the username/userid and the session path.
101 | void tryLogin();
102 |
103 | // Try to login using values from Custom Login widget.
104 | void tryCustomLogin();
105 |
106 | // ComboBox
107 | void on_UserEdit_textEdited( QString );
108 |
109 | // ComboBox
110 | void on_UserCombo_currentIndexChanged( int );
111 |
112 | // ListWidget
113 | void on_UserList_currentItemChanged( QListWidgetItem *, QListWidgetItem * );
114 |
115 | // UserNavButton - Right - Next User
116 | void on_UserNavRight_clicked();
117 |
118 | // UserNavButton - Left - Previous User
119 | void on_UserNavLeft_clicked();
120 |
121 | // SessionNavButton - Right - Next User
122 | void on_SessionNavRight_clicked();
123 |
124 | // SessionNavButton - Left - Previous User
125 | void on_SessionNavLeft_clicked();
126 |
127 | // SessionEditButton - Convert the SessionEdit from ReadOnly to ReadWrite
128 | void on_SessionEditButton_clicked();
129 |
130 | // LoginButton - ToolButton and PushButton - Perform the login: tryLogin()
131 | void on_LoginButton_clicked();
132 |
133 | // Password - Return pressed - Perform the login: tryLogin()
134 | void on_Password_returnPressed();
135 |
136 | // SessionEdit - Return pressed - Perform the login: tryLogin()
137 | void on_SessionEdit_returnPressed();
138 |
139 | // ComboBox
140 | void on_SessionCombo_currentIndexChanged( int );
141 |
142 | // ListWidget
143 | void on_SessionList_currentItemChanged( QListWidgetItem *, QListWidgetItem * );
144 |
145 | // PowerButton/Reboot/Halt/Suspend/Hibernate
146 | void on_PowerButton_suspend();
147 | void on_PowerButton_hibernate();
148 | void on_PowerButton_shutdown( bool );
149 | void on_PowerButton_reboot( bool );
150 | void on_Suspend_suspend();
151 | void on_Hibernate_hibernate();
152 | void on_Halt_shutdown( bool );
153 | void on_Reboot_reboot( bool );
154 | };
155 |
--------------------------------------------------------------------------------
/src/ui/ScreenManager.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include "QtGreet.hpp"
22 | #include "ScreenManager.hpp"
23 |
24 | #include
25 |
26 | QtGreet::ScreenManager::ScreenManager() {
27 | /** All the screens are currently "available", since none of them have been used */
28 | QList availScrns = qApp->screens();
29 |
30 | /** Let's now start creating instances of QtGreet for each of the available screens */
31 | for ( QScreen *scrn: availScrns ) {
32 | QtGreet::UI *ui = new QtGreet::UI( scrn );
33 |
34 | /** Map the screento the greeter */
35 | screenGreeterMap[ scrn ] = ui;
36 |
37 | /** Map the UI to the screen */
38 | greeterScreenMap[ ui->windowTitle() ] = scrn;
39 | }
40 |
41 | /** Create a new instance when a screen is added */
42 | connect(
43 | qApp, &QApplication::screenAdded, [ = ] ( QScreen *scrn ) mutable {
44 | QtGreet::UI *ui = new QtGreet::UI( scrn );
45 |
46 | /** Map the screento the greeter */
47 | screenGreeterMap[ scrn ] = ui;
48 |
49 | /** Map the UI to the screen */
50 | greeterScreenMap[ ui->windowTitle() ] = scrn;
51 |
52 | /** Show the greeter */
53 | ui->showFullScreen();
54 |
55 | /** Wait for Qt to process the pending events */
56 | qApp->processEvents();
57 |
58 | /** Sleep for 10 ms */
59 | usleep( 10 * 1000 );
60 | }
61 | );
62 |
63 | /** Remove the existing instance when a screen is removed */
64 | connect(
65 | qApp, &QApplication::screenRemoved, [ = ] ( QScreen *scrn ) mutable {
66 | QString instance = QString( "QtGreet-%1-%2x%3" ).arg( scrn->name() ).arg( scrn->size().width() ).arg( scrn->size().height() );
67 |
68 | greeterScreenMap.remove( instance );
69 | QtGreet::UI *ui = screenGreeterMap.take( scrn );
70 | ui->close();
71 |
72 | delete ui;
73 | }
74 | );
75 | }
76 |
77 |
78 | void QtGreet::ScreenManager::showInstacnes() {
79 | /** Show each of the greeters, force Qt to process the event queue, sleep of 10 ms */
80 | for ( QtGreet::UI *ui: screenGreeterMap.values() ) {
81 | /** Show the greeter */
82 | ui->showFullScreen();
83 |
84 | /** Wait for Qt to process the pending events */
85 | qApp->processEvents();
86 |
87 | /** Sleep for 10 ms */
88 | usleep( 10 * 1000 );
89 | }
90 | }
91 |
92 |
93 | QScreen * QtGreet::ScreenManager::screenForWindow( QString title ) {
94 | if ( greeterScreenMap.contains( title ) ) {
95 | return greeterScreenMap[ title ];
96 | }
97 |
98 | return nullptr;
99 | }
100 |
--------------------------------------------------------------------------------
/src/ui/ScreenManager.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include "Global.hpp"
24 |
25 | #include
26 |
27 | class LoginManager;
28 |
29 | namespace QtGreet {
30 | class UI;
31 | class ScreenManager;
32 | }
33 |
34 | class QtGreet::ScreenManager : public QObject {
35 | Q_OBJECT;
36 |
37 | public:
38 | ScreenManager();
39 |
40 | /** The parameter @title uniquely identifies a window */
41 | QScreen * screenForWindow( QString title );
42 |
43 | /** Show the already initialized instances */
44 | void showInstacnes();
45 |
46 | private:
47 | /** List of greeters */
48 | QMap screenGreeterMap;
49 |
50 | /** Greeter <-> Screen map */
51 | QMap greeterScreenMap;
52 | };
53 |
--------------------------------------------------------------------------------
/src/widgets/buttons/buttons.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 |
23 | #include "buttons.hpp"
24 |
25 | NavButton::NavButton( QString name, QString type ) : QToolButton() {
26 | setObjectName( name + type );
27 | setFixedSize( QSize( 27, 27 ) );
28 | setIconSize( QSize( 22, 22 ) );
29 | setAutoRaise( true );
30 |
31 | if ( type == "Right" ) {
32 | setIcon( QIcon( ":/icons/arrow-right.png" ) );
33 | }
34 |
35 | else {
36 | setIcon( QIcon( ":/icons/arrow-left.png" ) );
37 | }
38 | }
39 |
40 |
41 | SessionEditButton::SessionEditButton() : QToolButton() {
42 | setObjectName( "SessionEditButton" );
43 | setFixedSize( QSize( 27, 27 ) );
44 | setIconSize( QSize( 22, 22 ) );
45 | setAutoRaise( true );
46 |
47 | setIcon( QIcon( ":/icons/edit.png" ) );
48 | }
49 |
50 |
51 | LoginToolButton::LoginToolButton() : QToolButton() {
52 | setObjectName( "LoginButton" );
53 | setFixedSize( QSize( 27, 27 ) );
54 | setIconSize( QSize( 22, 22 ) );
55 | setAutoRaise( true );
56 |
57 | setIcon( QIcon( ":/icons/arrow-right.png" ) );
58 | }
59 |
60 |
61 | LoginPushButton::LoginPushButton() : QPushButton() {
62 | setObjectName( "LoginButton" );
63 | setFixedSize( QSize( 27, 27 ) );
64 | setIconSize( QSize( 22, 22 ) );
65 | setFlat( true );
66 |
67 | setText( "&Login" );
68 | setIcon( QIcon( ":/icons/arrow-right.png" ) );
69 | }
70 |
--------------------------------------------------------------------------------
/src/widgets/buttons/buttons.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | class NavButton : public QToolButton {
26 | Q_OBJECT;
27 |
28 | public:
29 | NavButton( QString name, QString type );
30 | };
31 |
32 | class SessionEditButton : public QToolButton {
33 | Q_OBJECT;
34 |
35 | public:
36 | SessionEditButton();
37 | };
38 |
39 | class LoginToolButton : public QToolButton {
40 | Q_OBJECT;
41 |
42 | public:
43 | LoginToolButton();
44 | };
45 |
46 | class LoginPushButton : public QPushButton {
47 | Q_OBJECT;
48 |
49 | public:
50 | LoginPushButton();
51 | };
52 |
--------------------------------------------------------------------------------
/src/widgets/clock/ClockWidget.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | class QDBusInterface;
30 | class BatteryInfo;
31 |
32 | class AnalogClock : public QWidget {
33 | Q_OBJECT;
34 |
35 | public:
36 | AnalogClock( QColor text, QWidget *parent = 0 );
37 |
38 | private:
39 | QColor mTextColor;
40 | QColor mShadowColor;
41 |
42 | BatteryInfo *battery;
43 | qreal mCharge = 100.0;
44 | bool mOnBattery = false;
45 | QImage battImg;
46 |
47 | protected:
48 | void paintEvent( QPaintEvent *event ) override;
49 | };
50 |
51 | class DigitalClock : public QWidget {
52 | Q_OBJECT
53 |
54 | public:
55 | DigitalClock( QWidget *parent = 0 );
56 |
57 | private:
58 | QLCDNumber *time;
59 | QLCDNumber *secs;
60 | QLabel *ampm;
61 | QLabel *date;
62 | QLabel *alrm;
63 |
64 | QBasicTimer *timer;
65 |
66 | protected:
67 | void timerEvent( QTimerEvent *event ) override;
68 | };
69 |
70 | class SimpleClock : public QLabel {
71 | Q_OBJECT
72 |
73 | public:
74 | SimpleClock( bool time, bool date, QWidget *parent = 0 );
75 |
76 | void setDateFormat( QString );
77 | void setTimeFormat( QString );
78 |
79 | private:
80 | QBasicTimer *timer;
81 | QString timeFmt;
82 | QString dateFmt;
83 | QString clockFmt;
84 |
85 | bool mShowTime = true;
86 | bool mShowDate = true;
87 |
88 | protected:
89 | void timerEvent( QTimerEvent *event ) override;
90 | };
91 |
92 | class BatteryInfo : public QObject {
93 | Q_OBJECT;
94 |
95 | public:
96 | BatteryInfo();
97 |
98 | qreal currentCharge();
99 | bool onBattery();
100 |
101 | private:
102 | QDBusInterface *iface;
103 | qreal mLastPercentage = 100.0;
104 | bool mOnBattery = false;
105 |
106 | private Q_SLOTS:
107 | void handlePowerChanges( QString, QVariantMap, QStringList );
108 |
109 | Q_SIGNALS:
110 | /* Battery Charge/Discharge Signals */
111 | void onBatteryChanged( bool );
112 |
113 | /* Battery charge changed */
114 | void chargeChanged( double );
115 | };
116 |
--------------------------------------------------------------------------------
/src/widgets/container/Container.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 |
23 | #include "Container.hpp"
24 |
25 | Container::Container( Hjson::Value bgClr, QString name ) : QWidget() {
26 | /** Object Name */
27 | setObjectName( name );
28 |
29 | /** Default Background will be transparent */
30 | bgColor = QColor( Qt::transparent );
31 |
32 | if ( not bgClr.empty() ) {
33 | int red, green, blue, alpha;
34 | red = bgClr[ "Red" ].to_double() * 255;
35 | green = bgClr[ "Green" ].to_double() * 255;
36 | blue = bgClr[ "Blue" ].to_double() * 255;
37 | alpha = bgClr[ "Alpha" ].to_double() * 255;
38 |
39 | bgColor = QColor( red, green, blue, alpha );
40 | }
41 | }
42 |
43 |
44 | void Container::paintEvent( QPaintEvent *pEvent ) {
45 | if ( bgColor != QColor( Qt::transparent ) ) {
46 | QPainter painter( this );
47 |
48 | painter.setBrush( bgColor );
49 | painter.setPen( Qt::NoPen );
50 |
51 | painter.drawRoundedRect( rect(), 5, 5 );
52 |
53 | painter.end();
54 | }
55 |
56 | QWidget::paintEvent( pEvent );
57 | }
58 |
--------------------------------------------------------------------------------
/src/widgets/container/Container.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | #include "hjson.h"
28 |
29 | class Container : public QWidget {
30 | Q_OBJECT;
31 |
32 | public:
33 | Container( Hjson::Value value, QString name );
34 |
35 | private:
36 | QColor bgColor;
37 | QColor border;
38 |
39 | protected:
40 | void paintEvent( QPaintEvent * );
41 | };
42 |
--------------------------------------------------------------------------------
/src/widgets/factory/WidgetFactory.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include "Global.hpp"
24 |
25 | #include "hjson.h"
26 |
27 | class WidgetFactory {
28 | public:
29 | /* Create a widget, given its name, and apply the properties given in the map */
30 | static QWidget *createWidget( QString name, QString type, Hjson::Value properties, QSize size );
31 |
32 | private:
33 |
34 | /*
35 | * Most of the properties given can be applied directly, like width and height
36 | * Some properties like text, or icon need to be applied after casting them into suitable types.
37 | * Invalid properties will be ignored. Ex. icon for a label
38 | */
39 | static void applyWidgetProperties( QWidget *, QString, QString, Hjson::Value, QSize size );
40 | };
41 |
--------------------------------------------------------------------------------
/src/widgets/key:
--------------------------------------------------------------------------------
1 | +==============================================================+=======================+========================+
2 | | Widget | Name | Type |
3 | +--------------------------------------------------------------+-----------------------+------------------------+
4 | | | | |
5 | | buttons - All generic buttons | | |
6 | | 1. Okay button | OkayButton | OkayButton |
7 | | 2. Cancel button | CancelButton | CancelButton |
8 | | 3. Session Edit Button | SessionEditButton | SessionEditButton |
9 | | 4. User nav buttons | UserNav | Left|Right |
10 | | 5. Session nav buttons | SessionNav | Left|Right |
11 | | 6. Login button | LoginButton | Tool|Push Button |
12 | +--------------------------------------------------------------+-----------------------+------------------------+
13 | | | | |
14 | | clock - various clock widgets | | |
15 | | 1. Analog Clock | Clock | AnalogClock |
16 | | 2. Digital Clock | Clock | DigitalClock |
17 | | 3. Simple Clock | Clock | Time|Date|Simple |
18 | +--------------------------------------------------------------+-----------------------+------------------------+
19 | | | | |
20 | | labels - simple labels | | |
21 | | 1. Caps lock | CapsLock | CapsLock |
22 | | 2. Num lock | NumLock | NumLock |
23 | | 3. User Icon | UserIcon | UserIcon |
24 | | 4. Logo | Logo | Logo |
25 | +--------------------------------------------------------------+-----------------------+------------------------+
26 | | | | |
27 | | power - power related buttons | | |
28 | | 1. Power menu button | PowerButton | Menu |
29 | | 2. Halt button | PowerButton | Halt |
30 | | 3. Reboot button | PowerButton | Reboot |
31 | | 4. Suspend button | PowerButton | Suspend |
32 | | 5. Hibernate button | PowerButton | Hibernate |
33 | | 6. Logout button | PowerButton | Logout |
34 | +--------------------------------------------------------------+-----------------------+------------------------+
35 | | | | |
36 | | password - Password entry | | |
37 | | 1. Password edit | Password | LineEdit |
38 | +--------------------------------------------------------------+-----------------------+------------------------+
39 | | | | |
40 | | session - Session name | | |
41 | | 1. Session combo | SessionName | Combo |
42 | | 2. Session list | SessionName | List |
43 | | 3. Session button | SessionName | PushButton |
44 | | 4. Session label | SessionName | Label |
45 | | 5. Session edit | SessionName | LineEdit |
46 | +--------------------------------------------------------------+-----------------------+------------------------+
47 | | | | |
48 | | user - User name | | |
49 | | 1. User combo | UserName | Combo |
50 | | 2. User list | UserName | List |
51 | | 3. User edit | UserName | LineEdit |
52 | | 4. User label | UserName | Label |
53 | | 5. User button | UserName | PushButton |
54 | +==============================================================+=======================+========================+
55 |
--------------------------------------------------------------------------------
/src/widgets/labels/labels.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 |
23 | #include "labels.hpp"
24 |
25 | LockState::LockState( QString type ) : QWidget() {
26 | /* Initial Status */
27 | QFile file;
28 |
29 | if ( type == "CapsLock" ) {
30 | setObjectName( "CapsLock" );
31 | file.setFileName( "/sys/class/leds/input0::capslock/brightness" );
32 | text = "A";
33 | }
34 |
35 | else {
36 | setObjectName( "NumLock" );
37 | file.setFileName( "/sys/class/leds/input0::numlock/brightness" );
38 | text = "#";
39 | }
40 |
41 | if ( file.open( QFile::ReadOnly ) ) {
42 | if ( file.readAll().toInt() ) {
43 | isOn = true;
44 | }
45 |
46 | else {
47 | isOn = false;
48 | }
49 |
50 | file.close();
51 | }
52 |
53 | mFont = font();
54 | mFont.setPointSize( qMin( width(), height() ) - 4 );
55 | mFont.setWeight( QFont::Bold );
56 |
57 | setFont( mFont );
58 |
59 | textClr = palette().color( QPalette::Text );
60 |
61 | setMinimumSize( QSize( 16, 16 ) );
62 | }
63 |
64 |
65 | void LockState::setState( bool state ) {
66 | isOn = state;
67 | repaint();
68 | }
69 |
70 |
71 | void LockState::toggle() {
72 | isOn = not isOn;
73 | repaint();
74 | }
75 |
76 |
77 | void LockState::paintEvent( QPaintEvent *pEvent ) {
78 | QPainter painter( this );
79 |
80 | painter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing );
81 |
82 | if ( isOn ) {
83 | textClr.setAlphaF( 1.0 );
84 | }
85 |
86 | else {
87 | textClr.setAlphaF( 0.2 );
88 | }
89 |
90 | painter.setPen( textClr );
91 | painter.drawText( rect(), Qt::AlignCenter, text );
92 |
93 | painter.end();
94 |
95 | pEvent->accept();
96 | }
97 |
98 |
99 | UserIcon::UserIcon() : QLabel() {
100 | setObjectName( "UserIcon" );
101 | setAlignment( Qt::AlignCenter );
102 | setFixedSize( QSize( 72, 72 ) );
103 |
104 | iconSize = QSize( 64, 64 );
105 |
106 | img = QImage( ":/icons/user.png" );
107 | }
108 |
109 |
110 | void UserIcon::setPixmap( QString path ) {
111 | img = QImage( path );
112 | update();
113 | }
114 |
115 |
116 | void UserIcon::paintEvent( QPaintEvent *pEvent ) {
117 | QPainter painter( this );
118 |
119 | painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform );
120 |
121 | QImage brush = img.scaled( iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation );
122 |
123 | if ( brush.isNull() ) {
124 | brush = QImage( ":/icons/user.png" ).scaled( iconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation );
125 | }
126 |
127 | painter.save();
128 | painter.setPen( QPen( Qt::gray, 2.0 ) );
129 | painter.drawRoundedRect( rect().adjusted( 1, 1, -1, -1 ), 5.0, 5.0 );
130 | painter.restore();
131 |
132 | painter.save();
133 | painter.translate( 4, 4 );
134 | painter.setBrush( brush );
135 | painter.setPen( Qt::NoPen );
136 | painter.drawRoundedRect( QRectF( QPointF( 0, 0 ), iconSize ), 5.0, 5.0 );
137 | painter.restore();
138 |
139 | painter.end();
140 |
141 | pEvent->accept();
142 | }
143 |
144 |
145 | Logo::Logo() : QWidget() {
146 | setObjectName( "Logo" );
147 | setFixedSize( 40, 40 );
148 | mIcon = ":/icons/QtGreet.png";
149 | }
150 |
151 |
152 | void Logo::setIconSize( QSize size ) {
153 | mIconSize = size.width();
154 | mPix = QPixmap( mIcon ).scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
155 |
156 | repaint();
157 | }
158 |
159 |
160 | void Logo::setIcon( QString img ) {
161 | mIcon = img;
162 | QSize size( mIconSize, mIconSize );
163 |
164 | mPix = QPixmap( mIcon ).scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
165 |
166 | repaint();
167 | }
168 |
169 |
170 | void Logo::paintEvent( QPaintEvent *pEvent ) {
171 | QPainter painter( this );
172 |
173 | painter.setRenderHints( QPainter::Antialiasing );
174 | painter.drawPixmap( QRect( (width() - mIconSize) / 2, (height() - mIconSize) / 2, mIconSize, mIconSize ), mPix );
175 | painter.end();
176 |
177 | pEvent->accept();
178 | }
179 |
--------------------------------------------------------------------------------
/src/widgets/labels/labels.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | class LockState : public QWidget {
26 | Q_OBJECT;
27 |
28 | public:
29 | LockState( QString type );
30 |
31 | void setState( bool state );
32 | void toggle();
33 |
34 | private:
35 | bool isOn = false;
36 | QFont mFont;
37 | QColor textClr;
38 | QString text;
39 |
40 | protected:
41 | void paintEvent( QPaintEvent *pEvent );
42 | };
43 |
44 | class UserIcon : public QLabel {
45 | Q_OBJECT;
46 |
47 | public:
48 | UserIcon();
49 |
50 | void setPixmap( QString );
51 |
52 | private:
53 | QImage img;
54 | QSize iconSize;
55 |
56 | protected:
57 | void paintEvent( QPaintEvent * );
58 | };
59 |
60 | class Logo : public QWidget {
61 | Q_OBJECT;
62 |
63 | public:
64 | Logo();
65 |
66 | void setIconSize( QSize );
67 | void setIcon( QString );
68 |
69 | private:
70 | int mIconSize;
71 | QString mIcon;
72 | QPixmap mPix;
73 |
74 | protected:
75 | void paintEvent( QPaintEvent *pEvent );
76 | };
77 |
--------------------------------------------------------------------------------
/src/widgets/power/power.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 |
23 | #include "Global.hpp"
24 | #include "power.hpp"
25 |
26 | QString getCommand( QString what ) {
27 | return sett->value( "PowerCommands/" + what ).toString();
28 | }
29 |
30 |
31 | PowerButton::PowerButton( QString type ) : QToolButton() {
32 | setAutoRaise( true );
33 | setFixedSize( QSize( 40, 40 ) );
34 | setIconSize( QSize( 32, 32 ) );
35 |
36 | if ( type == "Menu" ) {
37 | setIcon( QIcon( ":/icons/shutdown.png" ) );
38 | setObjectName( "PowerButton" );
39 |
40 | setToolTip( "Logout Menu" );
41 |
42 | QMenu *menu = new QMenu();
43 | menu->addAction(
44 | QIcon( ":/icons/suspend.png" ), "Suspend to RAM", [ = ] () {
45 | QStringList args = getCommand( "Suspend" ).split( " " );
46 |
47 | if ( args.at( 0 ) == "dbus" ) {
48 | emit suspend();
49 | }
50 |
51 | else {
52 | QProcess::startDetached( args.takeAt( 0 ), args );
53 | }
54 | }
55 | );
56 |
57 | menu->addAction(
58 | QIcon( ":/icons/hibernate.png" ), "Suspend to Disk", [ = ] () {
59 | QStringList args = getCommand( "Hibernate" ).split( " " );
60 |
61 | if ( args.at( 0 ) == "dbus" ) {
62 | emit hibernate();
63 | }
64 |
65 | else {
66 | QProcess::startDetached( args.takeAt( 0 ), args );
67 | }
68 | }
69 | );
70 |
71 | menu->addAction(
72 | QIcon( ":/icons/shutdown.png" ), "Halt System", [ = ] () {
73 | QStringList args = getCommand( "Shutdown" ).split( " " );
74 |
75 | if ( args.at( 0 ) == "dbus" ) {
76 | emit shutdown( false );
77 | }
78 |
79 | else {
80 | QProcess::startDetached( args.takeAt( 0 ), args );
81 | emit shutdown( true );
82 | }
83 | }
84 | );
85 |
86 | menu->addAction(
87 | QIcon( ":/icons/reboot.png" ), "Reboot System", [ = ] () {
88 | QStringList args = getCommand( "Reboot" ).split( " " );
89 |
90 | if ( args.at( 0 ) == "dbus" ) {
91 | emit reboot( false );
92 | }
93 |
94 | else {
95 | QProcess::startDetached( args.takeAt( 0 ), args );
96 | emit reboot( true );
97 | }
98 | }
99 | );
100 |
101 | setMenu( menu );
102 | setPopupMode( QToolButton::InstantPopup );
103 | }
104 |
105 | else if ( type == "Suspend" ) {
106 | setObjectName( "Suspend" );
107 | setToolTip( "Suspend to RAM" );
108 | setIcon( QIcon( ":/icons/suspend.png" ) );
109 | connect(
110 | this, &QToolButton::clicked, [ = ] () {
111 | QStringList args = getCommand( "Suspend" ).split( " " );
112 |
113 | if ( args.at( 0 ) == "dbus" ) {
114 | emit suspend();
115 | }
116 |
117 | else {
118 | QProcess::startDetached( args.takeAt( 0 ), args );
119 | }
120 | }
121 | );
122 | }
123 |
124 | else if ( type == "Hibernate" ) {
125 | setObjectName( "Hibernate" );
126 | setToolTip( "Suspend to Disk" );
127 | setIcon( QIcon( ":/icons/hibernate.png" ) );
128 | connect(
129 | this, &QToolButton::clicked, [ = ] () {
130 | QStringList args = getCommand( "Hibernate" ).split( " " );
131 |
132 | if ( args.at( 0 ) == "dbus" ) {
133 | emit hibernate();
134 | }
135 |
136 | else {
137 | QProcess::startDetached( args.takeAt( 0 ), args );
138 | }
139 | }
140 | );
141 | }
142 |
143 | else if ( type == "Halt" ) {
144 | setObjectName( "Halt" );
145 | setToolTip( "Shutdown the system" );
146 | setIcon( QIcon( ":/icons/shutdown.png" ) );
147 | connect(
148 | this, &QToolButton::clicked, [ = ] () {
149 | QStringList args = getCommand( "Shutdown" ).split( " " );
150 |
151 | if ( args.at( 0 ) == "dbus" ) {
152 | emit shutdown( false );
153 | }
154 |
155 | else {
156 | QProcess::startDetached( args.takeAt( 0 ), args );
157 | emit shutdown( true );
158 | }
159 | }
160 | );
161 | }
162 |
163 | else if ( type == "Reboot" ) {
164 | setObjectName( "Reboot" );
165 | setToolTip( "Reboot the system" );
166 | setIcon( QIcon( ":/icons/reboot.png" ) );
167 | connect(
168 | this, &QToolButton::clicked, [ = ] () {
169 | QStringList args = getCommand( "Reboot" ).split( " " );
170 |
171 | if ( args.at( 0 ) == "dbus" ) {
172 | emit reboot( false );
173 | }
174 |
175 | else {
176 | QProcess::startDetached( args.takeAt( 0 ), args );
177 | emit reboot( true );
178 | }
179 | }
180 | );
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/src/widgets/power/power.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 | #include
25 |
26 | class PowerButton : public QToolButton {
27 | Q_OBJECT;
28 |
29 | public:
30 | PowerButton( QString type );
31 |
32 | /** Perform a suspend */
33 | Q_SIGNAL void suspend();
34 |
35 | /** Perform a hibernate */
36 | Q_SIGNAL void hibernate();
37 |
38 | /**
39 | * Perform a shutdown or inform the user of a shutdown.
40 | * @done - The action has been done, just inform the user.
41 | */
42 | Q_SIGNAL void shutdown( bool done );
43 |
44 | /**
45 | * Perform a reboot or inform the user of a reboot.
46 | * @done - The action has been done, just inform the user.
47 | */
48 | Q_SIGNAL void reboot( bool done );
49 | };
50 |
--------------------------------------------------------------------------------
/src/widgets/session/session.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #include
22 | #include "Global.hpp"
23 |
24 | #include "session.hpp"
25 |
26 | static bool IsExec( QString exec ) {
27 | /* If this is a full path (ex: /usr/bin/fish) */
28 | if ( access( exec.toUtf8().constData(), R_OK | X_OK ) == 0 ) {
29 | return true;
30 | }
31 |
32 | QStringList parts = exec.split( QRegularExpression( "\\s+" ) );
33 | QString cmd;
34 |
35 | /** Pick the first part which is not a env variable as cmd */
36 | for ( QString part: parts ) {
37 | if ( part.contains( "=" ) ) {
38 | continue;
39 | }
40 |
41 | cmd = part;
42 | break;
43 | }
44 |
45 | /* Otherwise (ex: plasmashell) */
46 | for ( QString path : qgetenv( "PATH" ).split( ':' ) ) {
47 | if ( QFileInfo( path + "/" + exec ).isExecutable() ) {
48 | return true;
49 | }
50 |
51 | if ( QFileInfo( path + "/" + cmd ).isExecutable() ) {
52 | return true;
53 | }
54 | }
55 |
56 | return false;
57 | }
58 |
59 |
60 | Sessions getSessions( bool custom ) {
61 | Sessions mSessions;
62 |
63 | QStringList wlSessPaths;
64 |
65 | if ( wlSessPath == "default" ) {
66 | wlSessPaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "wayland-sessions", QStandardPaths::LocateDirectory );
67 | }
68 |
69 | else {
70 | wlSessPaths = wlSessPath.split( ";", Qt::SkipEmptyParts );
71 | }
72 |
73 | for ( QString wlSessDir: wlSessPaths ) {
74 | for ( QFileInfo sess: QDir( wlSessDir ).entryInfoList( { "*.desktop" } ) ) {
75 | QSettings session( sess.absoluteFilePath(), QSettings::IniFormat );
76 |
77 | bool isAvailable = IsExec( session.value( "Desktop Entry/TryExec" ).toString() );
78 | isAvailable |= IsExec( session.value( "Desktop Entry/Exec" ).toString() );
79 |
80 | if ( isAvailable ) {
81 | Session s = Session{
82 | session.value( "Desktop Entry/Name" ).toString(),
83 | session.value( "Desktop Entry/Icon", ":/icons/session.png" ).toString(),
84 | "wayland",
85 | session.value( "Desktop Entry/Exec" ).toString(),
86 | sess.absoluteFilePath()
87 | };
88 |
89 | if ( not s.name.contains( "wayland", Qt::CaseInsensitive ) ) {
90 | s.name += " (Wayland)";
91 | }
92 |
93 | mSessions << s;
94 | }
95 | }
96 | }
97 |
98 | QStringList xSessPaths;
99 |
100 | if ( xSessPath == "default" ) {
101 | xSessPaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "xsessions", QStandardPaths::LocateDirectory );
102 | }
103 |
104 | else {
105 | xSessPaths = xSessPath.split( ";", Qt::SkipEmptyParts );
106 | }
107 |
108 | for ( QString xSessDir: xSessPaths ) {
109 | for ( QFileInfo sess: QDir( xSessDir ).entryInfoList( { "*.desktop" } ) ) {
110 | QSettings session( sess.absoluteFilePath(), QSettings::IniFormat );
111 |
112 | bool isAvailable = IsExec( session.value( "Desktop Entry/TryExec" ).toString() );
113 | isAvailable |= IsExec( session.value( "Desktop Entry/Exec" ).toString() );
114 |
115 | if ( isAvailable ) {
116 | Session s = Session{
117 | session.value( "Desktop Entry/Name" ).toString() + " (X11)",
118 | session.value( "Desktop Entry/Icon", ":/icons/session.png" ).toString(),
119 | "X11",
120 | session.value( "Desktop Entry/Exec" ).toString(),
121 | sess.absoluteFilePath()
122 | };
123 |
124 | mSessions << s;
125 | }
126 | }
127 | }
128 |
129 | if ( custom ) {
130 | Session customSess{ "Custom", "application-x-executable", "unknown", "", "" };
131 | mSessions << customSess;
132 | }
133 |
134 | return mSessions;
135 | }
136 |
137 |
138 | SessionEdit::SessionEdit() : QLineEdit() {
139 | setObjectName( "SessionEdit" );
140 | setMinimumSize( QSize( 200, 27 ) );
141 | setAlignment( Qt::AlignCenter );
142 | }
143 |
144 |
145 | /* Session Name - Generic Class */
146 |
147 | SessionName::SessionName( bool custom ) {
148 | mSessionList = getSessions( custom );
149 | }
150 |
151 |
152 | void SessionName::switchToNextSession() {
153 | curSess++;
154 |
155 | if ( curSess >= mSessionList.count() ) {
156 | curSess = 0;
157 | }
158 | }
159 |
160 |
161 | void SessionName::switchToPreviousSession() {
162 | curSess--;
163 |
164 | if ( curSess < 0 ) {
165 | curSess = mSessionList.count() - 1;
166 | }
167 | }
168 |
169 |
170 | Sessions SessionName::sessions() {
171 | return mSessionList;
172 | }
173 |
174 |
175 | Session SessionName::currentSession() {
176 | // Return an invalid session
177 | return mSessionList.at( curSess );
178 | }
179 |
180 |
181 | /* Session ComboBox */
182 |
183 | SessionCombo::SessionCombo( bool custom ) : QComboBox(), SessionName( custom ) {
184 | setObjectName( "SessionCombo" );
185 | for ( Session sess: mSessionList ) {
186 | addItem( QIcon( sess.icon ), sess.name );
187 | }
188 | }
189 |
190 |
191 | void SessionCombo::switchToNextSession() {
192 | SessionName::switchToNextSession();
193 | setCurrentIndex( curSess );
194 | }
195 |
196 |
197 | void SessionCombo::switchToPreviousSession() {
198 | SessionName::switchToPreviousSession();
199 | setCurrentIndex( curSess );
200 | }
201 |
202 |
203 | /* Session List */
204 |
205 | SessionList::SessionList( bool custom ) : QListWidget(), SessionName( custom ) {
206 | setObjectName( "SessionList" );
207 | setIconSize( QSize( 24, 24 ) );
208 | setFont( QFont( "Quicksand", 12 ) );
209 | setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
210 | setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
211 |
212 | for ( Session sess: mSessionList ) {
213 | addItem( new QListWidgetItem( QIcon::fromTheme( sess.icon, QIcon( sess.icon ) ), sess.name, this ) );
214 | }
215 | }
216 |
217 |
218 | void SessionList::switchToNextSession() {
219 | SessionName::switchToNextSession();
220 | setCurrentRow( curSess );
221 | }
222 |
223 |
224 | void SessionList::switchToPreviousSession() {
225 | SessionName::switchToPreviousSession();
226 | setCurrentRow( curSess );
227 | }
228 |
229 |
230 | /* Session Label */
231 |
232 | SessionLabel::SessionLabel( bool custom ) : QWidget(), SessionName( custom ) {
233 | setObjectName( "SessionLabel" );
234 |
235 | prevBtn = new QToolButton();
236 | prevBtn->setObjectName( "SessionNavLeft" );
237 | prevBtn->setIcon( QIcon( ":/icons/arrow-left.png" ) );
238 |
239 | lbl = new QLabel();
240 | lbl->setObjectName( "SessionLabel" );
241 |
242 | nextBtn = new QToolButton();
243 | nextBtn->setObjectName( "SessionNavRight" );
244 | nextBtn->setIcon( QIcon( ":/icons/arrow-right.png" ) );
245 |
246 | QHBoxLayout *lyt = new QHBoxLayout();
247 |
248 | lyt->setContentsMargins( QMargins() );
249 | lyt->setSpacing( 5 );
250 |
251 | lyt->addWidget( prevBtn );
252 | lyt->addWidget( lbl );
253 | lyt->addWidget( nextBtn );
254 |
255 | setLayout( lyt );
256 |
257 | nextBtn->hide();
258 | prevBtn->hide();
259 |
260 | setFixedHeight( 27 );
261 | }
262 |
263 |
264 | void SessionLabel::setText( QString text ) {
265 | lbl->setText( text );
266 | }
267 |
268 |
269 | void SessionLabel::setAlignment( Qt::Alignment a ) {
270 | lbl->setAlignment( a );
271 | }
272 |
273 |
274 | void SessionLabel::switchToNextSession() {
275 | SessionName::switchToNextSession();
276 | setText( mSessionList.at( curSess ).name );
277 | }
278 |
279 |
280 | void SessionLabel::switchToPreviousSession() {
281 | SessionName::switchToPreviousSession();
282 | setText( mSessionList.at( curSess ).name );
283 | }
284 |
285 |
286 | void SessionLabel::setShowNavButtons( bool show ) {
287 | if ( show ) {
288 | prevBtn->show();
289 | nextBtn->show();
290 | }
291 |
292 | else {
293 | prevBtn->hide();
294 | nextBtn->hide();
295 | }
296 | }
297 |
298 |
299 | void SessionLabel::setIconSize( QSize size ) {
300 | nextBtn->setIconSize( size );
301 | prevBtn->setIconSize( size );
302 | }
303 |
304 |
305 | void SessionLabel::setFixedHeight( int h ) {
306 | QWidget::setFixedHeight( h );
307 |
308 | nextBtn->setFixedWidth( h );
309 | nextBtn->setFixedHeight( h );
310 |
311 | prevBtn->setFixedWidth( h );
312 | prevBtn->setFixedHeight( h );
313 | }
314 |
--------------------------------------------------------------------------------
/src/widgets/session/session.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | typedef struct session_t {
26 | QString name;
27 | QString icon;
28 | QString type;
29 | QString exec;
30 | QString file;
31 | } Session;
32 | Q_DECLARE_METATYPE( Session );
33 |
34 | typedef QList Sessions;
35 |
36 | class SessionEdit : public QLineEdit {
37 | Q_OBJECT;
38 |
39 | public:
40 | SessionEdit();
41 | };
42 |
43 | class SessionName {
44 | public:
45 | SessionName( bool );
46 |
47 | void switchToNextSession();
48 | void switchToPreviousSession();
49 |
50 | Sessions sessions();
51 | Session currentSession();
52 |
53 | protected:
54 | Sessions mSessionList;
55 | int curSess = 0;
56 | };
57 |
58 | class SessionCombo : public QComboBox, public SessionName {
59 | Q_OBJECT;
60 |
61 | public:
62 | SessionCombo( bool );
63 |
64 | void switchToNextSession();
65 | void switchToPreviousSession();
66 | };
67 |
68 | class SessionList : public QListWidget, public SessionName {
69 | Q_OBJECT;
70 |
71 | public:
72 | SessionList( bool );
73 |
74 | void switchToNextSession();
75 | void switchToPreviousSession();
76 | };
77 |
78 | class SessionLabel : public QWidget, public SessionName {
79 | Q_OBJECT;
80 |
81 | public:
82 | SessionLabel( bool );
83 |
84 | void setText( QString );
85 |
86 | void setAlignment( Qt::Alignment );
87 |
88 | void switchToNextSession();
89 | void switchToPreviousSession();
90 |
91 | void setShowNavButtons( bool show );
92 |
93 | void setIconSize( QSize );
94 |
95 | void setFixedHeight( int );
96 |
97 | private:
98 | QLabel *lbl;
99 | QToolButton *prevBtn, *nextBtn;
100 | };
101 |
--------------------------------------------------------------------------------
/src/widgets/user/user.hpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2020-2022 Britanicus
3 | * This file is a part of QtGreet project (https://gitlab.com/marcusbritanicus/QtGreet)
4 | *
5 | * This program is free software; you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation; either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU General Public License
16 | * along with this program; if not, write to the Free Software
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 | * MA 02110-1301, USA.
19 | **/
20 |
21 | #pragma once
22 |
23 | #include
24 |
25 | typedef struct user_t {
26 | QString username;
27 | uint uid;
28 | uint gid;
29 | QString name;
30 | QString homePath;
31 | QString shell;
32 | QString icon;
33 | } User;
34 |
35 | Q_DECLARE_METATYPE( User );
36 |
37 | typedef QList Users;
38 |
39 | class UserName {
40 | public:
41 | UserName();
42 |
43 | Users users();
44 | User currentUser();
45 |
46 | virtual void switchToNextUser();
47 | virtual void switchToPreviousUser();
48 |
49 | /**
50 | * Set the current user based on the struct user_t.
51 | * Here we compare the username and user id.
52 | */
53 | virtual bool setCurrentUser( User usr );
54 |
55 | /**
56 | * Set the current user based on the user id.
57 | * Here we compare only the user id.
58 | */
59 | virtual bool setCurrentUser( uint uid );
60 |
61 | protected:
62 | Users mUserList;
63 | int curUser = -1;
64 | };
65 |
66 | class UserEdit : public QLineEdit, public UserName {
67 | Q_OBJECT;
68 |
69 | public:
70 | UserEdit();
71 |
72 | void switchToNextUser();
73 | void switchToPreviousUser();
74 |
75 | bool setCurrentUser( User usr );
76 | bool setCurrentUser( uint uid );
77 | };
78 |
79 | class UserCombo : public QComboBox, public UserName {
80 | Q_OBJECT;
81 |
82 | public:
83 | UserCombo();
84 |
85 | void switchToNextUser();
86 | void switchToPreviousUser();
87 |
88 | bool setCurrentUser( User usr );
89 | bool setCurrentUser( uint uid );
90 | };
91 |
92 | class UserList : public QListWidget, public UserName {
93 | Q_OBJECT;
94 |
95 | public:
96 | UserList();
97 |
98 | void switchToNextUser();
99 | void switchToPreviousUser();
100 |
101 | bool setCurrentUser( User usr );
102 | bool setCurrentUser( uint uid );
103 | };
104 |
105 | class UserLabel : public QWidget, public UserName {
106 | Q_OBJECT;
107 |
108 | public:
109 | UserLabel();
110 |
111 | void setText( QString );
112 |
113 | void setAlignment( Qt::Alignment );
114 |
115 | void switchToNextUser();
116 | void switchToPreviousUser();
117 |
118 | bool setCurrentUser( User usr );
119 | bool setCurrentUser( uint uid );
120 |
121 | void setShowNavButtons( bool show );
122 | void setIconSize( QSize );
123 |
124 | void setFixedHeight( int );
125 |
126 | private:
127 | QLabel *lbl;
128 | QToolButton *prevBtn, *nextBtn;
129 | };
130 |
--------------------------------------------------------------------------------
/src/widgets/videobg/MpvWidget.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "MpvWidget.hpp"
6 |
7 | static void wakeup( void *ctx ) {
8 | QMetaObject::invokeMethod( (MpvWidget *)ctx, "on_mpv_events", Qt::QueuedConnection );
9 | }
10 |
11 |
12 | static void *get_proc_address( void *ctx, const char *name ) {
13 | Q_UNUSED( ctx );
14 | QOpenGLContext *glctx = QOpenGLContext::currentContext();
15 |
16 | if ( !glctx ) {
17 | return nullptr;
18 | }
19 |
20 | return reinterpret_cast(glctx->getProcAddress( QByteArray( name ) ) );
21 | }
22 |
23 |
24 | MpvWidget::MpvWidget( QWidget *parent ) : QOpenGLWidget( parent ) {
25 | mpv = mpv_create();
26 |
27 | if ( !mpv ) {
28 | throw std::runtime_error( "could not create mpv context" );
29 | }
30 |
31 | mpv_set_option_string( mpv, "terminal", "no" );
32 | mpv_set_option_string( mpv, "msg-level", "all=error" );
33 |
34 | if ( mpv_initialize( mpv ) < 0 ) {
35 | throw std::runtime_error( "could not initialize mpv context" );
36 | }
37 |
38 | Mpv::Qt::set_option_variant( mpv, "hwdec", "auto" );
39 |
40 | mpv_observe_property( mpv, 0, "duration", MPV_FORMAT_DOUBLE );
41 | mpv_observe_property( mpv, 0, "time-pos", MPV_FORMAT_DOUBLE );
42 | mpv_set_wakeup_callback( mpv, wakeup, this );
43 | }
44 |
45 |
46 | MpvWidget::~MpvWidget() {
47 | makeCurrent();
48 |
49 | if ( mpv_gl ) {
50 | mpv_render_context_free( mpv_gl );
51 | }
52 |
53 | mpv_terminate_destroy( mpv );
54 | }
55 |
56 |
57 | void MpvWidget::command( const QVariant& params ) {
58 | Mpv::Qt::command_variant( mpv, params );
59 | }
60 |
61 |
62 | void MpvWidget::setProperty( const QString& name, const QVariant& value ) {
63 | Mpv::Qt::set_property_variant( mpv, name, value );
64 | }
65 |
66 |
67 | QVariant MpvWidget::getProperty( const QString& name ) const {
68 | return Mpv::Qt::get_property_variant( mpv, name );
69 | }
70 |
71 |
72 | void MpvWidget::initializeGL() {
73 | mpv_opengl_init_params gl_init_params[ 1 ] = { get_proc_address, nullptr };
74 | mpv_render_param params[]{
75 | { MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL) },
76 | { MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params },
77 | { MPV_RENDER_PARAM_INVALID, nullptr }
78 | };
79 |
80 | if ( mpv_render_context_create( &mpv_gl, mpv, params ) < 0 ) {
81 | throw std::runtime_error( "failed to initialize mpv GL context" );
82 | }
83 |
84 | mpv_render_context_set_update_callback( mpv_gl, MpvWidget::on_update, reinterpret_cast(this) );
85 | }
86 |
87 |
88 | void MpvWidget::paintGL() {
89 | mpv_opengl_fbo mpfbo{ static_cast(defaultFramebufferObject() ), width(), height(), 0 };
90 | int flip_y{ 1 };
91 |
92 | mpv_render_param params[] = {
93 | { MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo },
94 | { MPV_RENDER_PARAM_FLIP_Y, &flip_y },
95 | { MPV_RENDER_PARAM_INVALID, nullptr }
96 | };
97 |
98 | mpv_render_context_render( mpv_gl, params );
99 | }
100 |
101 |
102 | void MpvWidget::on_mpv_events() {
103 | // Process all events, until the event queue is empty.
104 | while ( mpv ) {
105 | mpv_event *event = mpv_wait_event( mpv, 0 );
106 |
107 | if ( event->event_id == MPV_EVENT_NONE ) {
108 | break;
109 | }
110 |
111 | handle_mpv_event( event );
112 | }
113 | }
114 |
115 |
116 | void MpvWidget::handle_mpv_event( mpv_event *event ) {
117 | switch ( event->event_id ) {
118 | case MPV_EVENT_PROPERTY_CHANGE: {
119 | mpv_event_property *prop = (mpv_event_property *)event->data;
120 |
121 | if ( strcmp( prop->name, "time-pos" ) == 0 ) {
122 | if ( prop->format == MPV_FORMAT_DOUBLE ) {
123 | double time = *(double *)prop->data;
124 | Q_EMIT positionChanged( time );
125 | }
126 | }
127 | else if ( strcmp( prop->name, "duration" ) == 0 ) {
128 | if ( prop->format == MPV_FORMAT_DOUBLE ) {
129 | double time = *(double *)prop->data;
130 | Q_EMIT durationChanged( time );
131 | }
132 | }
133 |
134 | break;
135 | }
136 |
137 | default: { }
138 | // Ignore uninteresting or unknown events.
139 | }
140 | }
141 |
142 |
143 | void MpvWidget::maybeUpdate() {
144 | if ( window()->isMinimized() ) {
145 | makeCurrent();
146 | paintGL();
147 | context()->swapBuffers( context()->surface() );
148 | doneCurrent();
149 | }
150 | else {
151 | update();
152 | }
153 | }
154 |
155 |
156 | void MpvWidget::on_update( void *ctx ) {
157 | QMetaObject::invokeMethod( (MpvWidget *)ctx, "maybeUpdate" );
158 | }
159 |
--------------------------------------------------------------------------------
/src/widgets/videobg/MpvWidget.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "MpvHelper.hpp"
8 |
9 | class MpvWidget : public QOpenGLWidget {
10 | Q_OBJECT
11 |
12 | public:
13 | MpvWidget( QWidget *parent );
14 | ~MpvWidget();
15 |
16 | void command( const QVariant& params );
17 | void setProperty( const QString& name, const QVariant& value );
18 | QVariant getProperty( const QString& name ) const;
19 |
20 | QSize minimumSizeHint() const { return QSize( 640, 480 ); }
21 |
22 | Q_SIGNALS:
23 | void durationChanged( int value );
24 | void positionChanged( int value );
25 |
26 | protected:
27 | void initializeGL() Q_DECL_OVERRIDE;
28 | void paintGL() Q_DECL_OVERRIDE;
29 |
30 | private Q_SLOTS:
31 | void on_mpv_events();
32 | void maybeUpdate();
33 |
34 | private:
35 | void handle_mpv_event( mpv_event *event );
36 | static void on_update( void *ctx );
37 |
38 | mpv_handle *mpv;
39 | mpv_render_context *mpv_gl;
40 | };
41 |
--------------------------------------------------------------------------------
/themes/LytMgr.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 |
3 | from PyQt5.QtCore import *
4 | from PyQt5.QtGui import *
5 | from PyQt5.QtWidgets import *
6 |
--------------------------------------------------------------------------------
/themes/aerial/4k.m3u:
--------------------------------------------------------------------------------
1 | http://sylvan.apple.com/Aerials/2x/Videos/comp_CH_C007_C011_PSNK_v02_SDR_PS_FINAL_20180709_SDR_4K_HEVC.mov
2 | http://sylvan.apple.com/Aerials/2x/Videos/comp_CH_C002_C005_PSNK_v05_SDR_PS_FINAL_20180709_SDR_4K_HEVC.mov
3 | http://sylvan.apple.com/Aerials/2x/Videos/comp_CH_C007_C004_PSNK_v02_SDR_PS_FINAL_20180709_SDR_4K_HEVC.mov
4 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D008_C010_4K_SDR_HEVC.mov
5 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D001_C001_4K_SDR_HEVC.mov
6 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C010_4K_SDR_HEVC.mov
7 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D002_C003_4K_SDR_HEVC.mov
8 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D001_C005_4K_SDR_HEVC.mov
9 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_4K_SDR_HEVC.mov
10 | http://sylvan.apple.com/Aerials/2x/Videos/GL_G004_C010_4K_SDR_HEVC.mov
11 | http://sylvan.apple.com/Aerials/2x/Videos/GL_G002_C002_4K_SDR_HEVC.mov
12 | http://sylvan.apple.com/Aerials/2x/Videos/HK_B005_C011_4K_SDR_HEVC.mov
13 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C010_4K_SDR_HEVC.mov
14 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C013_4K_SDR_HEVC.mov
15 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C001_4K_SDR_HEVC.mov
16 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C008_4K_SDR_HEVC.mov
17 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT312_162NC_139M_1041_AFRICA_NIGHT_v14_SDR_FINAL_20180706_SDR_4K_HEVC.mov
18 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A103_C002_0205DG_v12_SDR_FINAL_20180706_SDR_4K_HEVC.mov
19 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT306_139NC_139J_3066_CALI_TO_VEGAS_v07_SDR_FINAL_22062018_SDR_4K_HEVC.mov
20 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A108_C001_v09_SDR_FINAL_22062018_SDR_4K_HEVC.mov
21 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT308_139K_142NC_CARIBBEAN_DAY_v09_SDR_FINAL_22062018_SDR_4K_HEVC.mov
22 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT329_113NC_396B_1105_CHINA_v04_SDR_FINAL_20180706_F900F2700_SDR_4K_HEVC.mov
23 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A083_C002_1130KZ_v04_SDR_PS_FINAL_20180725_SDR_4K_HEVC.mov
24 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT329_117NC_401C_1037_IRELAND_TO_ASIA_v48_SDR_PS_FINAL_20180725_F0F6300_SDR_4K_HEVC.mov
25 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT026_363A_103NC_E1027_KOREA_JAPAN_NIGHT_v17_SDR_FINAL_25062018_SDR_4K_HEVC.mov
26 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A105_C003_0212CT_FLARE_v10_SDR_PS_FINAL_20180711_SDR_4K_HEVC.mov
27 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A009_C001_010181A_v09_SDR_PS_FINAL_20180725_SDR_4K_HEVC.mov
28 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A114_C001_0305OT_v10_SDR_FINAL_22062018_SDR_4K_HEVC.mov
29 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A001_C004_1207W5_v23_SDR_FINAL_20180706_SDR_4K_HEVC.mov
30 | http://sylvan.apple.com/Aerials/2x/Videos/LW_L001_C006_4K_SDR_HEVC.mov
31 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A006_C008_4K_SDR_HEVC.mov
32 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A009_C009_4K_SDR_HEVC.mov
33 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A008_C004_4K_SDR_HEVC.mov
34 | http://sylvan.apple.com/Aerials/2x/Videos/comp_LA_A006_C004_v01_SDR_FINAL_PS_20180730_SDR_4K_HEVC.mov
35 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A005_C009_4K_SDR_HEVC.mov
36 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A011_C003_4K_SDR_HEVC.mov
37 |
--------------------------------------------------------------------------------
/themes/aerial/all_sd.m3u:
--------------------------------------------------------------------------------
1 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b2-1.mov
2 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b5-1.mov
3 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b6-1.mov
4 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//comp_GL_G010_C006_v08_6Mbps.mov
5 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b1-1.mov
6 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b2-2.mov
7 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b4-1.mov
8 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b6-2.mov
9 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b7-1.mov
10 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b8-1.mov
11 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b1-2.mov
12 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b3-1.mov
13 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b5-2.mov
14 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b6-3.mov
15 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b1-3.mov
16 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b2-3.mov
17 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b3-2.mov
18 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b4-2.mov
19 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b7-2.mov
20 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b1-4.mov
21 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b2-4.mov
22 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b3-3.mov
23 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b4-3.mov
24 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b5-3.mov
25 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b6-4.mov
26 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b7-3.mov
27 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b8-2.mov
28 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b8-3.mov
29 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b9-2.mov
30 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b9-3.mov
31 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos//b10-3.mov
32 | http://sylvan.apple.com/Aerials/2x/Videos//comp_CH_C007_C011_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov
33 | http://sylvan.apple.com/Aerials/2x/Videos//comp_CH_C002_C005_PSNK_v05_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov
34 | http://sylvan.apple.com/Aerials/2x/Videos//comp_CH_C007_C004_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov
35 | http://sylvan.apple.com/Aerials/2x/Videos//DB_D008_C010_2K_SDR_HEVC.mov
36 | http://sylvan.apple.com/Aerials/2x/Videos//DB_D001_C001_2K_SDR_HEVC.mov
37 | http://sylvan.apple.com/Aerials/2x/Videos//DB_D011_C010_2K_SDR_HEVC.mov
38 | http://sylvan.apple.com/Aerials/2x/Videos//DB_D002_C003_2K_SDR_HEVC.mov
39 | http://sylvan.apple.com/Aerials/2x/Videos//DB_D001_C005_2K_SDR_HEVC.mov
40 | http://sylvan.apple.com/Aerials/2x/Videos//DB_D011_C009_2K_SDR_HEVC.mov
41 | http://sylvan.apple.com/Aerials/2x/Videos//GL_G004_C010_2K_SDR_HEVC.mov
42 | http://sylvan.apple.com/Aerials/2x/Videos//GL_G002_C002_2K_SDR_HEVC.mov
43 | http://sylvan.apple.com/Aerials/2x/Videos//HK_B005_C011_2K_SDR_HEVC.mov
44 | http://sylvan.apple.com/Aerials/2x/Videos//HK_H004_C010_2K_SDR_HEVC.mov
45 | http://sylvan.apple.com/Aerials/2x/Videos//HK_H004_C013_2K_SDR_HEVC.mov
46 | http://sylvan.apple.com/Aerials/2x/Videos//HK_H004_C001_2K_SDR_HEVC.mov
47 | http://sylvan.apple.com/Aerials/2x/Videos//HK_H004_C008_2K_SDR_HEVC.mov
48 | http://sylvan.apple.com/Aerials/2x/Videos//comp_GMT312_162NC_139M_1041_AFRICA_NIGHT_v14_SDR_FINAL_20180706_SDR_2K_HEVC.mov
49 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A103_C002_0205DG_v12_SDR_FINAL_20180706_SDR_2K_HEVC.mov
50 | http://sylvan.apple.com/Aerials/2x/Videos//comp_GMT306_139NC_139J_3066_CALI_TO_VEGAS_v07_SDR_FINAL_22062018_SDR_4K_HEVC.mov
51 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A108_C001_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov
52 | http://sylvan.apple.com/Aerials/2x/Videos//comp_GMT308_139K_142NC_CARIBBEAN_DAY_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov
53 | http://sylvan.apple.com/Aerials/2x/Videos//comp_GMT329_113NC_396B_1105_CHINA_v04_SDR_FINAL_20180706_F900F2700_SDR_2K_HEVC.mov
54 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A083_C002_1130KZ_v04_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov
55 | http://sylvan.apple.com/Aerials/2x/Videos//comp_GMT329_117NC_401C_1037_IRELAND_TO_ASIA_v48_SDR_PS_FINAL_20180725_F0F6300_SDR_2K_HEVC.mov
56 | http://sylvan.apple.com/Aerials/2x/Videos//comp_GMT026_363A_103NC_E1027_KOREA_JAPAN_NIGHT_v17_SDR_FINAL_25062018_SDR_2K_HEVC.mov
57 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A105_C003_0212CT_FLARE_v10_SDR_PS_FINAL_20180711_SDR_2K_HEVC.mov
58 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A009_C001_010181A_v09_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov
59 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A114_C001_0305OT_v10_SDR_FINAL_22062018_SDR_2K_HEVC.mov
60 | http://sylvan.apple.com/Aerials/2x/Videos//comp_A001_C004_1207W5_v23_SDR_FINAL_20180706_SDR_2K_HEVC.mov
61 | http://sylvan.apple.com/Aerials/2x/Videos//LA_A006_C008_2K_SDR_HEVC.mov
62 | http://sylvan.apple.com/Aerials/2x/Videos//LA_A009_C009_2K_SDR_HEVC.mov
63 | http://sylvan.apple.com/Aerials/2x/Videos//LA_A008_C004_2K_SDR_HEVC.mov
64 | http://sylvan.apple.com/Aerials/2x/Videos//comp_LA_A006_C004_v01_SDR_FINAL_PS_20180730_SDR_2K_HEVC.mov
65 | http://sylvan.apple.com/Aerials/2x/Videos//LA_A005_C009_2K_SDR_HEVC.mov
66 | http://sylvan.apple.com/Aerials/2x/Videos//LA_A011_C003_2K_SDR_HEVC.mov
67 |
--------------------------------------------------------------------------------
/themes/aerial/day.m3u:
--------------------------------------------------------------------------------
1 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b2-1.mov
2 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b6-1.mov
3 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b1-1.mov
4 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b2-2.mov
5 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b4-1.mov
6 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b7-1.mov
7 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b5-2.mov
8 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b1-3.mov
9 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b3-2.mov
10 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b7-2.mov
11 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b8-2.mov
12 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b4-3.mov
13 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b8-3.mov
14 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b9-3.mov
15 | http://sylvan.apple.com/Aerials/2x/Videos/comp_CH_C007_C011_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov
16 | http://sylvan.apple.com/Aerials/2x/Videos/comp_CH_C002_C005_PSNK_v05_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov
17 | http://sylvan.apple.com/Aerials/2x/Videos/comp_CH_C007_C004_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov
18 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D008_C010_2K_SDR_HEVC.mov
19 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D001_C001_2K_SDR_HEVC.mov
20 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D002_C003_2K_SDR_HEVC.mov
21 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D001_C005_2K_SDR_HEVC.mov
22 | http://sylvan.apple.com/Aerials/2x/Videos/GL_G004_C010_2K_SDR_HEVC.mov
23 | http://sylvan.apple.com/Aerials/2x/Videos/GL_G002_C002_2K_SDR_HEVC.mov
24 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C010_2K_SDR_HEVC.mov
25 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C013_2K_SDR_HEVC.mov
26 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C008_2K_SDR_HEVC.mov
27 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A103_C002_0205DG_v12_SDR_FINAL_20180706_SDR_2K_HEVC.mov
28 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A108_C001_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov
29 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT308_139K_142NC_CARIBBEAN_DAY_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov
30 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A105_C003_0212CT_FLARE_v10_SDR_PS_FINAL_20180711_SDR_2K_HEVC.mov
31 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A009_C001_010181A_v09_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov
32 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A114_C001_0305OT_v10_SDR_FINAL_22062018_SDR_2K_HEVC.mov
33 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A001_C004_1207W5_v23_SDR_FINAL_20180706_SDR_2K_HEVC.mov
34 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A006_C008_2K_SDR_HEVC.mov
35 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A008_C004_2K_SDR_HEVC.mov
36 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A005_C009_2K_SDR_HEVC.mov
37 |
--------------------------------------------------------------------------------
/themes/aerial/index.theme:
--------------------------------------------------------------------------------
1 | [General]
2 | Name = Aerial
3 |
4 | [Files]
5 | Layout = layout.hjson
6 | StyleSheet = style.qss
7 |
8 | [Theme]
9 | Background = videobg
10 | BaseColor = ffffffff
11 | TextColor = ffffff
12 | Type = Video
13 |
14 | [videobg]
15 | File =
16 | Playlist = night.m3u
17 |
18 | [cache]
19 | Location = /var/tmp/qtgreet/aerial
20 |
--------------------------------------------------------------------------------
/themes/aerial/layout.hjson:
--------------------------------------------------------------------------------
1 | {
2 | Layout: {
3 | Direction: Vertical
4 | Keys: [ "R1", "R2" ]
5 | R1: [ "SessionName", "QLabel-1", "Stretch", "NumLock", "CapsLock" ]
6 | R2: [ "C1" ]
7 | C1: [ "Stretch", "Clock-1", "Clock-2", "QLabel-2", "R3", "R4" ]
8 | R3: [ "QLabel-3", "UserName", "Stretch" ]
9 | R4: [ "QLabel-4", "Password", "LoginButton", "Stretch" ]
10 | }
11 |
12 | Properties: {
13 | R1: {
14 | Height: 24
15 | }
16 | C1: {
17 | Spacing: 10
18 | Margins: 100
19 | Alignment: BL
20 | }
21 | R3: {
22 | Spacing: 0
23 | }
24 | R4: {
25 | Spacing: 0
26 | }
27 | SessionName: {
28 | Height: 24
29 | Type: Combo
30 | MaximumWidth: 270
31 | Font: Dejavu Sans, 12, Normal, Normal
32 | }
33 | QLabel-1: {
34 | Text: en_us
35 | Width: 80
36 | TextAlign: Right
37 | }
38 | NumLock: {
39 | Font: Monospace, 12, Normal, Normal
40 | Width: 15
41 | Height: 24
42 | ToolTip: NumLock status
43 | }
44 | CapsLock: {
45 | Font: Monospace, 12, Normal, Normal
46 | Width: 15
47 | Height: 24
48 | ToolTip: CapsLock status
49 | }
50 | Clock-1: {
51 | Type: Time
52 | Font: Quicksand, 40, Normal, Normal
53 | Format: "HH : mm"
54 | Width: 300
55 | }
56 | Clock-2: {
57 | Type: Date
58 | Font: Quicksand, 14, Normal, Normal
59 | Format: dddd, MMMM dd, yyyy
60 | Width: 300
61 | }
62 | QLabel-2: {
63 | Text: " "
64 | Width: 75
65 | }
66 | QLabel-3: {
67 | Text: "Username"
68 | Width: 75
69 | }
70 | QLabel-4: {
71 | Text: "Password"
72 | Width: 75
73 | Height: 25
74 | }
75 | UserName: {
76 | Type: LineEdit
77 | Width: 225
78 | Height: 25
79 | }
80 | Password: {
81 | Width: 200
82 | Height: 25
83 | }
84 | LoginButton: {
85 | Type: ToolButton
86 | Width: 25
87 | Height: 25
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/themes/aerial/night.m3u:
--------------------------------------------------------------------------------
1 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b5-1.mov
2 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/comp_GL_G010_C006_v08_6Mbps.mov
3 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b6-2.mov
4 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b8-1.mov
5 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b1-2.mov
6 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b3-1.mov
7 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b6-3.mov
8 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b2-3.mov
9 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b4-2.mov
10 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b1-4.mov
11 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b2-4.mov
12 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b3-3.mov
13 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b5-3.mov
14 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b6-4.mov
15 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b7-3.mov
16 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b9-2.mov
17 | http://a1.v2.phobos.apple.com.edgesuite.net/us/r1000/000/Features/atv/AutumnResources/videos/b10-3.mov
18 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C010_2K_SDR_HEVC.mov
19 | http://sylvan.apple.com/Aerials/2x/Videos/DB_D011_C009_2K_SDR_HEVC.mov
20 | http://sylvan.apple.com/Aerials/2x/Videos/HK_B005_C011_2K_SDR_HEVC.mov
21 | http://sylvan.apple.com/Aerials/2x/Videos/HK_H004_C001_2K_SDR_HEVC.mov
22 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT312_162NC_139M_1041_AFRICA_NIGHT_v14_SDR_FINAL_20180706_SDR_2K_HEVC.mov
23 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT306_139NC_139J_3066_CALI_TO_VEGAS_v07_SDR_FINAL_22062018_SDR_4K_HEVC.mov
24 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT329_113NC_396B_1105_CHINA_v04_SDR_FINAL_20180706_F900F2700_SDR_2K_HEVC.mov
25 | http://sylvan.apple.com/Aerials/2x/Videos/comp_A083_C002_1130KZ_v04_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov
26 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT329_117NC_401C_1037_IRELAND_TO_ASIA_v48_SDR_PS_FINAL_20180725_F0F6300_SDR_2K_HEVC.mov
27 | http://sylvan.apple.com/Aerials/2x/Videos/comp_GMT026_363A_103NC_E1027_KOREA_JAPAN_NIGHT_v17_SDR_FINAL_25062018_SDR_2K_HEVC.mov
28 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A009_C009_2K_SDR_HEVC.mov
29 | http://sylvan.apple.com/Aerials/2x/Videos/comp_LA_A006_C004_v01_SDR_FINAL_PS_20180730_SDR_2K_HEVC.mov
30 | http://sylvan.apple.com/Aerials/2x/Videos/LA_A011_C003_2K_SDR_HEVC.mov
31 |
--------------------------------------------------------------------------------
/themes/aerial/style.qss:
--------------------------------------------------------------------------------
1 | QWidget {
2 | color: #ffffff;
3 | }
4 |
5 | #Panel {
6 | background-color: rgba(0, 0, 0, 60);
7 | border-bottom: 1px solid rgba(80, 80, 80, 60);
8 | }
9 |
10 | #Sidebar {
11 | background-color: rgba(0, 0, 0, 30);
12 | border-right: 1px solid rgba(80, 80, 80, 60);
13 | }
14 |
15 | QPushButton:hover {
16 | background-color: rgba(255, 255, 255, 30);
17 | }
18 |
19 | QPushButton:pressed {
20 | background-color: rgba(255, 255, 255, 10);
21 | padding-top: 1px;
22 | padding-left: 1px;
23 | }
24 |
25 | QToolButton {
26 | border: none;
27 | border-radius: 0px;
28 | background-color: rgba(255, 255, 255, 60);
29 | }
30 |
31 | QToolButton:hover {
32 | background-color: rgba(255, 255, 255, 30);
33 | }
34 |
35 | QToolButton:pressed {
36 | background-color: rgba(255, 255, 255, 10);
37 | padding-top: 2px;
38 | padding-left: 2px;
39 | }
40 |
41 | QToolButton#nav {
42 | border: 1px solid gray;
43 | border-radius: 18px;
44 | padding-top: 1px;
45 | padding-left: 1px;
46 | }
47 |
48 | QToolButton#Halt {
49 | border: 1px solid gray;
50 | border-radius: 0px;
51 | border-top-right-radius: 18px;
52 | border-bottom-right-radius: 18px;
53 | padding-top: 1px;
54 | padding-left: 1px;
55 | }
56 |
57 | QToolButton#Reboot {
58 | border: 1px solid gray;
59 | border-radius: 0px;
60 | border-top-left-radius: 18px;
61 | border-bottom-left-radius: 18px;
62 | padding-top: 1px;
63 | padding-left: 1px;
64 | }
65 |
66 | QLineEdit {
67 | background-color: rgba(0, 0, 0, 60);
68 | border: none;
69 | border-radius: 0px;
70 | padding-left: 10px;
71 | padding-right: 10px;
72 | }
73 |
74 | QListWidget {
75 | margin-bottom: 2px;
76 | background-color: rgba(255, 255, 255, 60);
77 | border: none;
78 | }
79 |
80 | QWidget#widget {
81 | border: 2px solid gray;
82 | border-radius: 5px;
83 | }
84 |
85 | QWidget#OverLay {
86 | background-color: rgba(0, 0, 0, 230);
87 | }
88 |
89 | QLabel#UserIcon {
90 | border: 2px solid gray;
91 | border-radius: 6px;
92 | }
93 |
94 | QComboBox {
95 | border: none;
96 | background-color: rgba(0, 0, 0, 0);
97 | }
98 |
99 | QComboBox::drop-down {
100 | subcontrol-origin: padding;
101 | subcontrol-position: top right;
102 | width: 27px;
103 | background-color: rgba(255, 255, 255, 0);
104 | border: none;
105 | }
106 |
107 | QComboBox::down-arrow {
108 | image: url(:/icons/arrow-down.png);
109 | width: 18px;
110 | height: 18px;
111 | }
112 |
113 | QComboBox::down-arrow:on { /* shift the arrow when popup is open */
114 | top: 1px;
115 | left: 1px;
116 | }
117 |
118 | QComboBox QAbstractItemView {
119 | background-color: rgba(0, 0, 0, 60);
120 | }
121 |
122 | QMessageBox {
123 | background-color: rgba(0, 0, 0, 230);
124 | border: 2px solid gray;
125 | border-radius: 5px;
126 | }
127 |
--------------------------------------------------------------------------------
/themes/compact/index.theme:
--------------------------------------------------------------------------------
1 | [General]
2 | Name = Compact
3 |
4 | [Files]
5 | Layout = layout.hjson
6 | StyleSheet = style.qss
7 |
8 | [Theme]
9 | Background = ../../backgrounds/Water.svg
10 | BaseColor = ffffffff
11 | TextColor = ffffff
12 | Type = Image
13 |
--------------------------------------------------------------------------------
/themes/compact/layout.hjson:
--------------------------------------------------------------------------------
1 | {
2 | Layout: {
3 | Direction: Vertical
4 | Keys: [ "R1" ]
5 | R1: [ "C1", "C2" ]
6 | C1: [ "Logo", "Stretch", "UserName-1", "Stretch", "Stretch", "R2" ]
7 | C2: [ "R3", "Stretch", "R4", "R5", "R6", "R7", "Stretch", "Stretch", "R8" ]
8 | R2: [ "Stretch", "PowerButton-1", "PowerButton-2", "PowerButton-3", "PowerButton-4", "Stretch" ]
9 | R3: [ "Battery", "Stretch", "Clock-1", "Stretch", "NumLock", "CapsLock" ]
10 | R4: [ "Stretch", "UserIcon", "Stretch" ]
11 | R5: [ "Stretch", "UserName-2", "Stretch" ]
12 | R6: [ "Stretch", "SessionName", "Stretch" ]
13 | R7: [ "Stretch", "Password", "LoginButton", "Stretch" ]
14 | R8: [ "Stretch", "Clock-2", "Stretch" ]
15 | Margins: 0.25
16 | Spacing: 0
17 | }
18 |
19 | Properties: {
20 | R1: {
21 | Height: 0.5
22 | Width: 0.5
23 | }
24 | C1: {
25 | Wdith: 0.15
26 | BGColor: {
27 | Red:0.29
28 | Green: 0.16
29 | Blue: 0.16
30 | Alpha: 0.72
31 | }
32 | Margins: [ 0, 0, 3, 3 ]
33 | }
34 | C2: {
35 | Width: 0.35
36 | BGColor: {
37 | Red:0.4
38 | Green: 0.81
39 | Blue: 0.99
40 | Alpha: 0.72
41 | }
42 | Spacing: 10
43 | Margins: 3
44 | }
45 | R3: {
46 | Height: 24
47 | }
48 | R4: {
49 | Alignment: MM
50 | }
51 | R5: {
52 | Alignment: MM
53 | }
54 | R7: {
55 | Alignment: MM
56 | Spacing: 5
57 | }
58 | Logo: {
59 | Type: Label
60 | FixedWidth: 0.15
61 | FixedHeight: 0.1
62 | IconSize: 72
63 | }
64 | UserName-1: {
65 | Type: List
66 | Width: 0.15
67 | Height: 0.25
68 | IconSize: 24
69 | },
70 | Battery: {
71 | Width: 22
72 | Height: 22
73 | },
74 | Clock-1: {
75 | Type: Time
76 | Format: hh:mm:ss AP
77 | Font: Quicksand, 10, Bold, Normal
78 | },
79 | Clock-2: {
80 | Type: Date
81 | Format: dddd, MMM dd, yyyy
82 | FixedHeight: 27
83 | Font: Quicksand, 10, Bold, Normal
84 | },
85 | NumLock: {
86 | Font: monospace, 11, Normal, Normal
87 | Width: 15
88 | Height: 36
89 | ToolTip: NumLock status
90 | },
91 | CapsLock: {
92 | Font: monospace, 11, Normal, Normal
93 | Width: 15
94 | Height: 36
95 | ToolTip: CapsLock status
96 | },
97 | UserIcon: {
98 | Type: Label
99 | Height: 72
100 | Width: 72
101 | Alignment: Center
102 | },
103 | UserName-2: {
104 | Type: Label
105 | Width: 0.18
106 | Height: 36
107 | FixedHeight: 27
108 | Font: DejaVu Sans, 12, Bold, Italic
109 | TextAlign: Center
110 | ShowNav: false
111 | },
112 | Password: {
113 | Width: 0.18
114 | Height: 36
115 | },
116 | LoginButton: {
117 | Width: 36
118 | Height: 36
119 | Type: ToolButton
120 | TextAlign: Center
121 | IconSize: 16
122 | },
123 | SessionName: {
124 | Type: Combo
125 | Width: 0.12
126 | Height: 27
127 | TextAlign: Center
128 | IconSize: 24
129 | },
130 | PowerButton-1: {
131 | Type: Suspend
132 | FixedWidth: 32
133 | FixedHeight: 32
134 | IconSize: 36
135 | },
136 | PowerButton-2: {
137 | Type: Hibernate
138 | FixedWidth: 32
139 | FixedHeight: 32
140 | },
141 | PowerButton-3: {
142 | Type: Halt
143 | FixedWidth: 32
144 | FixedHeight: 32
145 | },
146 | PowerButton-4: {
147 | Type: Reboot
148 | FixedWidth: 32
149 | FixedHeight: 32
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/themes/compact/style.qss:
--------------------------------------------------------------------------------
1 | QWidget {
2 | color: white;
3 | }
4 |
5 | QWidget#OverLay {
6 | background-color: rgba(0, 0, 0, 230);
7 | }
8 |
9 | QToolButton {
10 | border: none;
11 | border-radius: 3px;
12 | }
13 |
14 | QToolButton:hover {
15 | background-color: rgba(60, 60, 60, 90);
16 | border: none;
17 | border-radius: 3px;
18 | }
19 |
20 | QToolButton:focus {
21 | background-color: rgba(60, 60, 60, 120);
22 | border-radius: 3px;
23 | border-left: 2px solid palette(Highlight);
24 | }
25 |
26 | QToolButton:pressed {
27 | background-color: rgba(60, 60, 60, 120);
28 | border-radius: 3px;
29 | padding-top: 1px;
30 | padding-left: 1px;
31 | }
32 |
33 | QToolButton#SessionName {
34 | background-color: rgba(60, 60, 60, 60);
35 | }
36 |
37 | QToolButton#LoginButton {
38 | background-color: rgba(60, 60, 60, 60);
39 | }
40 |
41 | QToolButton#SessionName:pressed {
42 | background-color: rgba(60, 60, 60, 120);
43 | }
44 |
45 | QToolButton#LoginButton:pressed {
46 | background-color: rgba(60, 60, 60, 120);
47 | }
48 |
49 | #Password {
50 | background-color: rgba(60, 60, 60, 60);
51 | border-radius: 3px;
52 | }
53 |
54 | #Password:focus {
55 | background-color: rgba(60, 60, 60, 90);
56 | border-radius: 3px;
57 | border-left: 2px solid palette(Highlight);
58 | }
59 |
60 | #UserList {
61 | background-color: transparent;
62 | border: none;
63 | font-size: 10pt;
64 | }
65 |
66 | #UserList::item:focus {
67 | border-right: 2px solid palette(Highlight);
68 | font-weight: bold;
69 | }
70 |
71 | #UserList::item:selected {
72 | background-color: #904A0404;
73 | color: yellow;
74 | }
75 |
76 | QComboBox {
77 | border: none;
78 | background-color: rgba(60, 60, 60, 60);
79 | }
80 |
81 | QComboBox::drop-down {
82 | subcontrol-origin: padding;
83 | subcontrol-position: top right;
84 | width: 27px;
85 | background-color: rgba(0, 0, 0, 0);
86 | border: none;
87 | }
88 |
89 | QComboBox::down-arrow {
90 | image: url(:/icons/arrow-down.png);
91 | width: 18px;
92 | height: 18px;
93 | }
94 |
95 | QComboBox::down-arrow:on { /* shift the arrow when popup is open */
96 | top: 1px;
97 | left: 1px;
98 | }
99 |
100 | QComboBox QAbstractItemView {
101 | background-color: rgba(0, 0, 0, 60);
102 | }
103 |
104 | QMessageBox {
105 | background-color: rgba(0, 0, 0, 230);
106 | border: 2px solid gray;
107 | border-radius: 5px;
108 | }
109 |
--------------------------------------------------------------------------------
/themes/default/index.theme:
--------------------------------------------------------------------------------
1 | [General]
2 | Name = Default
3 |
4 | [Files]
5 | Layout = layout.hjson
6 | StyleSheet = style.qss
7 |
8 | [Theme]
9 | Background = ../../backgrounds/BlurryBlob.png
10 | BaseColor = ffffffff
11 | TextColor = ffffff
12 | Type = Image
13 |
--------------------------------------------------------------------------------
/themes/default/layout.hjson:
--------------------------------------------------------------------------------
1 | {
2 | Layout: {
3 | Direction: Vertical
4 | Keys: [ "C1" ]
5 | C1: [ "R1", "Stretch", "R2", "Stretch", "R3", "R4", "Stretch", "R5", "Stretch", "R6", "R7", "Stretch", "R8" ]
6 | R1: [ "Battery", "Stretch", "Clock", "Stretch", "NumLock", "CapsLock" ]
7 | R2: [ "UserIcon" ]
8 | R3: [ "UserName" ]
9 | R4: [ "Password" ]
10 | R5: [ "LoginButton" ]
11 | R6: [ "SessionName" ]
12 | R7: [ "SessionEdit" ]
13 | R8: [ "VirtualKeyboard", "Stretch", "PowerButton" ]
14 | }
15 |
16 | Properties: {
17 | C1: {
18 | Spacing: 10
19 | }
20 | R1: {
21 | BGColor: {
22 | Red: 0.0
23 | Green: 0.0
24 | Blue: 0.0
25 | Alpha: 0.09
26 | }
27 | Height: 36
28 | }
29 | R2: {
30 | Alignment: MM
31 | }
32 | R3: {
33 | Alignment: MM
34 | Spacing: 10
35 | }
36 | R4: {
37 | Alignment: MM
38 | }
39 | R5: {
40 | Alignment: MM
41 | }
42 | R6: {
43 | Alignment: MM
44 | Spacing: 10
45 | }
46 | Battery: {
47 | Width: 36
48 | Height: 36
49 | },
50 | Clock: {
51 | Type: Time
52 | Format: hh:mm:ss AP
53 | Width: 75
54 | Height: 36
55 | Alignment: Center
56 | },
57 | NumLock: {
58 | Font: monospace, 11, Normal, Normal
59 | Width: 15
60 | Height: 36
61 | ToolTip: NumLock status
62 | },
63 | CapsLock: {
64 | Font: monospace, 11, Normal, Normal
65 | Width: 15
66 | Height: 36
67 | ToolTip: CapsLock status
68 | },
69 | UserIcon: {
70 | Type: Label
71 | Height: 72
72 | Width: 72
73 | TextAlign: Center
74 | },
75 | UserName: {
76 | Type: Label
77 | Width: 352
78 | Height: 36
79 | TextAlign: Center
80 | Font: DejaVu Sans, 11, Bold, Normal
81 | NavButtons: true
82 | },
83 | Password: {
84 | Width: 270
85 | Height: 36
86 | },
87 | LoginButton: {
88 | Width: 100
89 | Height: 36
90 | Type: PushButton
91 | TextAlign: Center
92 | },
93 | SessionName: {
94 | Type: Label
95 | Width: 352
96 | Height: 36
97 | TextAlign: Center
98 | NavButtons: true
99 | },
100 | SessionEdit: {
101 | Width: 270
102 | Height: 36
103 | TextAlign: Center
104 | },
105 | VirtualKeyboard: {
106 | Width: 36
107 | Height: 36
108 | TextAlign: Center
109 | },
110 | PowerButton: {
111 | Width: 36
112 | Height: 36
113 | TextAlign: Right
114 | Type: Menu
115 | },
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/themes/default/style.qss:
--------------------------------------------------------------------------------
1 | QWidget {
2 | color: #ffffff;
3 | }
4 |
5 | QPushButton:hover {
6 | background-color: rgba(255, 255, 255, 30);
7 | border: 1px solid cornflowerblue;
8 | }
9 |
10 | QPushButton:pressed {
11 | background-color: rgba(255, 255, 255, 10);
12 | padding-top: 1px;
13 | padding-left: 1px;
14 | }
15 |
16 | QPushButton:focus {
17 | border: 2px solid cornflowerblue;
18 | }
19 |
20 | QToolButton:focus {
21 | border: 2px solid cornflowerblue;
22 | }
23 |
24 | QToolButton:hover {
25 | background-color: rgba(255, 255, 255, 30);
26 | }
27 |
28 | QToolButton:pressed {
29 | background-color: rgba(255, 255, 255, 10);
30 | padding-top: 2px;
31 | padding-left: 2px;
32 | }
33 |
34 | #LoginButton {
35 | border: 1px solid gray;
36 | border-radius: 18px;
37 | }
38 |
39 | #LoginButton:focus {
40 | border: 1px solid cornflowerblue;
41 | border-radius: 18px;
42 | }
43 |
44 | #UserLabel, #SessionLabel {
45 | border: 1px solid gray;
46 | border-radius: 18px;
47 | }
48 |
49 | #UserNavRight, #UserNavLeft {
50 | border: 1px solid gray;
51 | border-radius: 18px;
52 | padding-top: 1px;
53 | padding-left: 1px;
54 | }
55 |
56 | #BackButton {
57 | border: 1px solid gray;
58 | border-radius: 18px;
59 | padding-top: 1px;
60 | padding-left: 1px;
61 | }
62 |
63 | #SessionNavRight, #SessionNavLeft {
64 | border: 1px solid gray;
65 | border-radius: 18px;
66 | padding-top: 1px;
67 | padding-left: 1px;
68 | }
69 |
70 | #UserNavRight:focus, #UserNavLeft:focus {
71 | border: 1px solid cornflowerblue;
72 | }
73 |
74 | #SessionNavRight:focus, #SessionNavLeft:focus {
75 | border: 1px solid cornflowerblue;
76 | }
77 |
78 | QToolButton#Halt {
79 | border: 1px solid gray;
80 | border-radius: 0px;
81 | border-top-right-radius: 18px;
82 | border-bottom-right-radius: 18px;
83 | padding-top: 1px;
84 | padding-left: 1px;
85 | }
86 |
87 | QToolButton#Reboot {
88 | border: 1px solid gray;
89 | border-radius: 0px;
90 | border-top-left-radius: 18px;
91 | border-bottom-left-radius: 18px;
92 | padding-top: 1px;
93 | padding-left: 1px;
94 | }
95 |
96 | QLineEdit {
97 | background-color: transparent;
98 | border: 1px solid gray;
99 | border-radius: 18px;
100 | padding-left: 10px;
101 | padding-right: 10px;
102 | }
103 |
104 | QLineEdit:focus {
105 | border: 2px solid cornflowerblue;
106 | }
107 |
108 | QLineEdit:edit-focus {
109 | border: 2px solid cornflowerblue;
110 | }
111 |
112 | QListWidget {
113 | background-color: transparent;
114 | border: none;
115 | }
116 |
117 | QWidget#widget {
118 | border: 2px solid gray;
119 | border-radius: 5px;
120 | }
121 |
122 | QWidget#OverLay {
123 | background-color: rgba(0, 0, 0, 230);
124 | }
125 |
126 | QLabel#UserIcon {
127 | border: 2px solid gray;
128 | border-radius: 6px;
129 | }
130 |
131 | QMessageBox {
132 | background-color: rgba(0, 0, 0, 230);
133 | border: 2px solid gray;
134 | border-radius: 5px;
135 | }
136 |
--------------------------------------------------------------------------------
/themes/sidebar/index.theme:
--------------------------------------------------------------------------------
1 | [General]
2 | Name = Sidebar
3 |
4 | [Files]
5 | Layout = layout.hjson
6 | StyleSheet = style.qss
7 |
8 | [Theme]
9 | Background = ../../backgrounds/Sailboats.svg
10 | BaseColor = ffffffff
11 | TextColor = ffffff
12 | Type = Image
13 |
--------------------------------------------------------------------------------
/themes/sidebar/layout.hjson:
--------------------------------------------------------------------------------
1 | {
2 | Layout: {
3 | Direction: Vertical
4 | Keys: [ "R1", "R2" ]
5 | R1: [ "Battery", "Stretch", "PowerButton" ]
6 | R2: [ "C1", "C2" ]
7 | C1: [ "Stretch", "UserIcon", "QLabel-1", "UserName", "Password", "QLabel-1", "LoginButton", "Stretch", "Stretch", "SessionName" ]
8 | C2: [ "Stretch", "Clock-1", "Clock-2" ]
9 | }
10 |
11 | Properties: {
12 | R1: {
13 | Height: 27
14 | BGColor: {
15 | Red: 0.0
16 | Green: 0.0
17 | Blue: 0.0
18 | Alpha: 0.18
19 | }
20 | }
21 | C1: {
22 | Margins: 20
23 | Width: 0.2
24 | Alignment: MM
25 | BGColor: {
26 | Red: 0.0
27 | Green: 0.0
28 | Blue: 0.0
29 | Alpha: 0.09
30 | }
31 | Spacing: 5
32 | }
33 | C2: {
34 | Width: 0.8
35 | Alignment: BR
36 | Margins: 0.05
37 | }
38 | Battery: {
39 | Type: Label
40 | }
41 | PowerButton: {
42 | Type: Menu
43 | }
44 | UserIcon: {
45 | Type: Icon
46 | Width: 72
47 | Height: 72
48 | }
49 | QLabel-1: {
50 | Text: " "
51 | Width: 0.1
52 | Height: 27
53 | }
54 | UserName: {
55 | Type: Label
56 | Height: 27
57 | Width: 0.18
58 | TextAlign: Center
59 | NavButtons: true
60 | }
61 | Password: {
62 | Type: LineEdit
63 | Height: 27
64 | Width: 0.18
65 | }
66 | LoginButton: {
67 | Type: PushButton
68 | Height: 27
69 | Width: 75
70 | IconSize: 16
71 | }
72 | Clock-1: {
73 | Type: Time
74 | Format: hh:mm AP
75 | FontSize: 3.0
76 | }
77 | Clock-2: {
78 | Type: Date
79 | Format: dddd, MMMM dd, yyyy
80 | FontSize: 1.4
81 | }
82 | SessionName: {
83 | Type: Label
84 | Height: 27
85 | Width: 0.18
86 | TextAlign: Center
87 | NavButtons: true
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/themes/sidebar/style.qss:
--------------------------------------------------------------------------------
1 | QWidget {
2 | color: #ffffff;
3 | }
4 |
5 | #Panel {
6 | background-color: rgba(0, 0, 0, 30);
7 | border-bottom: 1px solid rgba(80, 80, 80, 60);
8 | }
9 |
10 | #Sidebar {
11 | background-color: rgba(0, 0, 0, 30);
12 | border-right: 1px solid rgba(80, 80, 80, 60);
13 | }
14 |
15 | #LoginButton {
16 | border: none;
17 | border-radius: 0px;
18 | background-color: rgba(255, 255, 255, 60);
19 | }
20 |
21 | QPushButton:hover {
22 | background-color: rgba(255, 255, 255, 30);
23 | }
24 |
25 | QPushButton:pressed {
26 | background-color: rgba(255, 255, 255, 10);
27 | padding-top: 1px;
28 | padding-left: 1px;
29 | }
30 |
31 | QToolButton {
32 | border: none;
33 | border-radius: 0px;
34 | background-color: rgba(255, 255, 255, 60);
35 | }
36 |
37 | #UserNavRight, #UserNavLeft {
38 | background-color: transparent;
39 | }
40 |
41 | #SessionNavRight, #SessionNavLeft {
42 | background-color: transparent;
43 | }
44 |
45 | QToolButton#PowerButton {
46 | background-color: rgba(0, 0, 0, 0);
47 | }
48 |
49 | QToolButton:hover {
50 | background-color: rgba(255, 255, 255, 30);
51 | }
52 |
53 | QToolButton:pressed {
54 | background-color: rgba(255, 255, 255, 10);
55 | padding-top: 2px;
56 | padding-left: 2px;
57 | }
58 |
59 | QToolButton#nav {
60 | border: 1px solid gray;
61 | border-radius: 18px;
62 | padding-top: 1px;
63 | padding-left: 1px;
64 | }
65 |
66 | QToolButton#halt {
67 | border: 1px solid gray;
68 | border-radius: 0px;
69 | border-top-right-radius: 18px;
70 | border-bottom-right-radius: 18px;
71 | padding-top: 1px;
72 | padding-left: 1px;
73 | }
74 |
75 | QToolButton#reboot {
76 | border: 1px solid gray;
77 | border-radius: 0px;
78 | border-top-left-radius: 18px;
79 | border-bottom-left-radius: 18px;
80 | padding-top: 1px;
81 | padding-left: 1px;
82 | }
83 |
84 | QLineEdit {
85 | background-color: rgba(255, 255, 255, 60);
86 | border: none;
87 | border-radius: 0px;
88 | padding-left: 10px;
89 | padding-right: 10px;
90 | }
91 |
92 | QListWidget {
93 | margin-bottom: 2px;
94 | background-color: rgba(255, 255, 255, 60);
95 | border: none;
96 | }
97 |
98 | QWidget#widget {
99 | border: 2px solid gray;
100 | border-radius: 5px;
101 | }
102 |
103 | QWidget#OverLay {
104 | background-color: rgba(0, 0, 0, 230);
105 | }
106 |
107 | QWidget#R1 {
108 | background-color: rgba(0, 0, 0, 230);
109 | }
110 |
111 | QWidget#C1 {
112 | background-color: rgba(0, 0, 0, 230);
113 | }
114 |
115 | QMessageBox {
116 | background-color: rgba(0, 0, 0, 230);
117 | border: 2px solid gray;
118 | border-radius: 5px;
119 | }
120 |
--------------------------------------------------------------------------------