From 245f88a367396b8badb2895fad01cfd1f8de0fa7 Mon Sep 17 00:00:00 2001 From: April & May & June Date: Wed, 24 Dec 2025 12:00:15 +0800 Subject: [PATCH] refactor: Remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除不再需要的功能和依赖项,精简项目结构: - 将 Seat 类并入 SeatManager 和 Display - 删除无用的配置项 - 移除 elogind 支持,统一使用 systemd - 移除对 XCB 和 XKB 的依赖 - 清理未使用的类:ThemeConfig、ThemeMetadata、SafeDataStream - 删除不需要的资源文件:国旗图片、默认头像 - 维护手册 - 移除测试代码和相关构建配置 - 清理旧的 PAM 配置文件和 systemd 服务文件 - 增加注释和文档 这些更改简化了构建系统,减少了维护负担,使代码易于上手维护 --- .gitignore | 4 + CMakeLists.txt | 100 ++----- REUSE.toml | 2 +- cmake/FindXCB.cmake | 54 ---- cmake/FindXKB.cmake | 135 ---------- data/CMakeLists.txt | 16 -- data/faces/README | 2 - data/faces/default.face.icon.png | Bin 4920 -> 0 bytes data/faces/root.face.icon.png | Bin 5111 -> 0 bytes data/flags/ae.png | Bin 178 -> 0 bytes data/flags/am.png | Bin 175 -> 0 bytes data/flags/ar.png | Bin 350 -> 0 bytes data/flags/at.png | Bin 219 -> 0 bytes data/flags/az.png | Bin 677 -> 0 bytes data/flags/bd.png | Bin 1209 -> 0 bytes data/flags/be.png | Bin 214 -> 0 bytes data/flags/bg.png | Bin 209 -> 0 bytes data/flags/bh.png | Bin 797 -> 0 bytes data/flags/br.png | Bin 885 -> 0 bytes data/flags/by.png | Bin 1030 -> 0 bytes data/flags/ca.png | Bin 379 -> 0 bytes data/flags/ch.png | Bin 247 -> 0 bytes data/flags/cu.png | Bin 1009 -> 0 bytes data/flags/cz.png | Bin 375 -> 0 bytes data/flags/de.png | Bin 220 -> 0 bytes data/flags/dj.png | Bin 457 -> 0 bytes data/flags/dk.png | Bin 227 -> 0 bytes data/flags/dz.png | Bin 253 -> 0 bytes data/flags/ee.png | Bin 220 -> 0 bytes data/flags/eg.png | Bin 993 -> 0 bytes data/flags/es.png | Bin 221 -> 0 bytes data/flags/eu.png | Bin 2442 -> 0 bytes data/flags/fi.png | Bin 234 -> 0 bytes data/flags/fr.png | Bin 214 -> 0 bytes data/flags/gb.png | Bin 1210 -> 0 bytes data/flags/ge.png | Bin 178 -> 0 bytes data/flags/gr.png | Bin 262 -> 0 bytes data/flags/hr.png | Bin 2473 -> 0 bytes data/flags/hu.png | Bin 223 -> 0 bytes data/flags/il.png | Bin 382 -> 0 bytes data/flags/in.png | Bin 622 -> 0 bytes data/flags/iq.png | Bin 292 -> 0 bytes data/flags/is.png | Bin 260 -> 0 bytes data/flags/it.png | Bin 221 -> 0 bytes data/flags/jo.png | Bin 992 -> 0 bytes data/flags/jp.png | Bin 321 -> 0 bytes data/flags/km.png | Bin 281 -> 0 bytes data/flags/kr.png | Bin 1424 -> 0 bytes data/flags/kw.png | Bin 232 -> 0 bytes data/flags/la.png | Bin 281 -> 0 bytes data/flags/lb.png | Bin 657 -> 0 bytes data/flags/lt.png | Bin 223 -> 0 bytes data/flags/lv.png | Bin 200 -> 0 bytes data/flags/ly.png | Bin 165 -> 0 bytes data/flags/ma.png | Bin 217 -> 0 bytes data/flags/mk.png | Bin 1314 -> 0 bytes data/flags/mn.png | Bin 384 -> 0 bytes data/flags/mx.png | Bin 820 -> 0 bytes data/flags/nl.png | Bin 220 -> 0 bytes data/flags/no.png | Bin 257 -> 0 bytes data/flags/om.png | Bin 884 -> 0 bytes data/flags/pl.png | Bin 211 -> 0 bytes data/flags/ps.png | Bin 248 -> 0 bytes data/flags/pt.png | Bin 607 -> 0 bytes data/flags/qa.png | Bin 290 -> 0 bytes data/flags/qc.png | Bin 357 -> 0 bytes data/flags/ro.png | Bin 222 -> 0 bytes data/flags/ru.png | Bin 215 -> 0 bytes data/flags/sa.png | Bin 384 -> 0 bytes data/flags/sd.png | Bin 339 -> 0 bytes data/flags/se.png | Bin 202 -> 0 bytes data/flags/si.png | Bin 289 -> 0 bytes data/flags/sk.png | Bin 1205 -> 0 bytes data/flags/so.png | Bin 262 -> 0 bytes data/flags/sr.png | Bin 202 -> 0 bytes data/flags/sy.png | Bin 268 -> 0 bytes data/flags/th.png | Bin 227 -> 0 bytes data/flags/tn.png | Bin 228 -> 0 bytes data/flags/tr.png | Bin 392 -> 0 bytes data/flags/ua.png | Bin 170 -> 0 bytes data/flags/uk.png | Bin 1210 -> 0 bytes data/flags/un.png | Bin 1068 -> 0 bytes data/flags/us.png | Bin 889 -> 0 bytes data/flags/uy.png | Bin 932 -> 0 bytes data/flags/vn.png | Bin 269 -> 0 bytes data/flags/ye.png | Bin 214 -> 0 bytes data/flags/yu.png | Bin 204 -> 0 bytes data/flags/zz.png | Bin 297 -> 0 bytes data/man/CMakeLists.txt | 1 - ...tate.conf.rst.in => ddm-state.conf.rst.in} | 8 +- data/man/ddm.conf.rst.in | 147 ++++++++++ data/man/{sddm.rst.in => ddm.rst.in} | 20 +- data/man/sddm-greeter.rst.in | 67 ----- data/man/sddm.conf.rst.in | 254 ------------------ data/systemd/CMakeLists.txt | 5 - debian/control | 4 - services/CMakeLists.txt | 26 +- services/ddm-autologin-tally2.pam | 13 - services/ddm-autologin.pam | 13 - services/ddm-greeter.pam.in | 17 -- services/ddm.service.in | 9 + services/debian.ddm-autologin.pam | 32 --- services/debian.ddm-greeter.pam | 31 --- src/common/CMakeLists.txt | 6 - src/common/Configuration.h | 61 ----- src/common/SafeDataStream.cpp | 83 ------ src/common/SafeDataStream.h | 41 --- src/common/ThemeConfig.cpp | 101 ------- src/common/ThemeConfig.h | 47 ---- src/common/ThemeMetadata.cpp | 60 ----- src/common/ThemeMetadata.h | 47 ---- src/daemon/Auth.cpp | 187 +++++++------ src/daemon/Auth.h | 84 +++--- src/daemon/CMakeLists.txt | 3 - src/daemon/DaemonApp.cpp | 9 - src/daemon/DaemonApp.h | 5 - src/daemon/Display.cpp | 203 +++++++------- src/daemon/Display.h | 66 ++++- src/daemon/DisplayManager.cpp | 7 +- src/daemon/PowerManager.cpp | 18 +- src/daemon/Seat.cpp | 130 --------- src/daemon/Seat.h | 54 ---- src/daemon/SeatManager.cpp | 90 +++++-- src/daemon/SeatManager.h | 9 +- src/daemon/TreelandConnector.cpp | 29 +- src/daemon/XorgDisplayServer.cpp | 10 +- test/CMakeLists.txt | 21 -- test/ConfigurationTest.cpp | 247 ----------------- test/ConfigurationTest.h | 103 ------- test/QMLThemeConfigTest.cpp | 39 --- test/QMLThemeConfigTest.qml | 67 ----- test/SessionTest.cpp | 66 ----- test/plasmawayland-dev.desktop | 106 -------- test/theme.conf | 6 - 134 files changed, 612 insertions(+), 2353 deletions(-) delete mode 100644 cmake/FindXCB.cmake delete mode 100644 cmake/FindXKB.cmake delete mode 100644 data/faces/README delete mode 100644 data/faces/default.face.icon.png delete mode 100644 data/faces/root.face.icon.png delete mode 100644 data/flags/ae.png delete mode 100644 data/flags/am.png delete mode 100644 data/flags/ar.png delete mode 100644 data/flags/at.png delete mode 100644 data/flags/az.png delete mode 100644 data/flags/bd.png delete mode 100644 data/flags/be.png delete mode 100644 data/flags/bg.png delete mode 100644 data/flags/bh.png delete mode 100644 data/flags/br.png delete mode 100644 data/flags/by.png delete mode 100644 data/flags/ca.png delete mode 100644 data/flags/ch.png delete mode 100644 data/flags/cu.png delete mode 100644 data/flags/cz.png delete mode 100644 data/flags/de.png delete mode 100644 data/flags/dj.png delete mode 100644 data/flags/dk.png delete mode 100644 data/flags/dz.png delete mode 100644 data/flags/ee.png delete mode 100644 data/flags/eg.png delete mode 100644 data/flags/es.png delete mode 100644 data/flags/eu.png delete mode 100644 data/flags/fi.png delete mode 100644 data/flags/fr.png delete mode 100644 data/flags/gb.png delete mode 100644 data/flags/ge.png delete mode 100644 data/flags/gr.png delete mode 100644 data/flags/hr.png delete mode 100644 data/flags/hu.png delete mode 100644 data/flags/il.png delete mode 100644 data/flags/in.png delete mode 100644 data/flags/iq.png delete mode 100644 data/flags/is.png delete mode 100644 data/flags/it.png delete mode 100644 data/flags/jo.png delete mode 100644 data/flags/jp.png delete mode 100644 data/flags/km.png delete mode 100644 data/flags/kr.png delete mode 100644 data/flags/kw.png delete mode 100644 data/flags/la.png delete mode 100644 data/flags/lb.png delete mode 100644 data/flags/lt.png delete mode 100644 data/flags/lv.png delete mode 100644 data/flags/ly.png delete mode 100644 data/flags/ma.png delete mode 100644 data/flags/mk.png delete mode 100644 data/flags/mn.png delete mode 100644 data/flags/mx.png delete mode 100644 data/flags/nl.png delete mode 100644 data/flags/no.png delete mode 100644 data/flags/om.png delete mode 100644 data/flags/pl.png delete mode 100644 data/flags/ps.png delete mode 100644 data/flags/pt.png delete mode 100644 data/flags/qa.png delete mode 100644 data/flags/qc.png delete mode 100644 data/flags/ro.png delete mode 100644 data/flags/ru.png delete mode 100644 data/flags/sa.png delete mode 100644 data/flags/sd.png delete mode 100644 data/flags/se.png delete mode 100644 data/flags/si.png delete mode 100644 data/flags/sk.png delete mode 100644 data/flags/so.png delete mode 100644 data/flags/sr.png delete mode 100644 data/flags/sy.png delete mode 100644 data/flags/th.png delete mode 100644 data/flags/tn.png delete mode 100644 data/flags/tr.png delete mode 100644 data/flags/ua.png delete mode 100644 data/flags/uk.png delete mode 100644 data/flags/un.png delete mode 100644 data/flags/us.png delete mode 100644 data/flags/uy.png delete mode 100644 data/flags/vn.png delete mode 100644 data/flags/ye.png delete mode 100644 data/flags/yu.png delete mode 100644 data/flags/zz.png rename data/man/{sddm-state.conf.rst.in => ddm-state.conf.rst.in} (85%) create mode 100644 data/man/ddm.conf.rst.in rename data/man/{sddm.rst.in => ddm.rst.in} (68%) delete mode 100644 data/man/sddm-greeter.rst.in delete mode 100644 data/man/sddm.conf.rst.in delete mode 100644 data/systemd/CMakeLists.txt delete mode 100644 services/ddm-autologin-tally2.pam delete mode 100644 services/ddm-autologin.pam delete mode 100644 services/ddm-greeter.pam.in delete mode 100644 services/debian.ddm-autologin.pam delete mode 100644 services/debian.ddm-greeter.pam delete mode 100644 src/common/SafeDataStream.cpp delete mode 100644 src/common/SafeDataStream.h delete mode 100644 src/common/ThemeConfig.cpp delete mode 100644 src/common/ThemeConfig.h delete mode 100644 src/common/ThemeMetadata.cpp delete mode 100644 src/common/ThemeMetadata.h delete mode 100644 src/daemon/Seat.cpp delete mode 100644 src/daemon/Seat.h delete mode 100644 test/CMakeLists.txt delete mode 100644 test/ConfigurationTest.cpp delete mode 100644 test/ConfigurationTest.h delete mode 100644 test/QMLThemeConfigTest.cpp delete mode 100644 test/QMLThemeConfigTest.qml delete mode 100644 test/SessionTest.cpp delete mode 100644 test/plasmawayland-dev.desktop delete mode 100644 test/theme.conf diff --git a/.gitignore b/.gitignore index 7f34edf..da01e77 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ CMakeLists.txt.user #ccls .ccls-cache + +# emacs +*~ +#*# \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c0bf12..f6acc77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,8 +25,6 @@ include(FeatureSummary) # Options option(BUILD_MAN_PAGES "Build man pages" OFF) option(ENABLE_JOURNALD "Enable logging to journald" ON) -option(NO_SYSTEMD "Disable systemd support" OFF) -option(USE_ELOGIND "Use elogind instead of logind" OFF) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -67,15 +65,12 @@ find_package(PkgConfig) # PAM find_package(PAM REQUIRED) +# Systemd +pkg_check_modules(Systemd REQUIRED systemd) + # XAU pkg_check_modules(LIBXAU REQUIRED "xau") -# XCB -find_package(XCB REQUIRED) - -# XKB -find_package(XKB REQUIRED) - # TreelandProtocols find_package(TreelandProtocols 0.5.0 REQUIRED) @@ -90,83 +85,39 @@ if ("${ECM_VERSION}" VERSION_LESS "1.7.0") add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") endif() -# systemd -if(NOT NO_SYSTEMD AND NOT USE_ELOGIND) - pkg_check_modules(SYSTEMD "systemd") -endif() +add_definitions(-DHAVE_SYSTEMD) +set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_SYSTEMD) -if(SYSTEMD_FOUND) - add_definitions(-DHAVE_SYSTEMD) - set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_SYSTEMD) +# libsystemd-journal was merged into libsystemd in 209 +pkg_check_modules(JOURNALD "libsystemd") - # libsystemd-journal was merged into libsystemd in 209 - if(${SYSTEMD_VERSION} VERSION_LESS 209) - pkg_check_modules(JOURNALD "libsystemd-journal") +if(ENABLE_JOURNALD) + if(JOURNALD_FOUND) + add_definitions(-DHAVE_JOURNALD) + set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_JOURNALD) else() - pkg_check_modules(JOURNALD "libsystemd") - endif() - - if(ENABLE_JOURNALD) - if(JOURNALD_FOUND) - add_definitions(-DHAVE_JOURNALD) - set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_JOURNALD) - else() - message(WARNING "Disable journald support for lack of libsystemd-journal") - endif() - endif() - - if (NOT DEFINED SYSTEMD_SYSTEM_UNIT_DIR) - pkg_get_variable(SYSTEMD_SYSTEM_UNIT_DIR systemd systemdsystemunitdir) - endif() - - if (NOT DEFINED SYSTEMD_SYSUSERS_DIR) - pkg_get_variable(SYSTEMD_SYSUSERS_DIR systemd sysusersdir) + message(WARNING "Disable journald support for lack of libsystemd-journal") endif() +endif() - if (NOT DEFINED SYSTEMD_TMPFILES_DIR) - pkg_get_variable(SYSTEMD_TMPFILES_DIR systemd tmpfilesdir) - endif() +if (NOT DEFINED SYSTEMD_SYSTEM_UNIT_DIR) + pkg_get_variable(SYSTEMD_SYSTEM_UNIT_DIR systemd systemdsystemunitdir) +endif() - set(HALT_COMMAND "/usr/bin/systemctl poweroff") - set(REBOOT_COMMAND "/usr/bin/systemctl reboot") -else() - set(SYSTEMD_FOUND 0) +if (NOT DEFINED SYSTEMD_SYSUSERS_DIR) + pkg_get_variable(SYSTEMD_SYSUSERS_DIR systemd sysusersdir) endif() -add_feature_info("systemd" SYSTEMD_FOUND "systemd support") -add_feature_info("journald" JOURNALD_FOUND "journald support") -# elogind -if(NO_SYSTEMD AND USE_ELOGIND) - pkg_check_modules(ELOGIND "libelogind") +if (NOT DEFINED SYSTEMD_TMPFILES_DIR) + pkg_get_variable(SYSTEMD_TMPFILES_DIR systemd tmpfilesdir) endif() -if(ELOGIND_FOUND) - add_definitions(-DHAVE_ELOGIND) - set(CMAKE_AUTOMOC_MOC_OPTIONS -DHAVE_ELOGIND) +set(HALT_COMMAND "/usr/bin/systemctl poweroff") +set(REBOOT_COMMAND "/usr/bin/systemctl reboot") - set(HALT_COMMAND "/usr/bin/loginctl poweroff") - set(REBOOT_COMMAND "/usr/bin/loginctl reboot") -endif() -add_feature_info("elogind" ELOGIND_FOUND "elogind support") - -# Default behaviour if neither systemd nor elogind is used -if (NOT ELOGIND_FOUND AND NOT SYSTEMD_FOUND) - # Set the VT on which ddm will normally appear, and the - # commands for shutdown and reboot. On FreeBSD, there are - # normally more getty's running than on Linux. - if("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") - set(HALT_COMMAND "/sbin/shutdown -p now") - else() - set(HALT_COMMAND "/sbin/shutdown -h -P now") - endif() - set(REBOOT_COMMAND "/sbin/shutdown -r now") -endif() +add_feature_info("journald" JOURNALD_FOUND "journald support") -if (SYSTEMD_FOUND) - set(RUNTIME_DIR_DEFAULT "/run/ddm") -else() - set(RUNTIME_DIR_DEFAULT "${CMAKE_INSTALL_LOCALSTATEDIR}/run/ddm") -endif() +set(RUNTIME_DIR_DEFAULT "/run/ddm") # Set constants set(DATA_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/ddm" CACHE PATH "System application data install directory") @@ -224,9 +175,6 @@ add_subdirectory(data) add_subdirectory(services) add_subdirectory(src) -# enable_testing() -# add_subdirectory(test) - # Display feature summary feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/REUSE.toml b/REUSE.toml index 5d004f3..9049026 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -69,7 +69,7 @@ SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "GPL-2.0-or-later" [[annotations]] -path = ["releng/prepare-relnotes", "src/daemon/Auth.cpp", "src/daemon/Auth.h", "src/common/ConfigReader.cpp", "src/common/ConfigReader.h", "src/common/Configuration.cpp", "src/common/Configuration.h", "src/common/MessageHandler.h", "src/common/Messages.h", "src/common/SafeDataStream.cpp", "src/common/SafeDataStream.h", "src/common/Session.cpp", "src/common/Session.h", "src/common/SignalHandler.cpp", "src/common/SignalHandler.h", "src/common/SocketWriter.cpp", "src/common/SocketWriter.h", "src/common/ThemeConfig.cpp", "src/common/ThemeConfig.h", "src/common/ThemeMetadata.cpp", "src/common/ThemeMetadata.h", "src/common/VirtualTerminal.cpp", "src/common/VirtualTerminal.h", "src/common/XAuth.cpp", "src/common/XAuth.h", "src/daemon/DaemonApp.cpp", "src/daemon/DaemonApp.h", "src/daemon/Display.cpp", "src/daemon/Display.h", "src/daemon/DisplayManager.cpp", "src/daemon/DisplayManager.h", "src/daemon/PowerManager.cpp", "src/daemon/PowerManager.h", "src/daemon/Seat.cpp", "src/daemon/Seat.h", "src/daemon/SeatManager.cpp", "src/daemon/SeatManager.h", "src/daemon/SocketServer.cpp", "src/daemon/SocketServer.h", "src/daemon/TreelandConnector.cpp", "src/daemon/TreelandConnector.h", "src/daemon/Utils.h", "src/daemon/XorgDisplayServer.cpp", "src/daemon/XorgDisplayServer.h", "src/greeter/GreeterApp.h", "src/greeter/GreeterProxy.cpp", "src/greeter/GreeterProxy.h", "src/greeter/SessionModel.cpp", "src/greeter/SessionModel.h", "src/greeter/UserModel.cpp", "src/greeter/UserModel.h", "src/daemon/Pam.cpp", "src/daemon/Pam.h", "src/daemon/UserSession.cpp", "src/daemon/UserSession.h", "src/common/LogindDBusTypes.cpp", "src/common/LogindDBusTypes.h", "src/greeter/GreeterApp.cpp"] +path = ["releng/prepare-relnotes", "src/daemon/Auth.cpp", "src/daemon/Auth.h", "src/common/ConfigReader.cpp", "src/common/ConfigReader.h", "src/common/Configuration.cpp", "src/common/Configuration.h", "src/common/MessageHandler.h", "src/common/Messages.h", "src/common/Session.cpp", "src/common/Session.h", "src/common/SignalHandler.cpp", "src/common/SignalHandler.h", "src/common/SocketWriter.cpp", "src/common/SocketWriter.h", "src/common/VirtualTerminal.cpp", "src/common/VirtualTerminal.h", "src/common/XAuth.cpp", "src/common/XAuth.h", "src/daemon/DaemonApp.cpp", "src/daemon/DaemonApp.h", "src/daemon/Display.cpp", "src/daemon/Display.h", "src/daemon/DisplayManager.cpp", "src/daemon/DisplayManager.h", "src/daemon/PowerManager.cpp", "src/daemon/PowerManager.h", "src/daemon/SeatManager.cpp", "src/daemon/SeatManager.h", "src/daemon/SocketServer.cpp", "src/daemon/SocketServer.h", "src/daemon/TreelandConnector.cpp", "src/daemon/TreelandConnector.h", "src/daemon/Utils.h", "src/daemon/XorgDisplayServer.cpp", "src/daemon/XorgDisplayServer.h", "src/greeter/GreeterApp.h", "src/greeter/GreeterProxy.cpp", "src/greeter/GreeterProxy.h", "src/greeter/SessionModel.cpp", "src/greeter/SessionModel.h", "src/greeter/UserModel.cpp", "src/greeter/UserModel.h", "src/daemon/Pam.cpp", "src/daemon/Pam.h", "src/daemon/UserSession.cpp", "src/daemon/UserSession.h", "src/common/LogindDBusTypes.cpp", "src/common/LogindDBusTypes.h", "src/greeter/GreeterApp.cpp"] precedence = "aggregate" SPDX-FileCopyrightText = "None" SPDX-License-Identifier = "GPL-2.0-or-later" diff --git a/cmake/FindXCB.cmake b/cmake/FindXCB.cmake deleted file mode 100644 index 95703ef..0000000 --- a/cmake/FindXCB.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# - Try to find libxcb -# Once done this will define -# -# LIBXCB_FOUND - system has libxcb -# LIBXCB_LIBRARIES - Link these to use libxcb -# LIBXCB_INCLUDE_DIR - the libxcb include dir -# LIBXCB_DEFINITIONS - compiler switches required for using libxcb - -# Copyright (c) 2008 Helio Chissini de Castro, -# Copyright (c) 2007, Matthias Kretz, -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -IF (NOT WIN32) - IF (LIBXCB_INCLUDE_DIR AND LIBXCB_LIBRARIES) - # in cache already - SET(XCB_FIND_QUIETLY TRUE) - ENDIF (LIBXCB_INCLUDE_DIR AND LIBXCB_LIBRARIES) - - FIND_PACKAGE(PkgConfig) - PKG_CHECK_MODULES(PKG_XCB xcb) - - SET(LIBXCB_DEFINITIONS ${PKG_XCB_CFLAGS}) - - FIND_PATH(LIBXCB_INCLUDE_DIR xcb/xcb.h ${PKG_XCB_INCLUDE_DIRS}) - FIND_LIBRARY(LIBXCB_LIBRARIES NAMES xcb libxcb PATHS ${PKG_XCB_LIBRARY_DIRS}) - - include(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(XCB DEFAULT_MSG LIBXCB_LIBRARIES LIBXCB_INCLUDE_DIR) - - MARK_AS_ADVANCED(LIBXCB_INCLUDE_DIR LIBXCB_LIBRARIES XCBPROC_EXECUTABLE) -ENDIF (NOT WIN32) diff --git a/cmake/FindXKB.cmake b/cmake/FindXKB.cmake deleted file mode 100644 index 97bd45c..0000000 --- a/cmake/FindXKB.cmake +++ /dev/null @@ -1,135 +0,0 @@ -# - Try to find libxcb -# Once done this will define -# -# LIBXKB_FOUND - system has libxcb -# LIBXKB_LIBRARIES - Link these to use libxcb-xkb -# LIBXKB_INCLUDE_DIR - the libxcb-xkb include dir -# LIBXKB_DEFINITIONS - compiler switches required for using libxcb - -# Copyright (c) 2013, Abdurrahman AVCI, -# Copyright (c) 2008, Helio Chissini de Castro, -# Copyright (c) 2007, Matthias Kretz, -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -IF (NOT WIN32) - IF (LIBXKB_INCLUDE_DIR AND LIBXKB_LIBRARIES) - # in cache already - SET(XKB_FIND_QUIETLY TRUE) - ENDIF (LIBXKB_INCLUDE_DIR AND LIBXKB_LIBRARIES) - - # use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - FIND_PACKAGE(PkgConfig) - PKG_CHECK_MODULES(PKG_XKB xcb-xkb) - - SET(LIBXKB_DEFINITIONS ${PKG_XKB_CFLAGS}) - - FIND_PATH(LIBXKB_INCLUDE_DIR xcb/xkb.h ${PKG_XKB_INCLUDE_DIRS}) - - FIND_LIBRARY(LIBXKB_LIBRARIES NAMES xcb-xkb libxcb-xkb PATHS ${PKG_XKB_LIBRARY_DIRS}) - - include(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(XKB DEFAULT_MSG LIBXKB_LIBRARIES LIBXKB_INCLUDE_DIR) - - MARK_AS_ADVANCED(LIBXKB_INCLUDE_DIR LIBXKB_LIBRARIES) -ENDIF (NOT WIN32) - -#.rst: -# FindXKB -# ------- -# -# Try to find xkbcommon on a Unix system -# If found, this will define the following variables: -# -# ``XKB_FOUND`` -# True if XKB is available -# ``XKB_LIBRARIES`` -# Link these to use XKB -# ``XKB_INCLUDE_DIRS`` -# Include directory for XKB -# ``XKB_DEFINITIONS`` -# Compiler flags for using XKB -# -# Additionally, the following imported targets will be defined: -# -# ``XKB::XKB`` -# The XKB library - -if(NOT WIN32) - # Use pkg-config to get the directories and then use these values - # in the FIND_PATH() and FIND_LIBRARY() calls - find_package(PkgConfig) - pkg_check_modules(PKG_XKB QUIET xkbcommon) - - set(XKB_DEFINITIONS ${PKG_XKB_CFLAGS_OTHER}) - - find_path(XKB_INCLUDE_DIR - NAMES - xkbcommon/xkbcommon.h - HINTS - ${PKG_XKB_INCLUDE_DIRS} - ) - find_library(XKB_LIBRARY - NAMES - xkbcommon - HINTS - ${PKG_XKB_LIBRARY_DIRS} - ) - - set(XKB_LIBRARIES ${XKB_LIBRARY}) - set(XKB_INCLUDE_DIRS ${XKB_INCLUDE_DIR}) - set(XKB_VERSION ${PKG_XKB_VERSION}) - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(XKB - FOUND_VAR - XKB_FOUND - REQUIRED_VARS - XKB_LIBRARY - XKB_INCLUDE_DIR - VERSION_VAR - XKB_VERSION - ) - - if(XKB_FOUND AND NOT TARGET XKB::XKB) - add_library(XKB::XKB UNKNOWN IMPORTED) - set_target_properties(XKB::XKB PROPERTIES - IMPORTED_LOCATION "${XKB_LIBRARY}" - INTERFACE_COMPILE_OPTIONS "${XKB_DEFINITIONS}" - INTERFACE_INCLUDE_DIRECTORIES "${XKB_INCLUDE_DIR}" - ) - endif() - -else() - message(STATUS "FindXKB.cmake cannot find XKB on Windows systems.") - set(XKB_FOUND FALSE) -endif() - -include(FeatureSummary) -set_package_properties(XKB PROPERTIES - URL "https://xkbcommon.org" - DESCRIPTION "XKB API common to servers and clients" -) \ No newline at end of file diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index f0c34cd..bef73ba 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,5 +1,3 @@ -install(DIRECTORY "flags" DESTINATION "${DATA_INSTALL_DIR}") - install(FILES "org.freedesktop.DisplayManager.conf" DESTINATION "${DBUS_CONFIG_DIR}" @@ -11,18 +9,6 @@ install(FILES DESTINATION "${DBUS_CONFIG_DIR}" ) -install(FILES - "faces/root.face.icon.png" - DESTINATION "${DATA_INSTALL_DIR}/faces" - RENAME "root.face.icon" -) - -install(FILES - "faces/default.face.icon.png" - DESTINATION "${DATA_INSTALL_DIR}/faces" - RENAME ".face.icon" -) - install(FILES "scripts/Xsession" "scripts/Xsetup" @@ -35,8 +21,6 @@ install(FILES WORLD_READ WORLD_EXECUTE ) -add_subdirectory(systemd) - if(BUILD_MAN_PAGES) add_subdirectory(man) endif() diff --git a/data/faces/README b/data/faces/README deleted file mode 100644 index 85479ad..0000000 --- a/data/faces/README +++ /dev/null @@ -1,2 +0,0 @@ -These are the default avatars. -They are installed to `.face.icon` and `root.face.icon`. See ../CMakeLists.txt. diff --git a/data/faces/default.face.icon.png b/data/faces/default.face.icon.png deleted file mode 100644 index cd7c4fdeecce8508d39ffd927de81cf89cb334cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4920 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 diff --git a/data/faces/root.face.icon.png b/data/faces/root.face.icon.png deleted file mode 100644 index 308496979d6665a8e87451d273ad14233f821a90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5111 zcmcgw_fyl&*Zm|R^xlOCNC)XnczBS|rT3yzrHIrZEfgWBlpumgl@dY|MWjAL5F|mG z5;}r_B~(Fap@Ts3<&Svh{bhI0&Y3;;&fVFwbI~?dCM=8si~sC-|f)j4C@p01w;L7=u6>pmmgtCv0uGhS~xhBbG4{m=OY+P#7c= zY=UY)ot)j3W7qw@C;z2*nf=SiS_i>LV?UCROwjO@YSf{2e(K3je8hlJh2n zdRUvaFXT2>NFho$qHy>j0*qus%FF*^Hv~QNO~Eta)H@D!cynTnhF6`NmScpGGTnS# zVNmQQEh)M*8WQcxm)Hv3_Tki||Ca?em@~Fq4jz;3A;Ei(+E$M#+?y&7bCc)2=e6b$ z=?Fb;RR6$H2WlO?+0lB5(!AiAaU-CMsgpIn=*}BkZj|xxzOrajv^s(zyDz#pD7)$G z1Vr{@)MJNYIr{O%H@1R_To1Z!wXV8}vfXD#PWzODZSMALgW1?mk2ClF{PIcs>Y4a( z^)e?E8`7T$Z5-W^mr&EBJyYnbkp}WK&JGOysB^GYbFJ_Q7?Ke=#pw;j*7he}LeOO| z7l#>|-7UGndi`z)9Q5k>g4Dd^ym3X)*Sti81^Wl6qB!!~f(=kRze}Rq@KO$wcr?mX zBH7AR7N*IKvb{uAL+FN)Q^J0eSA(AAS zblIW!5=fk^YXjELJU_ zG96=j%7MD6XR!ZHGixeCEsR~I!SZ2>3sxK?nY zfloo?>H0c@1tfYk-ST4B=WM-YC$yKb<-MwT(2t+CnqPTPJk41+KjKS_pOOJ=AS%b8 z94HAqpvr{Z+ODe{m;ROX?f#VlY2dCJ<-@Goe;*sN8w!LP8`8$CxKW`)nVW{yBwXb< zQYeC+8&%z}Yvphf9DWcA6=cFqdf5PfU0Ga{P4ODTCxLa`4#20K`OW&Xw?w)+NQiWW z%MFmf^3i;`P_R!D8K@74djJo_$6xQDnz>P@Rjil68q&a~kFXHw$Dxg9iRPdi$bYsN zpQ>p#xW_&>EQfHrKJN(fNAH9}6a2p`#(*^S_7kK5`2{EEgq!`-qV?hSfI!z@5B>d< zt3Y$E*8H#d$`Xr;wmt_XuN24 zFFQOLw4P-CZ9;4;MX~+q3?=-aAWw-YzAQh2u~iQUQ9CSfj0I_7;>o1-n<#Okze(J+P+Bn)Se!;tw;sSKmmjBzw1kZAepzVBA={-0J7wohWHQ zy|3Bh=90ii2}=@d&~8Botb^jSDcWcPdPTZz-b=v`V2HQYzS3L}y`|)9SM!syQBSy0 zf14i7d~DjYo*py=6?3Cvn;hBTW)&uC^fG`tnmWMHr$H%b{)jTaU^ZfKe?QB^Wr)Vi zpn%>KIdDJKj@RB&N4)B_5Q;9*>_tS9JR@AEu$Km#Ycjs9gq>`>HdVe-pfd>PhbY(p ze|9P&sJ`rb0cN0ACUvbsY(Vzz>QoijM!0$!@~rtq&?1MI|93?ya2TB`MfYIH@U>i0+f6r!P<1G-(9{AHOGhY?%G#D=TTLw5-K=J~6 zfE{m*y#ZgIq`>FT8&DjNwC`ADcT9CZ13Vo@2!mdf0ARh~F7mVdXv-^~gtE$B0M#JI z=l5N1D3@`g1a`EVBE9)V0wbxqp}TxRRY29NxqnhpAAOqRr=!#XUvk*)&4XA~_K&GL zP%Ng?1fqEV*+R;5nbuq$lt2ndiW%a=VgZDzottZXxV052fGn?MPF9|`gkpbodhv^_ z-s2PI93Wm?0#?W`R92%R+-bna{XC8lejWpISuM%WYY>FdT{n~eB>YYfxPB#FOOEk* zo)W0j(!d%Bs06qPZwR^Jx19(ugvh(9+|C{FGttbrvJ|1;;?)zwLQCbX@e8fu1DRaf zV6Ks{6V}+61Kn~!jmT6;N14dSS&c*&ktN6>#a$7_tpluFw;xVJKfRDfJz~g|1%`8v zX6v?8abhAQKOtmOu*Z8xs0zc+E3Gt}Y|pAAlG^N;wsZZxlfNfG;rZ7OyJtI$01L%C4f$E$6c#I~`pO{nw(6IuCCc{}xIlQt^Jo7j~ zVHQ#W)WK;o0cwgA!!_RoVGu@b%NcMI1Jfm$ke$kl@WxgUYl-8J7v|nxzCBQm3Fu(63$oVT?Ua`Ymu6dCYWppDD-rI4&jykr_z zDaMrCbm43n`ZNmA1dDjg{eM&Y|G5))XvB740~pJL1;gFv{T72j0}+i1iF8O>q|S>} zTR>J6>`llcbir8pIdex{GLMACtoD_UDgXy7`Y3=6C`Oy<%VdqF=}_!hlfgE=9Q#=7XZ<63{;i$GOF*PmH@cA~hqU7jtPX(ZMFC{w3lJJ)B z&QRqI!lkRLY$s;knjoWk#t65+8<*I54WtW+0;$SJA9;w~s=uoq55+z$?=B@6ow%ue zXcOW1R;e?uNNB-K)d12oS7^RM_&7g6?ai61xAwCfv`rn%gaG$(G7m~m&@ol|(+i8H zQioLhUaTh@Lb;J^rs%`N_M#Zt%N4YDGI6K_gvQy?dW2vo#^836nB@l}P4%I*futX^ zD2>&r2de1mae8IA7cjgAikb?vBdqe#O6Z$RC9qny@x1${;74MJU6z7uB~ zG8FS4`<ImEZ3aHS<8;ZcDrWJ z-CMic1tY0Kw(ZCg#DebVXt`wD0`HYNHh`~DMOpCf4*iKUdUFT^wxK+krFYdU`Ka1= za+#oP`W<|BC&0GNUBMJHXkF0P^_TU@CXs12P7_*UAz$Ytr>}Oj0-N~$Cn5JWj8VtL zK_#IY$mN507zO2Q4n69e#vQz%QM|Hi$@Yg*;(gORZ2F&y$df!d8dXNZ-1nw$_v@He za83^jjsn%``pZxr zD`%#&US3jhT#C+-O{P2#WY|Cj%EvxtY)DgU?9^3iLy|m%Quz-di3V>Ej9gAVFFM{} z`F+Y~SUz^O$nZ@@BImKT=n%}<%aO|ZDDkb`oABB(rgr*cXtw3%Q%`1$WV-gojlixQ z4|s%kLe|0-DLTz9-=x+KgOT0UkAmo4aUVKM>n}G5;@GklB2D=$kyyX?&9$7b68UX! z@A&Y@GT1}iKM5_e4@nH5VDS(!n-b;mrWRy6!AiMWGEr=X)4;2brJXF5;NxY`|G-lS3WvN=I& z7P>1tr0>@)5``ks7ay1kEHiKDA`bnY$c}vuS@gDC`y23j!5VzTkyquYaE_s)#Be)4 zD&^?RWhE2S1$7NsJz>aKs1JRM3wd^IOC(GWG4NFa>EfLu-k~`xG$!BK63HB>=UPXn zcRNqqS%2d&N$xP5ocYmPKf!!(FE&oA&&oj+icNd)wM?~e_a}%tg%8=CDVvwKeB1nn z5=qEH6l-!kM%=zomC%&J2Syu9LSN2|1CF^2Ic8TJqD}6pTL7aNIabHSgE_`9Usbd^GLAB!|@tJr)30>kR3g(Nve4tA4h+wIs-Ohti$UWw0FgZC-Kcke6=_fBfV< z-;AT-Lvr3fKTT{ndOS=@pzTtE33?q0_CM?hD>7TQb!7ni3#!K9*HO+s17}bHPncA< z@OrGl2tD(~?-z=D&Yq+^cgc>&aNPBr2Ag*Etwvj%P-3az42!FKuY>^JI&3&sj@7}; z#-|7WbnW|Xv*KtM4L-zYY-{l(;PK}Jfvxl>Nnl$>pWa=>J)q(3?KG`QlEhX#PGYp+ z1ZEZ!ejpkuj;z%Xf_JS%nIyFP_27T=l!%X%pYn`5lLI(De_RS~SJ56gJTK0uhbjzv zP5#zXv{0{Nvfyh>VBhn$xk4D(pah=XeQ6T(#EJtm!HmGBg)id))@yHvG&_#8)8d#F zC9EF&EX1Fh*7V-IDH5gk@)A6YfTi)Iv#nEJKh>@=8N0Us!_fCz0byLU^N}@rsmgk4 zpJ>V1j(vg_I3MnXZ=0w&cSxU`p8M`DABt_!LxRw&y!t<@D~PNqm<#D$Ami=coh#zXhVi> zGYzD5c1sbYh~7OCHxK@s_8!5nNBcJ6rJqby$3$*NTO2A1%je^o?^C=8BSE+G_)w9v zQ!S3I|LVD5xYs)-u7OKMou(=cyT`L(`tc0$j&iZQcmL#G%|Gj?mOBp}xUc&4SA5)7 zD{L|N^WuNcoDY6JFI!hQJ#RkLYSjAX6ls9!eA@zP!Sxhzn}^E@?ulO_S|=Wq5~)8d z5`N|L2kBa@H%u>`ycilaq)^X0xL5Zksk8P(Ljzh9a1{5#&Vj595W{IX`LSc=D)-fq zW|ymF`SDf?H}xi(M;GPFREY@%8JQxF%S-e zysKxO?*cjXmczQDJWJed&|*_svl3x;Ez}=^wI8 za4rQu_Sg66ZGH#CIbL%xqSC-3q8FnyAX)*W{eJ;zfHmp=P|HpbB)uypx?=zS!MUy! XCj1SXu1eWOLk}=DvNEjK_k8$29Wh(^ diff --git a/data/flags/ae.png b/data/flags/ae.png deleted file mode 100644 index 1b77c2161fd7277e49c3bd3d742406476d3aff6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheJOMr- zuK$4m$eszr47pdm(}5IYlDE4HLkFv@2av;A;1OBOz`!j8!i<;h*8KqrvX^-Jy0Twl z;o-1ipSen89#BZe)5S5QVoov#Yf~u40Rx#IJRS)apZ+T!2zbuSP`*QHx{i@tE>InV Mr>mdKI;Vst07l#`ga7~l diff --git a/data/flags/am.png b/data/flags/am.png deleted file mode 100644 index 7b0d5f7dbb53aaf3ca51d3b7a27716614b8aeb90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheJOMr- zuK$5xCc}Rqmtp1`X~hpfnlZ`S-G!lpRn`N@;VkfoEM{Qf76M_$OLy!300r4gJbhi+ zFEPvWiD)SoONs!6Bt2amLn`JZN3?QDv|0VP*ODmv6A)r>vn6@E zyDx`7I;J!Gca%qf-qx!O8i8iAbW|YuPggSc0pcQrQGM{*+8M&o-U3d z6?5LsP~y{0rPB*Ni!{>Wd+(|r}Y_)(*Y60uE1DrdU zvVB|UP3iv6@S=gcK>p;p1H4POJn*>QbNbTy>rb_L1USrvKUWHJYzLG7XLT>yc~e=y z&gaZ?SA(VT2LvnnQmP*?zBv^pp&-!KUvl(&^$sUZZlj0)58l6Oq=uHMsS3j3^P6vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ69*nPWiI01zsJY5_^ zD(1Ysd6APrf#=AD;5+qCceOg{FL{=M7`rB~w3_zI uEXQE(!4kI1l0NAMv9TXMU1dr~5n%QI#^$Z`f1fze4hBzGKbLh*2~7ZDC`t_g diff --git a/data/flags/az.png b/data/flags/az.png deleted file mode 100644 index 9d561fa5ee1f1155573b650a05bcfb0ba1632b0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 zcmV;W0$TlvP)E(tsOhPx>8h>E=j)tm>|=>#wit zu(0c~vFoz3?6b4%w6yHCwd}UG?YFn>xVY`Qy6(KZ?!CS5zrXLm!0*Aq@4~|H#KiE$ z#qh?)@yN*W$;t7`%JR$0^32Tg&CT-8&hyXD^U%=q(b4nL((~2T|NsA=Y~*qP0004E zOGiWihy@);00009a7bBm000XT000XT0n*)m`~Uy|2XskIMF-LY9}XG}Z~d`n00017 zNklQdTPkpFHFL z8_(GP)lH|$YR@d#vS%(5_~-361iVh*Ls;NKWo*ZP95uT?{@hf@eHGX6<{Dgev};tu zYzeyNMHt#8u&m{lQMd2Y2!cUk_X%9|2jH=|1DVteg#M*h5kkN`_DLAcg76y%FbNTk z5y2iNlwcZQ@Uft~P1jF!ov%Lba!~?z)+&ln+qQl?^QC@9B#vW*0~7?FQ+Vc8*s}A4 zIU6hF%v72y%cTH)TyEvTCJ>GzH0o4V7=IYYuVjO|QX%4F^pCJ8zLqx4Np0+!J$Zqw=T{nQ)HR&f0$gJ(Tm2 zP?6ru0007LNkl1B9C81CuH0Y%W3SN4Okdrs>LP4!L ziS#e<*n_9qf);xBAF#BiUerURmzFI71)CrZm>5FW?2p;;5Rj$CH1mVlNWRCg^L-y) z-psst2%bHFQ4{{x05Tdw4@+a{Vad>ClnnXJvuMVT0N~WbN7r!2K)TG&NfnxK{_r$> z^gX!OW+e7I1Ne|4+q3lDjKPp*dZcnr-)*zk$K8S(_4&rJad{!}DMk8xBP#itUatE) z2X23204TW8`vZ5m?n?){C<1pDB$hp{`>(3rfY~Der6&79QDst3zGX7K)C$+Co=}}4 zfVHZ()CwiSU6e4i&G@F%mB<(Y*mSx!9BE507@HUBwJG@?LU$SmSj}7eQ+g&Al5fPyBxz7oY_UQ1RDj?` z-g=YOP#8VQpYvN;v$SYC_9YIEjZ2I6TYbbJo#~$H3A{B+zf9oifM-1($L|emUd~(3 z^VW%udo(VkVNG1gkl#9sGJXUA4HF+;<+0cwbqw?|MF4b8lK!Uuzcsxo8bc3DBMJQ* X)6KCn+*}_p00000NkvXXu0mjfa9}Q0 diff --git a/data/flags/be.png b/data/flags/be.png deleted file mode 100644 index 4252b217357a603018fb0f73a87fbe16a3e8476a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~thy6+-USK;d%8G= zRLpsMek1Pz1D*p0%m4qMqi1{2oAna|qm^-S`o-9_wddkq-Sqz3{Lt!fY1?a_>yqn? iW72n=E0~KzAWo#2+3)Vnq@zIN89ZJ6T-G@yGywq2(@e_% diff --git a/data/flags/bg.png b/data/flags/bg.png deleted file mode 100644 index 7f929e66ff8a4ec7215402c7778f824f327df795..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!2~3AZ}P1GQY`6?zK#qG8~eHcB(eheoCO|{ z#S9GGLLkg|>2BR0pdfpRr>`sf1$HSx4l9Rv_nAPU1Wy;okcv5PFF5ixI0ziQAS+ao zz;SVgbP0l+XkKFGE9X diff --git a/data/flags/bh.png b/data/flags/bh.png deleted file mode 100644 index a234dfe246d78342235d00bff77ba5a6f50bf77a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 797 zcmWlXTTsk#9L4{XDVIhv3}!rd!i(FW((cw~SEV8m)znHr1RTB&BsWy{CU%sJBsux{s)EIo z2`+H76Pg{f>$Mp6amqlYB$Zs4Ji2XyB#oaQ6tGE+B#kUtf~%`lF1IQaxVho(&Z<>- zcp#G@m*eS)mlsMU-rlHGsMV}lgO3ku*W&L_KmdV(tY1%15F0iS9L&azgoLnpGh4O{ zX*5Gyw-OpkSQz2qL_`o7iAIAcqoT&5qsO*yM_|VeVq%DmB`%JgJK4RPJ$s0cN2_J; zUiR%HF_EMs4jka%K@J__$Ptbn<=8QfALqmgl9NeIMW^HBNlu+2EsfKsNl)kOS@e1g z2F{)1{CP4m$jl@wi|lMJT_Puk%a^%wg{xP|&E?uPu3zWI4Q}2fFOU3uZr$ScZSLIR z?p+EBC@iF?h5mfJsN%d7=f}f%FC&!pt6#xDvZX~)>f*ksj1=V zQ)+8@_6(DWx;kFG;N?qRy`sLJh6dig<=s0P8)<6d{d+!qpt+fkA2FM0X+bP$Z|Bn| zIy$<#y6Egg=;zOT`9gO$U%&G0o2|Fk*4IZ*552tzW3ll4JN^Cq_+hnLhlht57+`Ra zp&_hRL>w96=TDo>#;;%e{>`612tPK)-@m}c`iObrUB*TG`>3Qd6XyDgFfqY5EK!ms zyZq<4ruO7fQ92~~1*#pI?58*`UF2p7aTisJpGvvuaIUFY>6GH-yt+}o-z3dUNEx4y zVyB9-ml;%@-plIVbmSYKWGyfD*L$wcoW9Ueuc*&!E2=TfPc`ba-LX!wRnC^V@%LAD z%xO40-|S%y)hbq)r{&c>*X=SHH5vNO#obeDU1xcuIVYF8SY{g{lN=q&+qAl#C&5!? WGqfXp{fcUFi{z(Xr@HSQmHH1Lhv1F? diff --git a/data/flags/br.png b/data/flags/br.png deleted file mode 100644 index ad76e4593d2a90261994c1e675f21a348c286cb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 885 zcmV-*1B(2KP)57RYJF;)P8=j95PF^9K$#lj1T{iavf%+giJUTRpz z9QIWKs{l3vUs18<7~3WlU{_(F!+-Ii8wTPi!u4I3*p3y}hq`d{v_}&&q(fT_wh#|2 z0GL*sLnb$fk_5lJcdUae@dnFpKSnJkyT+F6D+%EN(4-)(ZT~iap{$1(+f9gEED^eMYqA9-F zmz90nJox_|udO>R+WL;(4b0pdcrP8;gEc136O2pp>*arOr*)`0w~%e#QMZ0CEwX8` zms;x=@>1W2S>BfQ@*wr8rGVN6Kk2unLb4%ub#~9CpTMWCvjhGO`gIX|Da{7w00000 LNkvXXu0mjff|roO diff --git a/data/flags/by.png b/data/flags/by.png deleted file mode 100644 index a40f445b07b49d80b4d52f77650ec94a7b56a487..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1030 zcmWksPl#7_5dX-w_>UFpP!uap2ccV*bSwD$^tbH(P#1~yU{p+DR6-CMv~CeoU>F@T zN+{THK!Om8BS@B7}onfd&gdF$Zf{LGenwg8x! zEQ}x3`LOQ$Hcjby=9%ZO=(z3K(SZ?g;hnAPPfY_;IJkdlPH})h01X3-uz>XtBf$V0 z4mjZf?;$aW2t*@+Br=eV0*a_WHCoMx4s@GZf`%}(8O&%FW^KYDjbUtanA1GW+d}xX z2#dCaB`w3Utzbo~uxb<2rgc~g24X2f!V`=-s#yON;&27obkIo;dNZU+;b1fqOfrMn zEU?H5R#WQLpo85m>8eIJ+6``W3%7Rpp_UA1yThIC;octdNl@X@p75k+c(xb3=oMb= za#W-`yyX!FMuVZ!1KA%Ts18j@LY3Q{ z8j(~g5uJuKrbSw(<|gT?W~U>a>5<+U$dD!K+L_2?W@L62vX~WFotnJN6MlDT>~c=v z=rWYCEXumH3$jy;*ySi^d6ahrDmc)Lu0$m(qq3_|#j2?4(l%)z($qby5;zFLuuR$; zt%x>Y*e`NW$ze#Ehpd;g!_ox@=`o0xPDv7D5fvxFtGk-2Ua5MUz5CoQ02`j(H$TRy z>Fo>p*!<$c;p4#8JBEA1)n8v*S8(G?lLK=buTJgQw*B_K7x$e|=+()1w6wf>{mkW= z+O=u#?(x58PhR=tznRm2Or8I8_0##!&&}?*_Vwb2zkG0Q?da*pcYlB3^2O1%$&uMZ zPcE;mfA{7?cfR+++q0wJS8v&|pP!rTUpe&H(w@otCl62m^To=KU!HyCqkA8`aq8V$ wPdsqrx1YZG_{h%lH+SCk?Xk7LE-f$J|Myp~ue|(2KO!EO%q@;T+v9Ki4+E06y8r+H diff --git a/data/flags/ca.png b/data/flags/ca.png deleted file mode 100644 index e24e3fd0701ab10e45b37c309ba4a25a8e5c306b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~w5DBOxf3Y#!_&nv zq+-t7S%G{l3Op`}o6V!%*Ej7I{_T26Vp@iE@Ro0XwU#{I!g}S_spX=&Z&%A@Ey{bf zP(MLpy8^3wdhdf>GhbbBvhs1a+I`?@iG`J2Q}wI9po+5IhWUq$9s9P<(Ug^)moRgg zJD=nyxumY;hqIoPUA$E3Ud$kSob#RLPX2d38~z_-I)8WOC6T@zHK%*oA5Z14@LQA6 z=Ka8OW9+P>OLvgm8)78&qol`;+0Mm4uH~;_u diff --git a/data/flags/ch.png b/data/flags/ch.png deleted file mode 100644 index 46f6202f2f163d73c88590edf829913ccbb83468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~)aEBXodgsr@pN$v zshIQj#zo!+0}h5jgLnIjVjGuuoh{67{C3FwVvL|R+fKju1+x#9uwA~ZyL`~WIEen09Kd+bvrpmVact2F$ Zc7_#=-0UV5Sol=f)EtYwdV-I)J#u!&Q%GQ+U3{;&2n=Mwkl<@h}P4dU_ zzh`s921rOS`=?LCi|1zl`**nEhWGEM4AsafRsrWY!5CJ3LD9_v009wA6RD{c`Swjh z;`fVGR*KkcA$QsJREv!t7TD|uKLGeGJlXb_1ef;vMUJ0{Xyj%NSU@gPVNDY`e<4t~ zp+UrMpK(-!WXb2A1>_O+uB50 zT138nHLq1wg&b{wWs=5Q3rIyHtm`7Jts-u>NOrdQaMCo9%uErNOT^<5NlXkF=`CsE zq|X9EGYe~8=W&^auOhoI_sHtJRwgv_VRp(KPVHixU z!_yeU#xWXju`kBaR52KOhDUKwP9tuLW0^=XUxNRJeI!vv(;SmE37BCYNfgqKhpq9* zqns(iA6Y^k4|&D9c;!*fuO;0>3OPKU)3Puj{Dw6YaF^Gtjdvd9*t=LkC70-DAq4$X f%Xq9aDa7C>EFkrqFc+#100000NkvXXu0mjfGS$KU diff --git a/data/flags/cz.png b/data/flags/cz.png deleted file mode 100644 index 699a4f005cba82ce1e936b4bca8d0ad0ac0dbb66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qf-qx!O8i8iAbW|YuPggSHX$)}cAGcfX90!2c)B=- zRLpsL$(rx50T0W?zzM(OBUjGI;bJZNqWtnDkNCGo8y(heEt<_$^Xy*Y4`+EV%dgVE zwREqqxz&HId(AE1MBT|{!4apI+*MuUdi|ZywME(SV%LMcHoxwmaQ7MF1MJT zhY;Q^runzP#OYR3{##%ox^-*tt>bLWA>StF+h)E!64CJd9sfM3tXxq$TQM`vYKbge z@oy$#VqDeIS-OJXti;r~tL3tMC1nyvn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~q&D!)6a@-Jdb&7< zRLpsM^CBmM0?&~P!MpyS+STf$H*-OM-PCm|>aK6^Gw<;;us!&N<+8AkKZvpHRfyNa zHdYvyg)IL*P?^h+S;1jhPv9~_oIPO z00001VoOIv0Eh)0NB{r;32;bRa{vG?AOHX^AOY1J9vc7v00(qQO+^RN1PloQ8?f8W z-T(jr8%ab#RCt_yk+H7AFbqXA@B=}Dh_$0cl(80gz-HP$V7-*FUddRWWvnOS6E-rQm@eab ze8JUthHLQ*>rTd%c*M&++K=K9FD?`D5g-13{_F7(-<0|#`MHAiZkC2?T`cgIv(EML ze{a^vsfm;)!=^+Ae+YMm0agAG zhMi+Dq>-(&6kYI~Jb85K+%ynR^9QIWjLQVJ5X;Tmtbm64X6g=|vpRPfvH3nHBUGEy zpr0}|;&v=e<#9JU28Qngikq?NwO6mPB{Tm3+s2HS4Z*`Q00000NkvXXu0mjfQ;x<% diff --git a/data/flags/dk.png b/data/flags/dk.png deleted file mode 100644 index 0d637dc179dd2171884328c26ad8333a5fd5b815..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~#CGnuY6lcb@N{tu zshIQjh9Vz>0?*M4y}$4Od|W8uvCEEs;Y_KytFEk-ao@Fm{g2eYbqBK9E=&5P8_Yde y0%6?U@xbp~?!4SPExgO5#qa!!I)ow(R+sCV$K%$2L-Z@qE(T9mKbLh*2~7ZgeoxK- diff --git a/data/flags/dz.png b/data/flags/dz.png deleted file mode 100644 index 9993cd98013bef450117488871a21fc4d40b4790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 253 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheoB=)| zuK$4m$ezhyC1!jG$Y4zJc6VXuV3qX%sVMM>EM{Qf76M_$OLy!300r4gJbhi+FR}1& z7z+IC^_T<{%JOt^45^rN_Tp~d1_K_J3knC>c#d#r7HLW}*4|<76!|zsL?J~!pn13Y z&1v?I{TdH@>UXH+Cu~~hv3To&>&n*VI_BlaL{HsgdoOxy(pH6ivp>uK63w31{yg+d p%B^sL>ep`HgBDiT{k?zMI+f$pyt9rMV}Q0Yc)I$ztaD0e0szSERipp_ diff --git a/data/flags/ee.png b/data/flags/ee.png deleted file mode 100644 index 8bcdbf487026281287346e9194bcc67bd09f72aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~1Ojdsa07)RJzX3_ zD(1Ysd6APrf#=AD;5+qCceOg{FL{=M7`vt($?iOZ x#NYM6IClQDeZ0~>=>~HTmatux^a&TQVf?Mrhx zwyezD)J@zF6x>vERabFEK=G`Yi@Jyl$jGY>bErcc>`H2i5t@|5;vO4Qo6^+cWrU%q zxztR|5dPSfm8z+jBJ7fao1!LS0=g#@&l=Pq2HImD#N=(pLH~rHLsCtOH>g-(jVKh5>WwjrCm~RQy~iG$fOwnxpnBr#z7_;rbALw zjL^JEEOM|hwJD7lQJm&BYc6nN43hrXmX+{}$-joMn-7>1jd|un3aC8y7;heBFy`sR zv~$COoO_7j=UCw&??h>8aY_u2o?1W?XaIGf22_CxkO4)YpBVqK-D=-m@f+g5XNn}2rQEsqX$ zZFTG_96Pl(_~RY_nkr|diG|hQpTBhDc;Vq(^(R_qn@eBsJvelGe{J*3;>(Yd2Tv}{ zPi@b9U)r2qSe<-U`mjEF@z%i9n?E;?J{{;?S-J9hXYl^|w_npoHg<}8PsCxonpwO0 S{Kfm-Y=QF7ShjI)cKIKY8>y%O diff --git a/data/flags/es.png b/data/flags/es.png deleted file mode 100644 index 1ed6e7a2396c272a2c5d9e4022f3e18e79026f03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~xYq9MECdQgdAc}; zRLpsM?I16M0mos76}$eQdMl=2xsP+hr-kuXS1Y9dZpdW2Ea{VOF!x|d;X(7)8+l@G yBv>`S}2?t3;K~#90?V8zc8_5-hzbZC+;nt+JSkz+ABnXfM$qVEvkCjIV zkXOoWo*+PgV1Nv4YqunJv)N>CtjfjdmMEE$DBF|F4CVj=49P6jU;kPEBlWkxAKCao zQF#E+DxtlAAhPr>EyMSg(R<6_+|WA*e+JG1G@IME|2lj2|9t=Z@e5A8GozsBKo-LM z6->vP>AoU5R3v+f`Ie&Sz|sY)!O8njd0<;|K&4^XhSFE$J;(-%Y-q@an!E>tQ$zO} z+&O6TS$F(uR(MbbFyDgYwI)7-=s+>u*QDE!_k~E)0+f8lQA-4isHjwj1DzvTMjfO?YbQpIJKB;1u9gKRi&2Fj{nK_ubP(M-U%r;(c-7 zym#lm>ke>+?+sO3Guu^^U06EJ(E{EoarwniQMpk1n!Inx29`3glpRBGBeDHMv277D zN?(AcJBs)~7>$lHsQI9hxVC*TZAICE zY#?95p=R{KQhl`au0WSxmu;({2q5nX*mz$PA1dNQ#dKehzN(38uV+;m&=s`jl8BvG z-y2%F#+@77nIahrn`Kb5y#m^_#HEa*C<8^_v*e*A3oYS^rRW)g2!iO#**3tkNlHUV zcNLQ(#k6L2wxh@gHLI)S+`d!|Gy`vH>3y^e&MZ#v650!cJJ2 zm%%|^v2x`xmY$;M!Xkuh1dE|&^xjegmhO$bYP)zDP>TR4y5d3eCMg{V*y&g?9|m4`4A;l>U9tO(rjWSURdM zVV3#OQuHnTQ%inn=zfIm&C9?R9bq-yf@G|T55= zN8*NFZ156!DKAk(sbs<|tbgf)*KO+dvPo#6X1*n{J%9CdPiCz}DMh-yQfl4^*y&g? zejKn7e%PvnZ9js^45oV$Q;)H2 zH56Ka7ac|3w=71MhnATHU-#w0N?vaARudmUbflOZY0@166sBWHw1>o-w(LmV-o(!TsF`gkioR5V$C8p-N~sB=yQDNc5m)YASOJ|Ze?|Bw5$ZI(jXbbM#5=53@q6s2Pyf4$qZ0Bw|d04_Wv7-A#r&LN6 z>0Aq|!w-^y2j_N0YW5<)#{8dU%CBJRKfl|1);AkXDepnigJf4UUm4%z-;GMLuK)e(n|IG%Q#=2HFheyCMNqo?PlF zb~drWxn(huErDsv?|&#FHbR2{m#=IfntA_R#=++n1Zx2=wWtq8UnZjI{+;_y$4V~t za3)p?>df6pEp9!O^V{bEzy7x&9*a1ag=-#iMOHE`Rga#Qd|;Vx)ocf{AaLi8vwaV6 z6RX*v)|B=%(|w5EXyUOV-BINITGn~!zSiCi<&D&GA+g4vp9j46PfKtE@d3p9$WEvk zJsY;`1;Mf{>{hjiI3LwA?nvM2SC1_SZUGx=7YS=ksa{{ihj&RyWE|GIZzHw1GfVdx z`sejjbNqA=SEj(xF5BN3Iuk|rx)vG^70GKQT9#k4y|N&CDnW1}gBr&iXfH{ea>@~!1&fT0!{W_6~mz?&JonFtNuOo&K##N!^;`+Exl_wfaR zGu=~M|5|hP8;P66=+m9*D%e&fH8Y4Uy>m-=R*T(dHLFw6e_sN0)ii*CW8&X>jnG|dO5LkQ|CRMc|I*O85>{Ka6!fKb zyCBHw)k$e^XBu}VdiiuLnS5P$_tb*GiT5?}fyBox*ju0i_EzYg)RJhe|AwamzPZE? zu_M-o+dY+=$U4ZIX@a<3s_n{BZPNvTvlt>(aRPD&fPcUr(SID#cFtJ85~Pe>YrP@nIt8>+*pDA zs`jM|f=_zsJXDPTu@nvX+|s`kp*y&dn%XLU9Jvn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7~SZ&#+JOB!%d%8G= zRLpsM!;$NN0uRH%Wk3GwFSpkabSd0iEUMBiZfayae^JN(ufP1B?^(`%<7|Re^Glv( z#xu@=7`IrD%l7Xoy)}2k!4kI1l0Mhvn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6ft*?9C>HrD_d%8G= zRLpsMek1Pz1D*pLcKrW8N6+@4H|IwN##zPhY`e>{=g-`FWpmiC&bCtC*HYI^*JMXr i->@z*_V6wo0(*CJvG~1XUJ?T|p25@A&t;ucLK6TB989_Z diff --git a/data/flags/gb.png b/data/flags/gb.png deleted file mode 100644 index 486303cee2826f97ad3d6e2792d3ac956b18d69c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1210 zcmV;r1V#IaP)w^Rou1r2#gc(@?XvciBmv+?BuuBy)*15RB@5TJ7 zzfTuR5V>wnE{oc`UbIVYI3UV3nhS$N1kMn^W%BL4hy}0<5~9Mkv7JqTj+)7-?LfKj zOYd!y?=Ju(yCJr<-kv|nm0lB`Gs?(vjV5GMYz0^lmXamkU(iMrW!_>zSRl?dT1wm+ zvJcJe$g`j`72MF|xf({&`|LGOI7ZRFXc5EC5${-eB3z@0k8t>;;}pz$&B?;CiH$j`H0;tyb&BOn!K?InA+0khWOe4Q>cYsg zz=9APbAZVIot*Q%JF}ICgX>JeuNp8oYO1m7fNH*hNonk zLbfSY8##ComtJ4z;Zya!2WJsJ6{m#swNP2KZV|1w zUiZU1{2B1S^Y9npTgMmSTgMmSTgTU%)~%!Q*HTkl`UBw7`tD9?w^p@q#B74Co!3R@ z4wU|RolQm8u^F4ip7Y8B7z1!x%eZk!SCQqE6v(n5gwpRryrb)JjPBe4b=LVc2L{Aq zmf6;{yHZOyT$gtwW8W{dV90Qk6`_`9gFZChePY;XY4Yn8T~G9?`^m?4@thUHU0@+t znzd_G5>96}GH^-?(>WG|=uYQYy1cfxR0c&&h`atqDra6G@0||}u&z?;ZD~)dDtu-6 zM4fe3NM!kR&bYKPm1^2SGJQD@>)&YY0y(njXhYXQ2QOEdHxa|eV7!*f>Lw+TXMuL| z6VZ%tBnQd@zgbDSWA zz2qM{MI?reU%os+tGu1|$w5f@t7YuE2*>%VM}{MGr}J#_rnvMk4~OGY8LE2c(l@QD zCb(uU!TDBl*T*5PW@b-ch9RGFPFtJS)o1^M2LR}UUG9`F%ihxd Y1*2juWpvG3X8-^I07*qoM6N<$f+h_?Gynhq diff --git a/data/flags/ge.png b/data/flags/ge.png deleted file mode 100644 index 4fe01bdfac2bf9e1a3a1e4308a97048b91cad3c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheoB=)| zu0Z<#|Nk=?7#dj^_<$V7ByV>Yh7ML)50HuikH}&M25un`X1sK_?hjCqy~NYkmHiU4 zJfDK~r97m)X6!Bj PDrN9=^>bP0l+XkKz-le4 diff --git a/data/flags/gr.png b/data/flags/gr.png deleted file mode 100644 index 2a20e8a0c11c78d4fdc8a0b80bac6efb09995f17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6f_0LY=`wA3l_H=O! zshIP2x+C8K1rC;lAOFWMlfNLnF}3XZiGvoAh7$xsHzvmSp15;;`G=a?#@i7y&b_jE zbLD%zlU^eC<&=U#Vzz1%cWV`B9sv1Q8U6)DfRnK(wg^NgO+$IfpB6xyzPQZ*;h zs_4-1r;S}Phs2g`-eMJD0MtBD_}c@=FVdQ&MBb@0C68+ A-~a#s diff --git a/data/flags/hr.png b/data/flags/hr.png deleted file mode 100644 index d65bcc58bd94794a5f3021af37bc2b8080fcb7ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2473 zcmV;a30C%rP)b${^HlLsH#Q+0(yROmI4BrWN5kq0>e&GdRku7 z2M$6Es+T`bqJoxgMPJf7M&ktsE;Fw_3VN0r0=}~1%6^VYGB)f42m%JizdAoLF0+~z zT8llfW(ooh4tC0AYj!F~t1u!01k&;X1`-Cx+J1VvCJuK7N&UpfzMhim?fwJ=>Xt&9 zpchAQ3JA_GI(jUoJ{q##qKd&765fV-j|Mvp2Kt*NDc%uJ^VtxYz^7Ri3E)UJq zBQRDnQh)^mRwA0ta;AnJDE<8J>WX~+>gc*~wBoXwo?Ke~0tEig!8_+B=ibp{><$S60{%`WLcWr6o*I6Bg0lX_?&}5>qjH9`9#13$n9mU$^#d35j*h4o zF6Oejf;xWd3JLN`R`Lb~{{H;faAdw(P+BIq;SV1g0?YfNpME})#h0FnIy$`?APN-z zt12pF2q**w_`*gq&U$**k(6c@mj2e)x+WH$K2Dq@N|Jhpm^5DQhPKOHYS?6Cl!B4I zp4OjNmcb7S{`BmjGdBLMtNya2&X&e^c6aKMewr6Hh)iLWkd~qvB9ba5_k)A`y1teQ zBC|l1iez9u&GVJGK}s zJTauZ00001bW%=J06^y0W&i*H0b)x>L;#2d9Y_EG010qNS#tmY3labT3lag+-G2N4 z00t#VL_t(|0ezDTTvJsX$FDS#QbHS<4NyavDLLOH%s!J)k#f@s@>p|TP2~-2H3TxG7Us+#Q&)bI_e9e*9_G?Cc)1lFg-2&Ic@8!KG=ofY~s; zo)$Nj2Cg15cg>o8muJ5*dHpx9zV^YO0T(uAXW5Gs51KFs$lzU3xpo_E8n-L<#_EiW zqob$n3w-Ls#K|x0A2@J--@Y49XDOu$j%RsHb!=XM0NxZ1!wly*{JOh4f63T&YQ=~_ z18$zVbLMDG_5QbCzBM6W9hB(xuAnkW)3})9-3NBj{lI~LKmW<-(Z@&BoSwV+^5qd1 zF6_LkjqRdw6-lbRL7K*zZC$tkeoQc|Aah7kz!uwK!8JR^Ej&@zQ@5mG&AzN{w}xDO z*4~waOFKIu=mi_!)~NiU(rK~Tl}cMllucP_v&2+wn|b)~{pQTf<_QG_1&0^*RK>^~ za4%}qC@1^}JYWNEUd`8BO-yXP3M96+YFZPwZvC>Vz+#@-dZ@nH(*Ju+Nap>zn5|nA z6Z7HjgJ9Jz<#LnUm>_3C z#tT-RN|*?pI-YQ2(y1xJ_(f@^O;cVQ?g$B6T;7sou`SS1CKI8K_vTO>tEPZdHRV3k zgb8}Any}m5-P(%tTJ4RBuqy4@PtWT7pokiUeL!WkT8(5kgo%pRv9co=xXW|mQO zL{_>;B$`?g4>DtW3sG1#lF$Th2qJa9j&)juy`zz zqL#r)jtx4>FD0_KL#7MO(JCEIl-L)vov6oHGXnR)&TK`M`o3`t-3{BO(s zbjG`{5BqGnl?Nu0%Y3Rtf(3(|24jp1cG)ILZZyx@=j8N>!-ieFICj|2Yezx=nF!SJ zfb|K6vItbxGX<>PYAr5aK5g2xVjvCDt_&0N)X4?8jCt5zGBY=imxesVLmJ~hMwT!F zkHOE3f!fcz{@ix6J_tm2^vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6fRid1(*8+uNJY5_^ zD(1Ys?kLEhz;nc*i%Ca;as7+KUWJUtnPCT?Ru(=x5$5sV_JL{hOP*!MGtMPgHNQN? q>Yi35cLL4_G4!tG?Nc>EQ4}xrnM20u=O!vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7K%qQ+;NC67{_H=O! zshIP2rZ?YV0}hwRtG@3yiVc~lbUprn59=P^O($CfC9IbS2*x&6EM(rG##^mE=V4Lo z%`GvL+xC9m7IScE&H5AT5~n@9ol~3N+xaj(?fsiYKJw;ww33&+T-@fKEta~gVE;6M zn-??6K5kQe*X;6m(%qX)TS~$NQg>|UD{sDXDbg|KQt5^}3R_FkHq5@(e?i$=$W?c) z+{0PZx*qQOvm<)iv~wIAA6j|jZHTfmc4@2bO*N0uox8OBspo0SMU$`f+>Gmz;E*}{ zA%l0(GWp})yHcerUjwm^Mko2Z)7jq^Z$3)!LvN^eT(rQ Z#+c6~W{->5zXF4S!PC{xWt~$(69Ca@pE3Xd diff --git a/data/flags/in.png b/data/flags/in.png deleted file mode 100644 index 7ca09456b0d40113c481755a142ab5d0e11cedaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 622 zcmV-!0+IcRP)b}87Q--zMgqiQBb^COrMCIHwM#S- zKpk*UuQe$a_gGKn@cG<~nFKdwhtugi-*@+UI2Fd@IggcbaV(^*O{GNrQOyD z_&t=$H4dtWxGtRI-rXCtS{h1^f_Je0ba%K|s4$>9u%ETjY#!ls_VVm`oR_aw@ejKx zm#f(AHk{60;_*ZWjI{E9T}#%JKEUf$`BAB(>pC{u8LHKvJbpAusa#_#Tf*gX(r7ek zwKVQe-aP#s9*d1IGqZ%%YQgVw(`X#gZfku0Qs7#^Loj%ezCJrkZ#Eb_;r%u39!{t8 z?Ck6@J|05TbdHbPBobNrRXanMRNk(9;_4L_q0r?H4IZk4di{6sNG5X(n;1O)ZM2LA ziQT?#ZnXSXDRkH4!99IPzFGttrnZ~`QY`6?zK#qG8~eHcB(ehe1_3@H zu0WcBVHLwP28R0j{Xhapf${$RK;C~KWcdI8e;bJPAB-<(NdE@vU`+CMcVXyYmGuB} zI14-?iy0WWg+Q3`(%rg0Ktc8rPhVH|ODsGb22u>p6V3vKvOHZJLn`LHop74B!GOov z*jwy_&>Q<6agBwU3V*5`I0{$rhdxbr&rE&g#r98b`Z~FUI|(w)yt~g&NjN5zt0z(R zs%_<}wfW}f&E4;~%BHL8n(W+s_^LsVahy4mt$1IIy+&C5|6pUeU$fI1ragJO>-V=5 Ppsfs^u6{1-oD!Mvn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6frDiLix&{<#^mK6y zshIQjh9g&l0T1g%m#Y8T$LDefMlHSiE&X1QtIQ^iV`r7tT>QA?_tW0bPbG8f>knM# z2y@?H)pS*GOvn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6fg&+MdDgp{cdAc}; zRLpsM-jSC}U#7mm)A-w(jF8tQ&*q)kb|pi*_E4f#`%9T+ e#WT(kWb9u2ip7uD;LQ)9EexKnelF{r5}E*w`%e1+ diff --git a/data/flags/jo.png b/data/flags/jo.png deleted file mode 100644 index 7c8d1f011515b8b06da606106a88fd3c3537572f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 992 zcmYL{Ye>}x7{-5^mvi)ZNsZx{sZeb;a>IdV=>|GI^VT_OnV079ay;r$kN3>V%)FbI zQ<*hu%wb~)jY^lJL0RIlXs}`SVP4Ym-av-?Fc>1d`|r~}yzg`2<>CGCv?m&3++5yv z0o>wZqmL-~i8Al0b||~oWd2nFhx|x=Bn(+yx3e9=ek}1&vQF{s6b{Ov11P=|ID-n* zpyauNMhOLX@BmNP30~k0KClb4T5WiExDj%}1bL7T1z?6kD1u_JKnavW8I(f>R6-S; zfND4iHE;?}!x^ZBvrq@;6lvh}Vb1C~cZfPYwFZh)v7}OxLTL*5$I1HwDw3&5`BG3IX0sF)N>Py%7mLLrB_&c?DrIF- zUM>|CQducgRUTG$b>P*7cNd=B?Ci#;6T55dxQhKX9D8xPg7Xy|uHt$LRS)VOTrT5w z5zQssFTz*QhxU#(>~7fT=%}=|iq$H8eRBP}+_)kA{m+JnWne&V-ju;XxphnK-II|K zxqn|CJdlSE<tab$_q5diXAP9Zu9(^J}wP4$}RM-%%qv-EfF z+I~-)%-r6;xlsGhR%5?qaLN4RXsC5-Y-83x?OUli-1XaEx7WH&VPh?RLs2msGp?b3 tIL`fK?61xkdN=sF_gj|nW3y%Rf0m9lHS|mdoEcFbBu;0DzWrHN!@sUYeW?Hd diff --git a/data/flags/jp.png b/data/flags/jp.png deleted file mode 100644 index 984fc19b3c9b26396a4bd73b7d06aacd1acee5d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6f`5J%9tp*D1^K@|x zshIP2rXydo0S}AetN;7w%-eCXt3$Tg%sTu)MS(}tO2cC}#FFZ*8uOIi__f^a++aO_ z+U}6QcGvdsCba(VoHzHf!g-#TtFkwxUqASw^}QOecXn&&$)-zIiKUY!Y;l{hibJ4$ zXQ{=Z%NM*mE$XzuW_&RDBHjn$^tsKDy5rMq>1fP(BLp1!W^msof> zj2L$aST6<&b$YruhE&XHy>OAU#ejz`;V5Gsi@W8VHSY=!-*Dx7%cj-AZuvX@l7uMh zdVl%MOKK+ksTTKj>^>H+84 zSAH{ib~Na5RPWqgRR60ayLpY_rZDG_EzJFgBW887Pw~)HHcr~C>sTbY`SPXRiL!PC{xWt~$(698jXU-|$5 diff --git a/data/flags/kr.png b/data/flags/kr.png deleted file mode 100644 index 43730b1504c139b9008896885a5f879c587f7c94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1424 zcmV;B1#kL^P)C>kIl#`R=na6WT zuV23&+qOA!l2NQ6)*M0a;LYuB!&u&|I+ zD#gQx4?Xc2$=g0`i~+#5Z9<`s{Uyoy-Xoo-Hpj=uDJUqw7=vxwY}l}YL?W?3OE!2K z;W^Twp&{pbYHG?^yslii;)TvNs;jF3sHv&JvMeNV^ypFg`};A*5Dtgklevxks;Vjh zx_I%TPMta>K()2CYHMo~prWFp>?BW~NL5u5{8KDTdi*$R)%^T?0ebW1jn=GLBS6od zJ=4aG8wKd<)vK<2xH3F7HRUW$sZ?sgLWP?}>)g48CYLJVu=Mg}S_<2?l}sje{rYuH zPEI=Q+P3X!;dJ%X9O3x*xO08u#tm)Wyjg&=U3`L6O3KN}ZgzfIw=S)Y%F0RsI(+!B zPM$m|K$d0c!i5V06pcoMF)T@aeSNB_sS%(}n>MMdt4n}NOG`7bdoa3qw9`_4?C^K* z-Ypo2*RNl@^5J;{otvv!!^rE%E-F)@Pkku?eBR{d~^5r091s~GoF;<=C-fpJX}QXqbcRkd8*90(9xpCDqs0tE{X{l63s|aY2?u zz%0(6muhRJy?dpK3TfXysjg0HYs=pLwr$%4C?1b%cz9T)rKO6+V%oB0ivYE@wz~4+ zY0;YN$wVTd=g*%zy}Ek!Y5}@+>y{Tf*Jx>J5upA1_p7n7QQ>e{i9}+-6mtvTdFh#% z87Dm|eV)AZ;x<=2FAZ?!%ozX<95}$CLx%u}L?Yb2eH(!8?ryJ?8PU3$z)P@?%eT1;~8hqo|WWnRbC9=Lv#A{Y3iI1 e{ma9bj=urj$6v+*uo&b30000=BKSEBPf5*!f@jKtXa{s>lt%bR)^x#6fd)v6nzJl3S-=!x_(q}rup5O^I Oox#)9&t;ucLK6T4OGzjI diff --git a/data/flags/la.png b/data/flags/la.png deleted file mode 100644 index 9000553fcc1d2042d59caf5420236d34cae93a97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 281 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!VDw>rnZ~`QY`6?zK#qG8~eHcB(ehex&b~R zuK$66f#Lb{|M%|wKX&Z@+O_}Z%=zEb^S`C#e{%BwprHRwPX84Z{|g8JRsFxm&hi7O zkuk~J-G!lpRn`N@;VkfoEM{Qf76M_$OLy!300r4gJbhi+FEPvWDKWBLE>r{xC3(6y zhE&W+7C6E!;kI<6*Z#xY9+U5-boj->b~CWCtt;QL)R3X|67$S+?Q2XJ0w=R1 Uym&n6C(t$qPgg&ebxsLQ09|osz5oCK diff --git a/data/flags/lb.png b/data/flags/lb.png deleted file mode 100644 index f4e7102e06d0e91ef964a41f95d77be780c032ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 657 zcmX9)ZAg<*6h1?3%c)6)NoXJc7HQCK)F_D-Gv8&(Fq72})1agEOUoZatkk5vQlVhN zd%;4AV0~EH2fS$Zp$3DF5t42q;v&cqs9})(ux>|#dp@4$oO|wbZmX}jAT@b&G61A{ zHBSl0JT`|dfqm!MbE6y*tK3CyfW9{Sa%B>L<*4siX+HBp2t<@p5|L6$G7y3ovqvN@ z10a9|AOOWj2<37qL?xv%O+^&%4JiT9kU;_z@+~1bkr?jQ6@p}jhYBEMQYey2La4o( zq>#)I8oHk(CtL!(QIo3*XjK6b(y9XFITDCKDLz6eWTlGVRv-yT39Z5=Ng($qbooIl zK%UQ15Re!OVnIyuG|7-P0j_MqZ5aO%kH(|nSlEo3p-&+rZ0K+G>fY*r8Ssbvg4ZFb zb!#re#fu@Kqun7$Wa^o=MjQP9odD!er^&x*Ia65R0X->OW3aYHJ9!bnzJA3lW7C(H znY7kfJe)H+btsY~%?-!Nt zEjh55?UNp)HqVmYT5uhE6VyLk&@ zqGup@_4S_eJu01TIlp7Dzv_C^zWK-{JyPa$?EE^}^=1F@XTFa2zo%z@4qa*5 Y+7f(zswVAY6)ytb{9@0O!xhc{0K3p7umAu6 diff --git a/data/flags/lt.png b/data/flags/lt.png deleted file mode 100644 index d5ccfa97ea8f3ba0c3a22dad3e875f27da28e859..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 223 zcmV<503iQ~P)Yf{KP(He(5&C|0qb;a2tD*w%poH-&`*2!k6&Z z$%W??_CdgfUHBTZGnWck(kg6tIyO8V*->7_x(?g$bZmG!>kP~O#Z|29unkYghNrX6 Z@CWOxCmwg@0-yi@002ovPDHLkV1gPuUd;di diff --git a/data/flags/lv.png b/data/flags/lv.png deleted file mode 100644 index a2ce0071fa3f3b7f72e41d4a9218490eef05a601..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU+Puw=Z>ypBC4|7?$K4Brm90^0{wr{k@_^ntGp cuc5NcUB@`WOuR(vffg`$y85}Sb4q9e0Ba;bkpKVy diff --git a/data/flags/ly.png b/data/flags/ly.png deleted file mode 100644 index d2f16563913e302260ddc01d03e6a5f6add23c45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheoB=)| zu0VP}7;`WBB@SdTCV9KNFm$lWdVo|EctjR6FmMZjFyp1Wb$@_@>?NMQuI!gsM7daa x5;dd*fI>o^E{-7;bCM%kxg^|vF0Qfq#HhWlufZnq-$kG-gQu&X%Q~loCIHi$CgcDB diff --git a/data/flags/ma.png b/data/flags/ma.png deleted file mode 100644 index 0b3730e9cbc02dbac22b6ab36907255386cf4730..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheoB=)| zu0Z-f5btMT`Sqb1$Y4zJc6VXuV3qX%sVMM>EM{Qf76M_$OLy!300r4gJbhi+FR}1& zm~-seUG4-Fa`SX?45^rt%;Cz)bGT)`SHt|yWAi(w%WuuPx@x7zpA9P$12tZ4K4cX5 zBXD7G;E%-B0Y4|s%=iO3IP)r#FJf)4qg#7)${0WbX5%XSAw8_h)3Lm&KZJ1IkM=sauYldB)GF&wHovR z%Fh=JDZxwVc~lWSO%s~&sckHacojMsjEA~WHUz!A?i}{%tcj?QM6U;3ywG20i{n%k zjy@K>J3loQ{zZ*Z!rRc-p}1;5c)hDo5BkaHT|hffjdj+|X86e{#JygNnf$D<&i)vM&^*;2^(RHOD{`B}iQq(hvUYlL#t`tL`Q4A5Gz34xCbVty-q9I>+ zoNo+wTaFHxquXcIwRQyuszmG2uWo`o+JTZG&P!1ZszIy51-sFCSM5US(Jc$wu>|V% zp#SJwI}@l2?M7LYMY~ZKN|-*^qW9gNn?U^mt+t@ha|P4u&M;GGBdSE83_21t#U4Q! zH?|X56LYtf90n=U_f4CuL0e;lRIp>Sfy4xtp< z6bsj}3QfXqFb3z~H00m}oQ3mn3Z|ey>EluO*uw2G*kj>V0TpmFEP^&z3=NQhMbHXM zsG=G=!sDl52y!q2!!Qm*Fb<n6x_0R%oXo8hc2g@K0jm2cD zN~B3arsyS&LOZnELAOIKWT6)7>_UQ$QqaYZ6tqAhN=O1)V&x~)8!WQzgDE&1ay9`qund|Y?P_>(ThAzEiiPGJG##M-^-}VbJpg8>3($DeUTePcmJ=@X*7T) z-SIn)Izl|JcOOl|_D|~3N1j_Ti0)c&=w`IdEe7Xd`n{q%UAtV*$?(^+3iPx`vw-&6 zj=DuLY(o>CQ8|mcN<|&>_}^aCGlRbIIOnaKf6ykojk5d9!0lFdT=xden0tfU#{8Z}{hm6Tvty{!E;r~!Gxnf$U_IL7 z+xjS=Pv(!hiJJ?WWp_r|UIM*ihL1&w1w9jlF=L>k#&Fym>W-KabkwJ_BBH`A=x`8^ zgWiF!)#hx!MbG)I+T3|@tc)v9qP~!g(*i-iPNSF1b}VMy>lq0000007*qoM6N<$g7Wcbr2qf` diff --git a/data/flags/mn.png b/data/flags/mn.png deleted file mode 100644 index c4ce870b680448c8e1303f8e7b1addf653202de0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!2~3AZ}P1GQfx`y?k)`fL2$v|<&%LToCO|{ z#S9GGf*{OTpAtV2D9B#o>FdgVnTdyiO+q(LT$6!;k=N73F{EP7+ZlmeEe<@+mt8+_ zRsX;IR`idQy-Q(kuxt2Poqhb0B8tL6w=Z(>eazc^_kG>2visfZr#@%@UcwhsqL|IN zBSU(t*nxGEHutJkYb+~WbjqiA`RVUYC%>95S5;h8t2L#_$>q0!%}0w4VcVkz+{$y) zHoJK!Eq{Kh=gxjn^{RlAT!G3rFP2wjJc!%gmK5^q>jT+9&!B##C0%za1u#7e3G^3wg*4sG53kl4}<5qnwxs0 z_b)QNW0}Lw$Pgg&ebxsLQ0M}=kD*ylh diff --git a/data/flags/mx.png b/data/flags/mx.png deleted file mode 100644 index f48cb27eee2bf84ff895ed659e1190a4d95f9b87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 820 zcmeAS@N?(olHy`uVBq!ia0vp^u0X88!3HE(JU3qpq*&4&eH|GXHuiJ>Nn{1`*^<27 zT^Rm@;DWu&Cj&(|3p^r=85p>QK$!8;-MT+OLG}_)Usv`EEKHm#*5?9WpJZTQ+UV)x z7*a9k?aX)&;X;Pv_LpC*Tsqg$U(htnsL57j^Ii=K6=Yx)v596i-t|9%(ufdGGL<@cu~inj=TXulztv(0Fl zX;6vo!KC}OkN!^HAH?)4L|&oF$}wr)+`ys;b%xSXM_z^rclXcsd#mYt zkAtzk7O7#`1TayE4?GgM^b1lP? zee&r5#+R|T3#>(${t29yIjv#8>f?&#nf`7YwSS-Kh-g{)StQn5&ZhPNkIs5%{JQjDw?RDbd5v1a+CYsY8IK3NzOy&$#jipJvSo2Qk`-ao_cY`ws{ zrP`N!mmSRvVD`EGZ0DCm>z#Y;cP={Gur(}IblRTZEV2K#{y!7dRG7N5V*b&HU(|VOY|;P# diff --git a/data/flags/nl.png b/data/flags/nl.png deleted file mode 100644 index 7c7b04d3e0579f54366d5183c143828c4aff5e77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6f%r-ojUIG+~^mK6y zshIQj`axa>1)jqP8gA4--NfqAm){gsS?X(~xv5_M!>ofPY?mc{(hcT<7;}BDZoaa8 o1Cm(jLG9H0&UX(XDZ0uU@B4$zyR7Z#CZHt@p00i_>zopr00v1+YybcN diff --git a/data/flags/no.png b/data/flags/no.png deleted file mode 100644 index defe18fbb559da362d8775b793546f2395db86c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6f^sjW=ZvhI`dAc}; zRLpsM;~-aqf&fFH`Jeys+mc-zTV@(rzt<4qeZ90d%uCz$*2jt?PhVKX95MUN{4dR5 z?!gka%aT6n5XRNd=U+1{zW+aH7w2;BzNhc*B)n9M*+1v~TcLczmuhqLc9gyEo&Roq p^~;?+%Zz87OR#Ew31RG#{jo{NH}rkncc4ocJYD@<);T3K0RX#}V{ZTe diff --git a/data/flags/om.png b/data/flags/om.png deleted file mode 100644 index 4d21089a493dbca82d31c52a1e1682b6814d8b5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 884 zcmW-f&r4Nt5XHw-G=D4#g9-yTL7-4FAT0{g-oq!RNVrK_sL(`#AZ5^^f}+AikQNaG z(H{^Lh!jB}(WcErV5^8WK~M`X(!M>@EV65H;>=`~dl3~e5f=%OBv4TmQ*o70NpdD? zVkT}9CP}G_x|oZ*giF#Hq9GRIArX=ZmS~ElcuHi6fCd{dx+%{Rm1C-|8mh@u0#h?} z(=bg)kaIOxcMaEs6Q!XR>Y)*ukOnK&Qav@YjD<8o*0dOXi=RWS&YPJ^h1kkoJKBQVh1c~#t%rL7>SSu3)Zy43nEMg z8tg2s#XIs`aFP|`EP~-dI_n!Nze5pR-!L|pjn=nRXcgm8U#u;5)ZKz|*>_!WAzeg( zRA?5n>XVbh|55LzoP6fKo0s45CpOHE4p(Hc`B05u_k8W#Rgw0+~Y)N+K;*JzqeN>_w*iJ{&={0^5^?w h13SIzOZ@`_<5wD6*G|3irq(}9lacCp<;BqSo&S0=kRt#9 diff --git a/data/flags/pl.png b/data/flags/pl.png deleted file mode 100644 index cfadbe5f01bf5a4be133c843af8f149e75325235..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6fG`!xg5(f$ec)B=- zRLpsM;~?(=10H6><-gy*$-BsOrjY4wczSuc-lspd53*Tbb6pc%qa6{xVO>J(!Cg(I ltgp|V`;vJQLzL^<-dZg-PjzFXwLr5OJYD@<);T3K0RVQ#NJIbt diff --git a/data/flags/ps.png b/data/flags/ps.png deleted file mode 100644 index d0f1c9c0a927dc7d07ad935264a01c3c4551b822..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw#0(_wUoFf5QY`6?zK#qG8~eHcB(eheJOMr- zu0Wb$Cc}RQhX4QnKa3Hb1mrR%dAqwXbg;^L06Clm9+AZi4BSE>%y{W;-5;PJdx@v7 zEBhrD9u5mu*Gb|AK%pd07srr_Ij!e6@-is$I0sHUV;9*pPfch>lc2;~zYvZ62k%bq zaPFEuhpjxqgsX*Vp~E8Cyn=RD>plBsKj!Sd_n}FBP5aMzwRgV%(0{+OtT^W;GvAIw j(`+9!XoHv*{kQqgTovCaw%q3@&^887S3j3^P69;3lR~f_F}-H*Ahe+m<@d(7r;Kkjwo7V zwlmpYf%vdXQwrJ4$&mAkTN_fAGae(1(!g|)g$JCnmD;G9B?!B8CY1h=j@-BTG%j5& zHW%?2R+8epvJtCa`?)Tj!!AvuiYnVu_){Ou(~4yGzd%f3pOvjTW&pk9l?F840q5cq z5mMM@<-=iTNUl&hM0hMY#f?YSJqtq$t2+8Vwf74klO-WAY_!z$^HwOlKZbMlw0+q~ z79)GD4+5WZ!6fX8;X*d{Pt;C}km`CeUJ;|7GPa1=Y|x&Qo|L|o=+>Euu^5*A4U)_* z3{cpU&#ra(EFExR8^>J?hQyhORa&Mxg6*SJ*|-H5|JOr;9K+-HdlDDBXW$KFTIO2gAg&JgY2KJM5eDP7{zGGUJMl-MNuM!+<`_=e&$F#=|;#s?Rv%L^m tk)sNC@cce}Av}cdj)(Bw@esZ{egVub*FHvEz<~e&002ovPDHLkV1moF5irnZ~`QY`6?zK#qG8~eHcB(ehe1_3@H zu0T3MfSqAK!~Xq1CXfKJ4jeep(9rN7DDa=*KbQj2Ko$^4xb3?G6lYBGc6VXuV3qX% zaySb-B8wRqxP?HN@zUM8KR`kD5>H=O_Dd{09OfGBSHru2LK&Vejv*Cu)=oMo$e_r< zoO|%!>Mcw)7LV^L=ajVMH@snqTJvgG6pLxirYqZRGNQWoXSN@^=aaWbc-x|gik*&+ z12(tKig@Fxa(m^O)3UQ{JB{plu2x!aneKlzrF7$hp3}mcy8UYv{P(CAc=o+G+g1n) O0R~T3KbLh*2~7ZS@n~-V diff --git a/data/flags/qc.png b/data/flags/qc.png deleted file mode 100644 index c2b9c4407fd4a59d746625f766dc1d117f21ac90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6fWMyLVOn^dK>wmzZ`y=D( zf*Je5)?G7iiqloGt+)~vWYl@|pz~@~7DwLv_!+OC`BZIL&{jV&{PP=GJ<}QQHl#6m zn?!ZY^!-0=-LVpNU5RgeJk{)Ndzla41DfBV&#*vn6@E zyDx`7I;J!Gca%qf-qx!O8i8iAbW|YuPgfnE(u|Ilh2iAF+ibcPZ!6K ziaBr3FBD`@6gYa}Da)jPuaC@&V9~8{R$Je2CMBdaJmCGzGqJDxm+p&rDad!((&xFs f+`}aV8Fv|Xzhw2h8IlnOw1&ac)z4*}Q$iB}3gS#< diff --git a/data/flags/ru.png b/data/flags/ru.png deleted file mode 100644 index 33b2176a991e0dcaa1edea0a3eb510c76618c60e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6f#Jc;o?*R&hc)B=- zRLpsM{U9%c0nZ_aOMlCkMQ@q(cs7Im%x!0to_}w+&a=#T#<>Km=9eHwp3r@vSqDql wE=&5P8_Yde^15kx=kvxhFzIs%yGjp=b1dO->sq7m5NJMwr>mdKI;Vst0O=A-X#fBK diff --git a/data/flags/sa.png b/data/flags/sa.png deleted file mode 100644 index 759b86d65ada03ae75c8054102d2f343c8775155..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!VDw>rnZ~`QY`6?zK#qG8~eHcB(eheDgizr zuK)l4zxVw8-gC$1?A6Gd@E!jQQQ7zd~*~ymKK@vfh3~3BJ;VnHt^^8g0?k)@+ ztg;?J4rhT!WHAE+w-5+3UbFSZ!g+& z9Wsz${jfgEwQ{kz#-nMt>sD!o+*7PwIMX1d9msv z^P_s3cS&4`KeSDM+Lf1DPopM?Os(Jf>2KitgNwg@{{M_!@3O{fu}?lFg+|B1dp~*q c`(tQ+Z<@03_qc5@fWBk!boFyt=akR{0K~|eQvd(} diff --git a/data/flags/sd.png b/data/flags/sd.png deleted file mode 100644 index d9249cee5774673d9d847a39af51018633ee25d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 339 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!VDw>rnZ~`QY`6?zK#qG8~eHcB(ehe1_3@H zu0WdM9K(MGhW|tWpxQfg@0kKA#w2fd7lsa2Sq~tGv%n*=n1O*?2!t6g-L3lr6l5>) z^mS#w#KOa2CKPdKexhh%6Ty3B6y7IQd^cU=lf1OjfCs|Pt`gfgS_pdpB zcKw>1Kd)dl|M?w9r+zpZyshf*?8=`Hvi>C2=r%9?q_1g|dwybor-{Y&bE?mjY}uF%Qo^}C{AP8=ck9@l8PCf8KP3TlB!j1`pUXO@geCwPl#E8(A1FHC;fz~a4FeD})c=(T!Q=RaCqzj30Sxgy>zKmNM($;;yQN_PQs(wEslIXL2zy0p-KX6n7yQXCfQ4XIO Yzozoc4)Dvn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ6fSosaUB>{!zdAc}; zRLprh&5-Ya0uS@-uK)Fxva9&kI*CkMbYq{O;t|IJgYxgq9mU_-{<$4`;UOW*x!8D- zqj7Z9l3;EA*8EjM+3lO9cTJjRU{!KxvD68F0r$`1&b8W}UiWLP{nYL?ZdtPV+pQH} z_s!r6Z?W>a+$uKrgUOb#|CeKDaG2N3aed(x1va(#i3i_;-HDuwl@m);diq)}P6Qb! XUR)y?xG2a76c`Miu6{1-oD!MC;TkV8a>D7?7H`{KUqD~5hv9z$Mtz{R&F2)37H#>q;FBD|bQzknY zC$sg7?BeKY)Oa*DCy8~xo5Oj(_&?`;&hxzQBYg5{OBjImc3S7XylA|-rCbAEp!IZ~UQrBp6-hqrwI~@ht8w@H@hVk6_5%JVf#s+5)%8NmHHs{*% z2y^>$jnw>H#Pkn$i%uF$c`SF{)Y=||mf|kT2;O_$4uDxrOWi=phCz;kYyzRM*5j%F z2zSd(Ooc}P^}yn`n3+9Mis?)RnWZP`7M*xde}^1-C}nc|Pk)UAAgtb&9{2st-G|{d zgXR|M@!N_tmwsvPAKgWtWWEBxqhBVuTGO&&y;MMR>9BRnfX&$83`$QQV}mnV+xqud z)=MPs929_Uq@_rN@?sh%7Lm@oaWprf^z_kq_7ajsK(Lsx8X`5m#1ypj0@Q8^UfbH? zZqdo{6D~Z3NAQ4p&;X{bE~N8rJg$RG7rhT}+YFQ%A7XOp^@j;ZK{k%&CbbXni%tLz z#YdYV=(@DucL7h!7X(6Kvc9{6-&RCzmc&$L6`%&J+AImbtw@XJZi|^5d5C-W7ZYMY ztmy7=*KcofsLI8)3`$4+1N$e>indS+I?uFL8#Q$fS!HkeS|v~}JK+M&V= z6J21+k=d%0M)i7Ubx8)b{Srz_XKz z9-^<3+AJwf(u~0jAU*vZ3c)M?N+1+QvIuLQO3yL;fh%NYT-RM}Y;Xq2B0#81eWnmy zc&Xmkh45{4br|6I{8MHJMzx3=iEPiuQd5DicY4!w6YTdPlov;xpG;N*>Vwb{flzpD zl-^9Nbv#J#^>%J|)1917$}mcE2mZhng8e>D7pF7%!!hO- z>dBFZ)XGPS5@~cymxs){TKu*ma^xXych)g&bum?0MQ_b#DY?7RSd*5vBf3NxhSHNf z0p3_`GeB58k?r}ga+}+8b?N^Ne$mkko*fv~8@H>88l|%i=jx`V-AtriQ7;d&Js<0M za7Q0tr}K;;TGr7Fo*fuf3vr?oLQA;q`8zAjt;|meR!UCph$dm5>GRa9mK(@_ey(rc TrnZ~`QY`6?zK#qG8~eHcB(ehex&b~R zu0Z<1g9i&593B)fJow0<5Ma>Ikg#CEgaiYD1_p)$3=A6r3>X9w6dW2D3O;mw$lwQR zU`+CMcVXyYmGuB}I14-?iy0WWg+Q3`(%rg0Ktc8rPhVH|ODsGb`h3?9d+7m%{5@S9 zLn`JZSG0>8^mqk3M)9rx;(TfetL8+pBg(oQtVK7L$|s#zB*i!Jc&_;_ompR;|6F1z z5uP-yy8Tgs$@J3;+pSiabR5v_<#b#6QlFQB@36t`sfC2m$h9qnk>UOu2uxTlL_NX4AD*AMbCDDWIU&~T&v z=_Xc>zWk=B+Eia7%}w?4A7&jaVY@8plWs8gU`gpgZOP-zGf_mAXIqKX-AJ%%e#x`U ec*Z#pL+{N@Ht(&DM_vG}VDNPHb6Mw<&;$Uv??cD{ diff --git a/data/flags/sy.png b/data/flags/sy.png deleted file mode 100644 index f74e6b80b54924c16c28c1c841539466ae9ed74e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!VDw>rnZ~`QY`6?zK#qG8~eHcB(ehe1_3@H zu0VPw0|QX{Kad4u8qfT1eC9tx8dTu_8HWG=8UCjM$^WlBr^x^nGA4PuyD)UH%6b4f zoCO|{#S9GGLLkg|>2BR0pdfpRr>`sfB^DkIU9}4i4Pii`AWs*^kcv6U2FJK1+?Kx7 z|0}Pr5Labex}-jFY8>nIxPHyQ*;lnz*i6_c=lsjwsX+9OjLOUS)&Cw(j$_?k^jBZ! q((6RO|E*6rSFvh^y$m$C!NB0p@q9vObkSCz=?tE(elF{r5}E)Xa#myj diff --git a/data/flags/th.png b/data/flags/th.png deleted file mode 100644 index 1b55adf3ecb66ca24a30a3f172182ee352234371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7KO$65`%m)f3c)B=- zRLpsMvyqcQk%#5r>E!>q$MxcF++KM=b%96PWZ#MJzcT(yGnjj@gzfU&oU6un%oCem z@+_M@CH8Wuu-S}r305Gk@r-qPKT2w4xzuwEVq-t-kZ&`FNa@9kae1sbdes7G7lWs( KpUXO@geCy*X--K1 diff --git a/data/flags/tn.png b/data/flags/tn.png deleted file mode 100644 index 9b5753147a15158bceda6dc756c74f0f69f5b777..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw$P6TBlydI@QY`6?zK#qG8~eHcB(eheYymzY zuK$66f#G%3^T|LF#w2fd7lsa2Sq~tGv%n*=n1O*?2!t6g-L3lr6l5>)^mS#w#KOa& zEA;V8$zz~Uh^LEVNX4AwAN-8+5*Y_A68KXMJ~&JKe{x%~$G-H8z_EV$9)V-$`2&s} zZ|4y>_PkwqK~J;%f}Y3x7bFWbXC&?TCU3y}FznC9WVd3rJBb|2FR7U@TzaFP&8uSA Q3pAg>)78&qol`;+0P&ni-T(jq diff --git a/data/flags/tr.png b/data/flags/tr.png deleted file mode 100644 index 395e0b76c066f853240c7de9fdff0064ca5c64fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 392 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU@|l`Z_W&Z0zU$lgJ9>vn6@E zyDx`7I;J!Gca%qfiUBxyLEqng6t)pzOL*SSeQ7KwdX9)&0=6+Wc74$ z45^s&cE&}%!wMX(sW<=s-&CD-Yo-=QQ`emo{?lQnKXxsc5Pa&TLTws*!dixJ>wxHS z!~R9fje{;SxE#*rh$xj{{#$)G>Ow7Fu!Hx3Ikzv|c;D>G{!H)wQJH1AQBgaqdT&ow za(c+Oy(#jHZPzWn>~l4i+a{j=v+2rXJ<(@x>zl(T`aV9$8>N`~>cHaS?cXJr{yn&D z>k=o8ytZ$9P1qLi`7B>v!I4m!sOq&-?t0_Kw)z%^cl{G{Wb6DwIDh_G_rgd%Lg>no z$)VB_$_*z|JIfw#d>HEIyG6B^QF31T(nZe=Sby=>Y&>c4PN<)~CiC!}X^iFS$q}tw5^g`2d~^;xs4?Hfj^SCY){|}f=9~vAVeoYIb6Mw< G&;$TSvoJLP diff --git a/data/flags/uk.png b/data/flags/uk.png deleted file mode 100644 index 486303cee2826f97ad3d6e2792d3ac956b18d69c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1210 zcmV;r1V#IaP)w^Rou1r2#gc(@?XvciBmv+?BuuBy)*15RB@5TJ7 zzfTuR5V>wnE{oc`UbIVYI3UV3nhS$N1kMn^W%BL4hy}0<5~9Mkv7JqTj+)7-?LfKj zOYd!y?=Ju(yCJr<-kv|nm0lB`Gs?(vjV5GMYz0^lmXamkU(iMrW!_>zSRl?dT1wm+ zvJcJe$g`j`72MF|xf({&`|LGOI7ZRFXc5EC5${-eB3z@0k8t>;;}pz$&B?;CiH$j`H0;tyb&BOn!K?InA+0khWOe4Q>cYsg zz=9APbAZVIot*Q%JF}ICgX>JeuNp8oYO1m7fNH*hNonk zLbfSY8##ComtJ4z;Zya!2WJsJ6{m#swNP2KZV|1w zUiZU1{2B1S^Y9npTgMmSTgMmSTgTU%)~%!Q*HTkl`UBw7`tD9?w^p@q#B74Co!3R@ z4wU|RolQm8u^F4ip7Y8B7z1!x%eZk!SCQqE6v(n5gwpRryrb)JjPBe4b=LVc2L{Aq zmf6;{yHZOyT$gtwW8W{dV90Qk6`_`9gFZChePY;XY4Yn8T~G9?`^m?4@thUHU0@+t znzd_G5>96}GH^-?(>WG|=uYQYy1cfxR0c&&h`atqDra6G@0||}u&z?;ZD~)dDtu-6 zM4fe3NM!kR&bYKPm1^2SGJQD@>)&YY0y(njXhYXQ2QOEdHxa|eV7!*f>Lw+TXMuL| z6VZ%tBnQd@zgbDSWA zz2qM{MI?reU%os+tGu1|$w5f@t7YuE2*>%VM}{MGr}J#_rnvMk4~OGY8LE2c(l@QD zCb(uU!TDBl*T*5PW@b-ch9RGFPFtJS)o1^M2LR}UUG9`F%ihxd Y1*2juWpvG3X8-^I07*qoM6N<$f+h_?Gynhq diff --git a/data/flags/un.png b/data/flags/un.png deleted file mode 100644 index 47c6f742a3f093aaff9d81a08126483eea481092..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1068 zcmV+{1k?M8P)3Pu4W*?q$4MUm~2w0yT*ltVF?mrk=BH)-t>^gg2rr&(U@ zMW8li*+(;;jJ8!D9bDjhxJkzd{IWmI@`f|)#KB7>z?IgfY`ZUtrZzd(ru{B+<}dqf z+ouh^G<^GPYL0DED^h#$!mG3^wJhgT!$iFBjCax^j`q|}%hCe9$~FxVHZ67C@9Uf0 zzgC*%<$|+|v<4weC(?z$_mE~e=F1HL(|LtS?Re(PO*N*=Y$v0w;Urzri!cSc3rcTF zp{3WP7o``c=ep@$tzM^97%k&tHqg&wnn%q$xy>O zjCDykdJ$gj#?}l+?$^oxO%owEG{awQ>TS4vMzyH?9|j&kX*rMnewlljG_|BPK?19t zNrc*z2>~6H9#2b=TD57AjxUL7+8rJN^; zx{?KYnsm8`yh^y(FMqkOv?H>mdH^sP)%%y@<=C#{i9}t~#$FnpjJB1~gcMF|c(ofh zLP`LJDRW#jHP2_j)U<4q&TtJoLiVDP$hnB>-@Mn*$nk{cv}I<}Ui+K#RdRfq@LKbh#bx9u4)&ujp#=kcL9 z31OgFwgt*U0g37OSARy4mcmqVi0@4&BMbn)e*Z!8_d5V!@okNtKV|^jzdv6k!<0zq3q)$ik{Ho2Iq#GFV%OAY*aclNn2a z9=gbCn5Re&u@M-O3xahBI!Ho6c!$F=EuV1_Z*5|d>AG~BVe!@`>a$EFh8e$g66dvqKxk060>hxS z%u8Xxpda%K%6}OE%sjh_a6^?_J{(K5gWJh={7^Nd?!Goz?{;ZBVf8k1#TWpD8>-+x zcElwc&Se^wiG;jT!2Pi~*jYN0bCvOw2mrAt!Sm4zXutN#OsE)>iG;Z)m(i1YYrZjq zIgK;e=FNU=dT!U!!^Qsny=2^$CF8qeE0II5CYI>0>IaSp#n_Zz;UMXNUyF%R{uM{vfy~wcH?21__);KHUA!g%Y zY%#|ky)T*dB_asaR5OeaiCV7#;B)7?TOLXhv+>y6_{ju0W&h%9>nzhgWE~~wwuC@v zP?w2>-b4iHOpfZqy=1(WCG!o}Z% zFv0Y2EJ^@?+WWfA0C1bqOb^G~!T{(5owAnGM^RT>&9GA^4l#y#$$Z1HC}EP?OQsCe zxZ|Ki*$xj{k;8*V4W3e1PYTq=!^+mCCOtO`RN&!3NDjT!cMfx3shTAokA<+Me9?JK zOJ4Hr98z8qwq8tfDQR93md>24D8m(3(xU%dEAJdU)&7(&cZtX?;P>h(?>s!y{**3v zi3bli^3K6i?N8})m-uP*7sB|;I}gt!EO*BBKi|Lc&cieLD#>f>dm{7rkpi?v8`m55Bfe=}(t;OC+LfN} zR%|ec^SFoRCNJtjHHWL?L}RHl`34o@YcoR25!hg*_LOJIi(Uwd*?TzP_o19<1mMYi z6-BD=^u;wC*qcPqC3x2|0YI=Ye!L_3*3P7o| zfc>Tso<1l+_!c6e^kCm*BODU{I<;2{X@aNM&9}a1e2Hra-W|iS2b``LovjAOzpi1o ztDk{SYkBm19osf4P{&gfy~wP|KEag^H` zkBmkE#yFZqgDcI$;gHCHcmhF}Alj7#Qdc|JtDv?nm&l+%PV5K%SETv6qs@qM^SLx1 zuhgNHwudcNJDcpcsW|uveYuzRu$nt<<+y58M7xr_eE5TWg9?kigkZ0N$-H`!IWH)y zxP{heTP_X%#GK$U?Zb}NX0}$jxzfHY_ZyB{MgZEWZ%hdv_>0+W&;~G z-vfTFuWUg2A}fUsDs zx(>^NrOv7oEbn2dBMX)~a`2EkvS6vR>IBQdL+Z$arOrWy diff --git a/data/flags/vn.png b/data/flags/vn.png deleted file mode 100644 index 3fc1c810f2b500039c0fab2581b4a210fed33c9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!VDw>rnZ~`QY`6?zK#qG8~eHcB(eheDgizr zu0VP}81DyD`+>au`wtvA(9qEEA1MBx;s1YztaBl^fNaJjZ+91l4pvzYAcwQSBeIx* zfm;ZK886+f`vVkYFY)wsWxvEM&!??1b#V|2P$=Hh#WAE}&f5##Tn7|*SOVVHGtZpN zvomI)SXSMoOS=R&cXTgL+j1pw>REn?KZlfpXEM8;yA*n0$5h7a4>rtt8*2FGs+#4R ze<$^BdT-mmPX5?x)tYZpZcj42swaQ;`lcEN3zJ(nV-|O80b0f2>FVdQ&MBb@0GfJV A7ytkO diff --git a/data/flags/ye.png b/data/flags/ye.png deleted file mode 100644 index be7080c23d8a5d7c645414c4ef6c764f486e547d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!VDw>rnZ~`QY`6?zK#qG8~eHcB(ehe1_3@H zu0VP}81DyD`+>au`wtvA(9qEEA1MBx;XjxH(m)mvv^@Tn0~BXW@^*J&=wOxg0CG4B zJR*x37`TN%nDNrxx<5cc_7YEDSN2ORJRG_VOunqEfkHB#E{-7;bCPFtiW~HJU5@`{ kA7`Lt`(ugw!31UoD}(Nd%}*6;fa(}LUHx3vIVCg!02X{eWB>pF diff --git a/data/flags/yu.png b/data/flags/yu.png deleted file mode 100644 index 9470101b8ade37229ba9744b15865cb7e79e67de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp^HbAVw!3HE3?VkA`NU`sfB`yhGJ|%vZ{v4oCq^FBxNX4AD*AMbCDDWIU&~T&v z=_Xc>zWk=B%2HKh%}w?4A7&jaVY@8plWs5<#F)D-eq}*o^Glv(#xu?(ST(rnZ~`Qn~>?A+A9B!Gi}28XO)JFg*Ck zpb%it(2%fT!Gr_@fd&SK0}Kos0t^@g5)>R77z#dgeaPSkYG6$Ac6VXuV3qX%aySb- zB8wRqxP?HN@zUM8KR`kD5>H=O_A6X`%uLdujC~-hn><|{Lo7}oy?mFqL4k+m!MXzO zlK)$GF&InyeBGF_Na+(x4f{e+2>vvDvHm_HbeO>Re6(9I4ZW+GF%eFiDGV%Gtho_G92)bP0l+XkKdO2+4 diff --git a/data/man/CMakeLists.txt b/data/man/CMakeLists.txt index 318c5ba..822c093 100644 --- a/data/man/CMakeLists.txt +++ b/data/man/CMakeLists.txt @@ -19,7 +19,6 @@ function(BUILD_MAN_PAGE _sources _src _dst) endfunction() build_man_page(MAN1_OUTPUT "ddm.rst" "ddm.1") -build_man_page(MAN1_OUTPUT "ddm-greeter.rst" "ddm-greeter.1") build_man_page(MAN5_OUTPUT "ddm.conf.rst" "ddm.conf.5") build_man_page(MAN5_OUTPUT "ddm-state.conf.rst" "ddm-state.conf.5") diff --git a/data/man/sddm-state.conf.rst.in b/data/man/ddm-state.conf.rst.in similarity index 85% rename from data/man/sddm-state.conf.rst.in rename to data/man/ddm-state.conf.rst.in index b6475d4..1814131 100644 --- a/data/man/sddm-state.conf.rst.in +++ b/data/man/ddm-state.conf.rst.in @@ -2,11 +2,11 @@ state.conf ============ ----------------------------------- -ddm display manager configuration ----------------------------------- +----------------- +ddm configuration +----------------- -:Date: August 2014 +:Date: Dec 2025 :Version: ddm @DDM_VERSION_STRING@ :Manual section: 5 :Manual group: ddm diff --git a/data/man/ddm.conf.rst.in b/data/man/ddm.conf.rst.in new file mode 100644 index 0000000..326fe89 --- /dev/null +++ b/data/man/ddm.conf.rst.in @@ -0,0 +1,147 @@ +=========== + ddm.conf +=========== + +---------------------------------- +ddm display manager configuration +---------------------------------- + +:Date: Dec 2025 +:Version: ddm @DDM_VERSION_STRING@ +:Manual section: 5 +:Manual group: ddm + +SYNOPSIS +======== + +Configuration loads all files in the configuration directories followed by the configuration file in the order listed below with the latter having highest precedence. Changes should be made to the local configurations. + +**@SYSTEM_CONFIG_DIR@** + System configuration directory + +**@CONFIG_DIR@** + Local configuration directory + +**@CONFIG_FILE@** + Local configuration file for compatibility + +DESCRIPTION +=========== + +This file configures various parameters of the ddm display manager **ddm**\(1\). +If this file is not available, default values are used. + +OPTIONS +======= + +[General] section: + +`HaltCommand=` + Halt command. + Default value is "@HALT_COMMAND@". + +`RebootCommand=` + Reboot command. + Default value is "@REBOOT_COMMAND@". + +`Namespaces=` + Comma-separated list of paths bound to Linux namespaces to enter with + setns() before starting the user session. For example, to enter network + namespace `mynet` created with `ip netns add mynet`, the value might be + `/run/netns/mynet`. Default value is empty. (The value is ignored if + the operating system is not Linux.) + +[Theme] section: + +`CursorTheme=` + Name of the cursor theme to be set before starting + the display server. + +`CursorSize=` + Cursor size to be set before starting the display server. + +[X11] section: + +`ServerPath=` + Path of the X server. + Default value is "/usr/bin/X". + +`ServerArguments=` + Arguments to the X server. + Default value is "-nolisten tcp". + +`SessionDir=` + Comma-separated list of directories containing session files. + Default value is "/usr/local/share/xsessions,/usr/share/xsessions". + +`SessionCommand=` + Path of script to execute when starting the user session. This script + receives the value of the "Exec" setting in the ".desktop" file of the selected + session and runs it. + Default value is "@SESSION_COMMAND@". + +`SessionLogFile=` + Path to the user session log file, relative to the home directory. + Default value is ".local/share/ddm/xorg-session.log". + +`DisplayCommand=` + Path of script to execute when starting the display server. + The script will be executed as root when General.DisplayServer + is "x11", otherwise as ddm user. + Default value is "@DATA_INSTALL_DIR@/scripts/Xsetup". + +`DisplayStopCommand=` + Path of script to execute when stopping the display server. + The script will be executed as root when General.DisplayServer + is "x11", otherwise as ddm user. + Default value is "@DATA_INSTALL_DIR@/scripts/Xstop". + +[Wayland] section: + +`SessionDir=` + Comma-separated list of directories containing session files. + Default value is "/usr/local/share/wayland-sessions,/usr/share/wayland-sessions". + +`SessionCommand=` + Path of script to execute when starting the user session. This script + receives the value of the "Exec" setting in the ".desktop" file of the selected + session and run it. + Default value is "@WAYLAND_SESSION_COMMAND@". + +`SessionLogFile=` + Path to the user session log file, relative to the home directory. + Default value is ".local/share/ddm/wayland-session.log". + +[Single] section: + +`SessionCommand=` + Path of script to execute when starting the user session for Treeland. + This script receives the value of the "Exec" setting in the ".desktop" file + of the selected session and run it. + Default value is "@WAYLAND_SESSION_COMMAND@". + +[Users] section: + +`DefaultPath=` + Default path to set after successfully logging in. + This is also where DDM looks for programs. + Default value is "/usr/local/bin:/usr/bin:/bin". + +`RememberLastUser=` + If this flag is true, LastUser value will updated + on every successful login, if false last user value + won't be updated. + Default value is true. + +`RememberLastSession=` + If this flag is true, LastSession value will updated + on every successful login, if false last session value + won't be updated. + Default value is true. + +SEE ALSO +======== + +**ddm**\(1\) + +The full documentation for ddm is available at https://github.com/ddm/ddm diff --git a/data/man/sddm.rst.in b/data/man/ddm.rst.in similarity index 68% rename from data/man/sddm.rst.in rename to data/man/ddm.rst.in index 0dc122c..4b06981 100644 --- a/data/man/sddm.rst.in +++ b/data/man/ddm.rst.in @@ -2,11 +2,11 @@ ddm ====== ----------------------------------- -the simple desktop display manager ----------------------------------- +--- +DDM +--- -:Date: May 2014 +:Date: Dec 2025 :Version: ddm @DDM_VERSION_STRING@ :Manual section: 1 :Manual group: ddm @@ -19,13 +19,8 @@ ddm [OPTIONS...] DESCRIPTION =========== -ddm is a display and login manager based on Qt technologies. - -Using QtQuick and QML, designers are given the ability to -easily create pleasant, modern looking interfaces for ddm. - -ddm runs the greeter as a system user named **ddm** -whose home directory needs to be set to **/var/lib/ddm**. +ddm is a display and login manager based on Qt technologies and using +Treeland as greeter. If pam and systemd are available, the greeter will go through logind, which will give it access to drm devices. @@ -62,9 +57,6 @@ FILES **@CONFIG_FILE@** Local configuration file for compatibility -**@DATA_INSTALL_DIR@/themes** - Where ddm looks for themes - SEE ALSO ======== diff --git a/data/man/sddm-greeter.rst.in b/data/man/sddm-greeter.rst.in deleted file mode 100644 index 89d369f..0000000 --- a/data/man/sddm-greeter.rst.in +++ /dev/null @@ -1,67 +0,0 @@ -============== - ddm-greeter -============== - ----------------------------- -ddm display manager greeter ----------------------------- - -:Date: May 2014 -:Version: ddm @DDM_VERSION_STRING@ -:Manual section: 1 -:Manual group: ddm - -SYNOPSIS -======== - -ddm-greeter [OPTIONS...] - -DESCRIPTION -=========== - -ddm is a display and login manager based on Qt technologies. - -Using QtQuick and QML, designers are given the ability to -easily create pleasant, modern looking interfaces for ddm. - -ddm-greeter is an auxiliary process that displays the greeter, a graphical -user interface to perform the authentication and select the session to run. - -It is launched by the ddm daemon, end users are not meant to run it. - -OPTIONS -======= - ---theme `PATH` - Specify theme full path. - ---socket `NAME` - Specify the socket used to communicate with ddm daemon. - ---test-mode - Start greeter in test mode. - ---help, -h - Show help message and exit. - -FILES -===== - -**@SYSTEM_CONFIG_DIR@** - System configuration directory - -**@CONFIG_DIR@** - Local configuration directory - -**@CONFIG_FILE@** - Local configuration file for compatibility - -**@DATA_INSTALL_DIR@/themes** - Where ddm looks for themes - -SEE ALSO -======== - -**ddm**\(1\), **ddm.conf**\(5\) - -The full documentation for ddm is available at https://github.com/ddm/ddm diff --git a/data/man/sddm.conf.rst.in b/data/man/sddm.conf.rst.in deleted file mode 100644 index b79472e..0000000 --- a/data/man/sddm.conf.rst.in +++ /dev/null @@ -1,254 +0,0 @@ -=========== - ddm.conf -=========== - ----------------------------------- -ddm display manager configuration ----------------------------------- - -:Date: March 2021 -:Version: ddm @DDM_VERSION_STRING@ -:Manual section: 5 -:Manual group: ddm - -SYNOPSIS -======== - -Configuration loads all files in the configuration directories followed by the configuration file in the order listed below with the latter having highest precedence. Changes should be made to the local configurations. - -**@SYSTEM_CONFIG_DIR@** - System configuration directory - -**@CONFIG_DIR@** - Local configuration directory - -**@CONFIG_FILE@** - Local configuration file for compatibility - -DESCRIPTION -=========== - -This file configures various parameters of the ddm display manager **ddm**\(1\). -If this file is not available, default values are used. - -OPTIONS -======= - -[General] section: - -`DisplayServer=` - Select the display server to use for the greeter. - Valid values are: - - * `x11`: X server running as root. - * `x11-user`: X server running as unprivileged user. - * `wayland`: Wayland compositor as unprivileged user. (Experimental) - - Default value is "x11". - For `x11-user` you might need to configure Xorg.wrap(1). - -`HaltCommand=` - Halt command. - Default value is "@HALT_COMMAND@". - -`RebootCommand=` - Reboot command. - Default value is "@REBOOT_COMMAND@". - -`Numlock=` - Change numlock state when **ddm-greeter** starts. - Valid values are `on`, `off` or `none`. - If property is set to `none`, numlock won't be changed. - Default value is "none". - -`InputMethod=` - Set the Qt input method for the greeter. - Tablet users with Qt Virtual Keyboard installed can set this - to "qtvirtualkeyboard" for the on-screen keyboard. - Other known values are "ibus" for the Intelligent Input Bus, - or "compose" for dead keys support. - Leave this empty if unsure. - -`Namespaces=` - Comma-separated list of paths bound to Linux namespaces to enter with - setns() before starting the user session. For example, to enter network - namespace `mynet` created with `ip netns add mynet`, the value might be - `/run/netns/mynet`. Default value is empty. (The value is ignored if - the operating system is not Linux.) - -[Theme] section: - -`ThemeDir=` - Path of the directory containing theme files. - Default value is "@DATA_INSTALL_DIR@/themes". - -`Current=` - Name of the current theme. - By default this setting is empty, meaning the embedded theme - will be used. - -`FacesDir=` - Path of the directory containing face files, - face files should be in username.face.icon format. - Default value is "@DATA_INSTALL_DIR@/faces". - -`CursorTheme=` - Name of the cursor theme to be set before starting - the display server. - -`CursorSize=` - Cursor size to be set before starting the display server. - -`Font=` - Name of the font to be set before starting the - display server. Please note that the theme can still override this option. - -`EnableAvatars=` - When enabled, home directories are searched for ".face.icon" images to - display as their avatars. This can be slow on some file systems. - When disabled, all avatars will be default. Themes may choose to hide - them altogether. - Default value is true. - -[X11] section: - -`ServerPath=` - Path of the X server. - Default value is "/usr/bin/X". - -`ServerArguments=` - Arguments to the X server. - Default value is "-nolisten tcp". - -`XephyrPath=` - Path of the Xephyr. - Default value is "/usr/bin/Xephyr". - -`SessionDir=` - Comma-separated list of directories containing session files. - Default value is "/usr/local/share/xsessions,/usr/share/xsessions". - -`SessionCommand=` - Path of script to execute when starting the user session. This script - receives the value of the "Exec" setting in the ".desktop" file of the selected - session and runs it. - Default value is "@SESSION_COMMAND@". - -`SessionLogFile=` - Path to the user session log file, relative to the home directory. - Default value is ".local/share/ddm/xorg-session.log". - -`DisplayCommand=` - Path of script to execute when starting the display server. - The script will be executed as root when General.DisplayServer - is "x11", otherwise as ddm user. - Default value is "@DATA_INSTALL_DIR@/scripts/Xsetup". - -`DisplayStopCommand=` - Path of script to execute when stopping the display server. - The script will be executed as root when General.DisplayServer - is "x11", otherwise as ddm user. - Default value is "@DATA_INSTALL_DIR@/scripts/Xstop". - -`MinimumVT=` - Minimum virtual terminal number that will be used - by the first display. Virtual terminal number will - increase as new displays added. - This setting is no longer available since DDM v0.20. - -`EnableHiDPI=` - Enables Qt's automatic HiDPI scaling. - Can be either "true" or "false". - Default value is "true". - -The `XauthPath=` option is no longer necessary, libxau is used instead. - -The `UserAuthFile=` option was removed, the file is always created as -`/tmp/xauth_XXXXX`. This is necessary for to the use of `FamilyWild` entries. - -[Wayland] section: - -`CompositorCommand=` - Path of the compositor to execute when starting the greeter. - Default value is "weston --shell=fullscreen-shell.so". - -`SessionDir=` - Comma-separated list of directories containing session files. - Default value is "/usr/local/share/wayland-sessions,/usr/share/wayland-sessions". - -`SessionCommand=` - Path of script to execute when starting the user session. This script - receives the value of the "Exec" setting in the ".desktop" file of the selected - session and run it. - Default value is "@WAYLAND_SESSION_COMMAND@". - -`SessionLogFile=` - Path to the user session log file, relative to the home directory. - Default value is ".local/share/ddm/wayland-session.log". - -`EnableHiDPI=` - Enables Qt's automatic HiDPI scaling. - Can be either "true" or "false". - Default value is "true". - -[Users] section: - -`DefaultPath=` - Default path to set after successfully logging in. - This is also where DDM looks for programs. - Default value is "/usr/local/bin:/usr/bin:/bin". - -`MinimumUid=` - Minimum user id of the users to be listed in the - user interface. - Default value is @UID_MIN@. - -`MaximumUid=` - Maximum user id of the users to be listed in the - user interface. - Default value is @UID_MAX@ - -`HideUsers=` - Comma-separated list of Users that shouldn't show up in the user list. - Default value is empty. - -`HideShells=` - Comma-separated list of Shells of users that shouldn't show up in the user list. - Default value is empty. - -`RememberLastUser=` - If this flag is true, LastUser value will updated - on every successful login, if false last user value - won't be updated. - Default value is true. - -`RememberLastSession=` - If this flag is true, LastSession value will updated - on every successful login, if false last session value - won't be updated. - Default value is true. - -[Autologin] section: - -`User=` - Name of the user to automatically log in when the - system starts first time. - Default value is empty. - -`Session=` - Name of the session to automatically log in when the - system starts first time. - Default value is empty. - -`Relogin=` - If true and User and Session are set automatic login will - kick in again on session exit, otherwise it will work - only the first time. - Default value is false. - -SEE ALSO -======== - -**ddm**\(1\) - -The full documentation for ddm is available at https://github.com/ddm/ddm diff --git a/data/systemd/CMakeLists.txt b/data/systemd/CMakeLists.txt deleted file mode 100644 index e4a01e2..0000000 --- a/data/systemd/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -if (NOT DEFINED SYSTEMD_SYSTEM_UNIT_DIR) - find_package(PkgConfig REQUIRED) - pkg_check_modules(Systemd REQUIRED systemd) - pkg_get_variable(SYSTEMD_SYSTEM_UNIT_DIR systemd systemduserunitdir) -endif() diff --git a/debian/control b/debian/control index 2e6c183..e5f73c8 100644 --- a/debian/control +++ b/debian/control @@ -8,10 +8,6 @@ Build-Depends: debhelper-compat (= 13), libpam0g-dev, libsystemd-dev [linux-any], libxau-dev, - libxcb-xkb-dev, - libxcb1-dev, - libxkbcommon-dev, - libxcb-ewmh-dev, qt6-base-dev (>= 6.6.1~), qt6-declarative-dev (>= 6.6.1~), qt6-tools-dev, diff --git a/services/CMakeLists.txt b/services/CMakeLists.txt index d584fae..fbf54e5 100644 --- a/services/CMakeLists.txt +++ b/services/CMakeLists.txt @@ -1,10 +1,8 @@ -if(SYSTEMD_FOUND) - configure_file(ddm.service.in ddm.service) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ddm.service" DESTINATION "${SYSTEMD_SYSTEM_UNIT_DIR}") +configure_file(ddm.service.in ddm.service) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ddm.service" DESTINATION "${SYSTEMD_SYSTEM_UNIT_DIR}") - configure_file(ddm-sysuser.conf.in ddm-sysuser.conf) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ddm-sysuser.conf" DESTINATION "${SYSTEMD_SYSUSERS_DIR}" RENAME dde.conf) -endif() +configure_file(ddm-sysuser.conf.in ddm-sysuser.conf) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ddm-sysuser.conf" DESTINATION "${SYSTEMD_SYSUSERS_DIR}" RENAME dde.conf) # systemd-tmpfiles can be used standalone without other systemd parts if(DEFINED SYSTEMD_TMPFILES_DIR) @@ -12,24 +10,8 @@ if(DEFINED SYSTEMD_TMPFILES_DIR) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ddm-tmpfiles.conf" DESTINATION "${SYSTEMD_TMPFILES_DIR}" RENAME ddm.conf) endif() -if(USE_ELOGIND) - set(LOGIND_PAM_MODULE "pam_elogind.so") -else() - set(LOGIND_PAM_MODULE "pam_systemd.so") -endif() -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ddm-greeter.pam.in" "${CMAKE_CURRENT_BINARY_DIR}/ddm-greeter.pam") - if(EXISTS "/etc/debian_version") - install(FILES debian.ddm-autologin.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm-autologin) - install(FILES debian.ddm-greeter.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm-greeter) install(FILES debian.ddm.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm) else() - if(HAVE_PAM_FAILLOCK) - install(FILES ddm-autologin.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm-autologin) - else() - install(FILES ddm-autologin-tally2.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm-autologin) - endif() - install(FILES ddm.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ddm-greeter.pam" DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME ddm-greeter) endif() diff --git a/services/ddm-autologin-tally2.pam b/services/ddm-autologin-tally2.pam deleted file mode 100644 index 99729bc..0000000 --- a/services/ddm-autologin-tally2.pam +++ /dev/null @@ -1,13 +0,0 @@ -#%PAM-1.0 -auth required pam_env.so -auth required pam_tally2.so file=/var/log/tallylog onerr=succeed -auth required pam_shells.so -auth required pam_nologin.so -auth required pam_permit.so --auth optional pam_gnome_keyring.so --auth optional pam_kwallet5.so -account include system-local-login -password include system-local-login -session include system-local-login --session optional pam_gnome_keyring.so auto_start --session optional pam_kwallet5.so auto_start diff --git a/services/ddm-autologin.pam b/services/ddm-autologin.pam deleted file mode 100644 index b42991e..0000000 --- a/services/ddm-autologin.pam +++ /dev/null @@ -1,13 +0,0 @@ -#%PAM-1.0 -auth required pam_env.so -auth required pam_faillock.so preauth -auth required pam_shells.so -auth required pam_nologin.so -auth required pam_permit.so --auth optional pam_gnome_keyring.so --auth optional pam_kwallet5.so -account include system-local-login -password include system-local-login -session include system-local-login --session optional pam_gnome_keyring.so auto_start --session optional pam_kwallet5.so auto_start diff --git a/services/ddm-greeter.pam.in b/services/ddm-greeter.pam.in deleted file mode 100644 index d41792d..0000000 --- a/services/ddm-greeter.pam.in +++ /dev/null @@ -1,17 +0,0 @@ -#%PAM-1.0 - -# Load environment from /etc/environment and ~/.pam_environment -auth required pam_env.so - -# Always let the greeter start without authentication -auth required pam_permit.so - -# No action required for account management -account required pam_permit.so - -# Can't change password -password required pam_deny.so - -# Setup session -session required pam_unix.so -session optional @LOGIND_PAM_MODULE@ diff --git a/services/ddm.service.in b/services/ddm.service.in index 6231442..06e4c8c 100644 --- a/services/ddm.service.in +++ b/services/ddm.service.in @@ -14,5 +14,14 @@ Before=seatd.service ExecStart=@CMAKE_INSTALL_FULL_BINDIR@/ddm Restart=always +CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_KILL CAP_SETGID CAP_SETUID CAP_SYS_ADMIN CAP_SYS_BOOT CAP_SYS_CHROOT CAP_SYS_TTY_CONFIG +OOMScoreAdjust=-300 +Nice=-15 +PrivateIPC=true +ProtectClock=true +ProtectKernelTunables=true +ProtectKernelModules=true +RestrictSUIDSGID=true + [Install] Alias=display-manager.service diff --git a/services/debian.ddm-autologin.pam b/services/debian.ddm-autologin.pam deleted file mode 100644 index d595682..0000000 --- a/services/debian.ddm-autologin.pam +++ /dev/null @@ -1,32 +0,0 @@ -#%PAM-1.0 - -# Block login if they are globally disabled -auth requisite pam_nologin.so -auth required pam_permit.so - -@include common-account - -# SELinux needs to be the first session rule. This ensures that any -# lingering context has been cleared. Without this it is possible that a -# module could execute code in the wrong domain. -session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close -# Create a new session keyring. -session optional pam_keyinit.so force revoke -session required pam_limits.so -session required pam_loginuid.so -@include common-session -# SELinux needs to intervene at login time to ensure that the process starts -# in the proper default security context. Only sessions which are intended -# to run in the user's context should be run after this. -session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open - -@include common-password - -# From the pam_env man page -# Since setting of PAM environment variables can have side effects to other modules, this module should be the last one on the stack. - -# Load environment from /etc/environment -session required pam_env.so - -# Load environment from /etc/default/locale -session required pam_env.so envfile=/etc/default/locale diff --git a/services/debian.ddm-greeter.pam b/services/debian.ddm-greeter.pam deleted file mode 100644 index 78aed41..0000000 --- a/services/debian.ddm-greeter.pam +++ /dev/null @@ -1,31 +0,0 @@ -#%PAM-1.0 - -auth required pam_permit.so - -@include common-account - -# SELinux needs to be the first session rule. This ensures that any -# lingering context has been cleared. Without this it is possible that a -# module could execute code in the wrong domain. -session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close -# Create a new session keyring. -session optional pam_keyinit.so force revoke -session required pam_limits.so -session required pam_loginuid.so -@include common-session -# SELinux needs to intervene at login time to ensure that the process starts -# in the proper default security context. Only sessions which are intended -# to run in the user's context should be run after this. -session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open - -# Can't change password -password required pam_deny.so - -# From the pam_env man page -# Since setting of PAM environment variables can have side effects to other modules, this module should be the last one on the stack. - -# Load environment from /etc/environment -session required pam_env.so - -# Load environment from /etc/default/locale -session required pam_env.so envfile=/etc/default/locale diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 75519d0..7e01138 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -4,12 +4,9 @@ set(PUBLIC_HEADERS ${CMAKE_SOURCE_DIR}/src/common/Configuration.h ${CMAKE_SOURCE_DIR}/src/common/MessageHandler.h ${CMAKE_SOURCE_DIR}/src/common/Messages.h - ${CMAKE_SOURCE_DIR}/src/common/SafeDataStream.h ${CMAKE_SOURCE_DIR}/src/common/Session.h ${CMAKE_SOURCE_DIR}/src/common/SignalHandler.h ${CMAKE_SOURCE_DIR}/src/common/SocketWriter.h - ${CMAKE_SOURCE_DIR}/src/common/ThemeConfig.h - ${CMAKE_SOURCE_DIR}/src/common/ThemeMetadata.h ${CMAKE_SOURCE_DIR}/src/common/VirtualTerminal.h ${CMAKE_SOURCE_DIR}/src/common/XAuth.h ${CMAKE_BINARY_DIR}/src/common/Constants.h @@ -19,12 +16,9 @@ set(PUBLIC_HEADERS set(SRCS ${CMAKE_SOURCE_DIR}/src/common/ConfigReader.cpp ${CMAKE_SOURCE_DIR}/src/common/Configuration.cpp - ${CMAKE_SOURCE_DIR}/src/common/SafeDataStream.cpp ${CMAKE_SOURCE_DIR}/src/common/Session.cpp ${CMAKE_SOURCE_DIR}/src/common/SignalHandler.cpp ${CMAKE_SOURCE_DIR}/src/common/SocketWriter.cpp - ${CMAKE_SOURCE_DIR}/src/common/ThemeConfig.cpp - ${CMAKE_SOURCE_DIR}/src/common/ThemeMetadata.cpp ${CMAKE_SOURCE_DIR}/src/common/VirtualTerminal.cpp ${CMAKE_SOURCE_DIR}/src/common/XAuth.cpp ${CMAKE_SOURCE_DIR}/src/common/LogindDBusTypes.cpp diff --git a/src/common/Configuration.h b/src/common/Configuration.h index 011f1a3..b258980 100644 --- a/src/common/Configuration.h +++ b/src/common/Configuration.h @@ -34,84 +34,44 @@ namespace DDM { // Name File Sections and/or Entries (but anything else too, it's a class) - Entries in a Config are assumed to be in the General section Config(MainConfig, QStringLiteral(CONFIG_FILE), QStringLiteral(CONFIG_DIR), QStringLiteral(SYSTEM_CONFIG_DIR), - enum NumState { NUM_NONE, NUM_SET_ON, NUM_SET_OFF }; // Name Type Default value Description - // TODO: Change default to x11-user in a future release - Entry(DisplayServer, QString, _S("single"), _S("Which display server should be used.\n" - "Valid values are: x11, x11-user, wayland. Wayland support is experimental")); Entry(HaltCommand, QString, _S(HALT_COMMAND), _S("Halt command")); Entry(RebootCommand, QString, _S(REBOOT_COMMAND), _S("Reboot command")); - Entry(Numlock, NumState, NUM_NONE, _S("Initial NumLock state. Can be on, off or none.\n" - "If property is set to none, numlock won't be changed\n" - "NOTE: Currently ignored if autologin is enabled.")); - Entry(InputMethod, QString, QStringLiteral("qtvirtualkeyboard"), _S("Input method module")); Entry(Namespaces, QStringList, QStringList(), _S("Comma-separated list of Linux namespaces for user session to enter")); - Entry(GreeterEnvironment, QStringList, QStringList(), _S("Comma-separated list of environment variables to be set")); // Name Entries (but it's a regular class again) Section(Theme, - Entry(ThemeDir, QString, _S(DATA_INSTALL_DIR "/themes"), _S("Theme directory path")); - Entry(Current, QString, _S(""), _S("Current theme name")); - Entry(FacesDir, QString, _S(DATA_INSTALL_DIR "/faces"), _S("Global directory for user avatars\n" - "The files should be named .face.icon")); Entry(CursorTheme, QString, QString(), _S("Cursor theme used in the greeter")); Entry(CursorSize, QString, QString(), _S("Cursor size used in the greeter")); - Entry(Font, QString, QString(), _S("Font used in the greeter")); - Entry(EnableAvatars, bool, true, _S("Enable display of custom user avatars")); - Entry(DisableAvatarsThreshold,int, 7, _S("Number of users to use as threshold\n" - "above which avatars are disabled\n" - "unless explicitly enabled with EnableAvatars")); ); // TODO: Not absolutely sure if everything belongs here. Xsessions, VT and probably some more seem universal Section(X11, Entry(ServerPath, QString, _S("/usr/bin/X"), _S("Path to X server binary")); Entry(ServerArguments, QString, _S("-nolisten tcp"), _S("Arguments passed to the X server invocation")); - Entry(XephyrPath, QString, _S("/usr/bin/Xephyr"), _S("Path to Xephyr binary")); Entry(SessionDir, QStringList, {_S("/usr/local/share/xsessions"), _S("/usr/share/xsessions")}, _S("Comma-separated list of directories containing available X sessions")); Entry(SessionCommand, QString, _S(SESSION_COMMAND), _S("Path to a script to execute when starting the desktop session")); Entry(SessionLogFile, QString, _S(".local/share/ddm/xorg-session.log"), _S("Path to the user session log file")); Entry(DisplayCommand, QString, _S(DATA_INSTALL_DIR "/scripts/Xsetup"), _S("Path to a script to execute when starting the display server")); Entry(DisplayStopCommand, QString, _S(DATA_INSTALL_DIR "/scripts/Xstop"), _S("Path to a script to execute when stopping the display server")); - Entry(EnableHiDPI, bool, true, _S("Enable Qt's automatic high-DPI scaling")); ); Section(Wayland, - Entry(CompositorCommand, QString, _S("weston --shell=fullscreen-shell.so"), _S("Path of the Wayland compositor to execute when starting the greeter")); Entry(SessionDir, QStringList, {_S("/usr/local/share/wayland-sessions"), _S("/usr/share/wayland-sessions")}, _S("Comma-separated list of directories containing available Wayland sessions")); Entry(SessionCommand, QString, _S(WAYLAND_SESSION_COMMAND), _S("Path to a script to execute when starting the desktop session")); Entry(SessionLogFile, QString, _S(".local/share/ddm/wayland-session.log"),_S("Path to the user session log file")); - Entry(EnableHiDPI, bool, true, _S("Enable Qt's automatic high-DPI scaling")); ); Section(Single, - Entry(CompositorCommand, QString, _S("treeland"), _S("Path of the Wayland compositor to execute when starting the greeter")); - Entry(SessionDir, QStringList, {_S("/usr/local/share/wayland-sessions"), - _S("/usr/share/wayland-sessions")}, _S("Comma-separated list of directories containing available Wayland sessions")); Entry(SessionCommand, QString, _S(WAYLAND_SESSION_COMMAND), _S("Path to a script to execute when starting the desktop session")); - Entry(SessionLogFile, QString, _S(".local/share/ddm/wayland-session.log"),_S("Path to the user session log file")); - Entry(EnableHiDPI, bool, true, _S("Enable Qt's automatic high-DPI scaling")); ); Section(Users, Entry(DefaultPath, QString, _S("/usr/local/bin:/usr/bin:/bin"), _S("Default $PATH for logged in users")); - Entry(MinimumUid, int, UID_MIN, _S("Minimum user id for displayed users")); - Entry(MaximumUid, int, UID_MAX, _S("Maximum user id for displayed users")); - Entry(HideUsers, QStringList, QStringList(), _S("Comma-separated list of users that should not be listed")); - Entry(HideShells, QStringList, QStringList(), _S("Comma-separated list of shells.\n" - "Users with these shells as their default won't be listed")); Entry(RememberLastUser, bool, true, _S("Remember the last successfully logged in user")); Entry(RememberLastSession, bool, true, _S("Remember the session of the last successfully logged in user")); - - Entry(ReuseSession, bool, true, _S("When logging in as the same user twice, restore the original session, rather than create a new one")); - ); - - Section(Autologin, - Entry(User, QString, QString(), _S("Username for autologin session")); - Entry(Session, QString, QString(), _S("Name of session file for autologin session (if empty try last logged in)")); - Entry(Relogin, bool, false, _S("Whether ddm should automatically log back into sessions when they exit")); ); ); @@ -126,27 +86,6 @@ namespace DDM { extern MainConfig mainConfig; extern StateConfig stateConfig; - - inline QTextStream& operator>>(QTextStream &str, MainConfig::NumState &state) { - QString text = str.readLine().trimmed(); - if (text.compare(QLatin1String("on"), Qt::CaseInsensitive) == 0) - state = MainConfig::NUM_SET_ON; - else if (text.compare(QLatin1String("off"), Qt::CaseInsensitive) == 0) - state = MainConfig::NUM_SET_OFF; - else - state = MainConfig::NUM_NONE; - return str; - } - - inline QTextStream& operator<<(QTextStream &str, const MainConfig::NumState &state) { - if (state == MainConfig::NUM_SET_ON) - str << "on"; - else if (state == MainConfig::NUM_SET_OFF) - str << "off"; - else - str << "none"; - return str; - } } #endif // DDM_CONFIGURATION_H diff --git a/src/common/SafeDataStream.cpp b/src/common/SafeDataStream.cpp deleted file mode 100644 index ce132f7..0000000 --- a/src/common/SafeDataStream.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * QDataStream implementation for safe socket operation - * Copyright (C) 2014 Martin Bříza - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "SafeDataStream.h" - -#include -#include - -namespace DDM { - SafeDataStream::SafeDataStream(QIODevice* device) - : QDataStream(&m_data, QIODevice::ReadWrite) - , m_device(device) { } - - void SafeDataStream::send() { - qint64 length = m_data.length(); - qint64 writtenTotal = 0; - if (!m_device->isOpen()) { - qCritical() << " Auth: SafeDataStream: Could not write any data"; - return; - } - m_device->write((const char*) &length, sizeof(length)); - while (writtenTotal != length) { - qint64 written = m_device->write(m_data.mid(writtenTotal)); - if (written < 0 || !m_device->isOpen()) { - qCritical() << " Auth: SafeDataStream: Could not write all stored data"; - return; - } - writtenTotal += written; - m_device->waitForBytesWritten(-1); - } - - reset(); - } - - void SafeDataStream::receive() { - qint64 length = -1; - - if (!m_device->isOpen()) { - qCritical() << " Auth: SafeDataStream: Could not read from the device"; - return; - } - if (!m_device->bytesAvailable()) - m_device->waitForReadyRead(-1); - m_device->read((char*) &length, sizeof(length)); - - if (length < 0) - return; - reset(); - - while (m_data.length() < length) { - if (!m_device->isOpen()) { - qCritical() << " Auth: SafeDataStream: Could not read from the device"; - return; - } - if (!m_device->bytesAvailable()) - m_device->waitForReadyRead(-1); - m_data.append(m_device->read(length - m_data.length())); - } - } - - void SafeDataStream::reset() { - m_data.clear(); - device()->reset(); - resetStatus(); - } -} diff --git a/src/common/SafeDataStream.h b/src/common/SafeDataStream.h deleted file mode 100644 index 5249b3b..0000000 --- a/src/common/SafeDataStream.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * QDataStream implementation for safe socket operation - * Copyright (C) 2014 Martin Bříza - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef SAFEDATASTREAM_H -#define SAFEDATASTREAM_H - -#include -#include - -namespace DDM { - class SafeDataStream : public QDataStream { - public: - SafeDataStream(QIODevice* device); - void send(); - void receive(); - void reset(); - - private: - QByteArray m_data { }; - QIODevice *m_device { nullptr }; - }; -} - -#endif // SAFEDATASTREAM_H diff --git a/src/common/ThemeConfig.cpp b/src/common/ThemeConfig.cpp deleted file mode 100644 index 3be2647..0000000 --- a/src/common/ThemeConfig.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2023 Fabian Vogt -* Copyright (c) 2016 Pier Luigi Fiorini -* Copyright (c) 2014 David Edmundson -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "ThemeConfig.h" - -#include -#include -#include - -namespace DDM { - ThemeConfig::ThemeConfig(const QString &path, QObject *parent) - : QQmlPropertyMap(this, parent) { - setTo(path); - } - - void ThemeConfig::setTo(const QString &path) { - for(const QString &key : keys()) { - clear(key); - } - - if (path.isNull()) { - qDebug() << "Loaded empty theme configuration"; - return; - } - - qDebug() << "Loading theme configuration from" << path; - - QSettings settings(path, QSettings::IniFormat); - QSettings userSettings(path + QStringLiteral(".user"), QSettings::IniFormat); - - // read default keys - for (const QString &key: settings.allKeys()) { - insert(key, settings.value(key)); - } - // read user set themes overwriting defaults if they exist - for (const QString &key: userSettings.allKeys()) { - if (!userSettings.value(key).toString().isEmpty()) { - insert(key, userSettings.value(key)); - } - } - - //if the main config contains a background, save this to a new config value - //to themes can use it if the user set config background cannot be loaded - if (settings.contains(QStringLiteral("background"))) { - insert(QStringLiteral("defaultBackground"), settings.value(QStringLiteral("background"))); - } - } - - QVariant ThemeConfig::value(const QString &key, const QVariant &def) { - if (!contains(key)) { - return def; - } - - return value(key); - } - - bool ThemeConfig::boolValue(const QString &key) { - return value(key).toBool(); - } - - int ThemeConfig::intValue(const QString &key) { - bool ok; - auto ret = value(key).toInt(&ok); - if (!ok) { - qWarning() << "Could not convert" << key << "(value" << value(key) << ") to int"; - } - return ret; - } - - qreal ThemeConfig::realValue(const QString &key) { - bool ok; - auto ret = value(key).toReal(&ok); - if (!ok) { - qWarning() << "Could not convert" << key << "(value" << value(key) << ") to real"; - } - return ret; - } - - QString ThemeConfig::stringValue(const QString &key) { - return value(key).toString(); - } -} diff --git a/src/common/ThemeConfig.h b/src/common/ThemeConfig.h deleted file mode 100644 index fa10b54..0000000 --- a/src/common/ThemeConfig.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016 Pier Luigi Fiorini -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_THEMECONFIG_H -#define DDM_THEMECONFIG_H - -#include - -namespace DDM { - class ThemeConfig : public QQmlPropertyMap { - Q_OBJECT - public: - explicit ThemeConfig(const QString &path, QObject *parent = nullptr); - - void setTo(const QString &path); - - // Also provide QVariantMap's value(key, default) method - using QQmlPropertyMap::value; - QVariant value(const QString &key, const QVariant &def); - - // QSettings::IniFormat returns string types for basic - // types. Let the theme request specific conversions. - Q_INVOKABLE bool boolValue(const QString &key); - Q_INVOKABLE int intValue(const QString &key); - Q_INVOKABLE qreal realValue(const QString &key); - Q_INVOKABLE QString stringValue(const QString &key); - }; -} - -#endif // DDM_THEMECONFIG_H diff --git a/src/common/ThemeMetadata.cpp b/src/common/ThemeMetadata.cpp deleted file mode 100644 index 38d4b9b..0000000 --- a/src/common/ThemeMetadata.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016 Pier Luigi Fiorini -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "ThemeMetadata.h" - -#include - -namespace DDM { - class ThemeMetadataPrivate { - public: - QString mainScript { QStringLiteral("Main.qml") }; - QString configFile; - QString translationsDirectory { QStringLiteral(".") }; - }; - - ThemeMetadata::ThemeMetadata(const QString &path, QObject *parent) : QObject(parent), d(new ThemeMetadataPrivate()) { - setTo(path); - } - - ThemeMetadata::~ThemeMetadata() { - delete d; - } - - const QString &ThemeMetadata::mainScript() const { - return d->mainScript; - } - - const QString &ThemeMetadata::configFile() const { - return d->configFile; - } - - const QString &ThemeMetadata::translationsDirectory() const { - return d->translationsDirectory; - } - - void ThemeMetadata::setTo(const QString &path) { - QSettings settings(path, QSettings::IniFormat); - // read values - d->mainScript = settings.value(QStringLiteral("SddmGreeterTheme/MainScript"), QStringLiteral("Main.qml")).toString(); - d->configFile = settings.value(QStringLiteral("SddmGreeterTheme/ConfigFile"), QStringLiteral("theme.conf")).toString(); - d->translationsDirectory = settings.value(QStringLiteral("SddmGreeterTheme/TranslationsDirectory"), QStringLiteral(".")).toString(); - } -} diff --git a/src/common/ThemeMetadata.h b/src/common/ThemeMetadata.h deleted file mode 100644 index 9a72962..0000000 --- a/src/common/ThemeMetadata.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2016 Pier Luigi Fiorini -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_THEMEMETADATA_H -#define DDM_THEMEMETADATA_H - -#include - -namespace DDM { - class ThemeMetadataPrivate; - - class ThemeMetadata : public QObject { - Q_OBJECT - Q_DISABLE_COPY(ThemeMetadata) - public: - explicit ThemeMetadata(const QString &path, QObject *parent = 0); - ~ThemeMetadata(); - - const QString &mainScript() const; - const QString &configFile() const; - const QString &translationsDirectory() const; - - void setTo(const QString &path); - - private: - ThemeMetadataPrivate *d { nullptr }; - }; -} - -#endif // DDM_THEMEMETADATA_H diff --git a/src/daemon/Auth.cpp b/src/daemon/Auth.cpp index 673728f..7276eb5 100644 --- a/src/daemon/Auth.cpp +++ b/src/daemon/Auth.cpp @@ -29,88 +29,21 @@ #include namespace DDM { - int Auth::lastId = 0; - Auth::Auth(QObject *parent) - : QObject(parent) - , id(++lastId) - , m_pam(new Pam(this)) - , m_session(new UserSession(this)) { - connect(m_session, - QOverload::of(&QProcess::finished), - this, - &Auth::userProcessFinished); - } - - Auth::~Auth() { - stop(); - } - - bool Auth::authenticate(const QByteArray &secret) { - m_pam->user = user; - if (!m_pam->start()) { - utmpLogin(std::to_string(tty).c_str(), display, user, 0, false); - return false; - } - if (!skipAuth && !m_pam->authenticate(secret)) { - utmpLogin(std::to_string(tty).c_str(), display, user, 0, false); - return false; - } - active = true; - return true; - } - - int Auth::openSession(const QProcessEnvironment &env) { - Q_ASSERT(active); - auto ret = m_pam->openSession(env); - if (!ret.has_value()) - return -1; - m_env = *ret; - xdgSessionId = m_env.value(QStringLiteral("XDG_SESSION_ID")).toInt(); - return xdgSessionId; - } - - void Auth::startUserProcess(const QString &command, Display::DisplayServerType type, const QByteArray &cookie) { - Q_ASSERT(!m_env.isEmpty()); - QProcessEnvironment env = m_env; - struct passwd *pw = getpwnam(qPrintable(user)); - if (pw) { - env.insert(QStringLiteral("HOME"), QString::fromLocal8Bit(pw->pw_dir)); - env.insert(QStringLiteral("PWD"), QString::fromLocal8Bit(pw->pw_dir)); - env.insert(QStringLiteral("SHELL"), QString::fromLocal8Bit(pw->pw_shell)); - env.insert(QStringLiteral("USER"), QString::fromLocal8Bit(pw->pw_name)); - env.insert(QStringLiteral("LOGNAME"), QString::fromLocal8Bit(pw->pw_name)); - } - m_session->setProcessEnvironment(env); - m_session->start(command, type, cookie); - - // write successful login to utmp/wtmp - const QString displayId = env.value(QStringLiteral("DISPLAY")); - const QString vt = env.value(QStringLiteral("XDG_VTNR")); - // cache pid for session end - utmpLogin(vt, displayId, user, m_session->processId(), true); - } - - void Auth::stop() { - if (!active) - return; - active = false; - qint64 pid = m_session->processId(); - if (m_session->state() != QProcess::NotRunning) - m_session->stop(); - if (m_pam->sessionOpened) - m_pam->closeSession(); - - // write logout to utmp/wtmp - if (pid > 0) { - QProcessEnvironment env = m_session->processEnvironment(); - QString vt = env.value(QStringLiteral("XDG_VTNR")); - QString displayId = env.value(QStringLiteral("DISPLAY")); - utmpLogout(vt, displayId, pid); - } - } - - void Auth::utmpLogin(const QString &vt, const QString &displayName, const QString &user, qint64 pid, bool authSuccessful) { + ////////////////////// + // Helper functions // + ////////////////////// + + /** + * Write utmp/wtmp/btmp records when a user logs in + * + * @param vt Virtual terminal (tty7, tty8,...) + * @param displayName Display (:0, :1,...) + * @param user User logging in + * @param pid User process ID (e.g. PID of startkde) + * @param authSuccessful Was authentication successful + */ + static void utmpLogin(const QString &vt, const QString &displayName, const QString &user, qint64 pid, bool authSuccessful) { struct utmpx entry { }; struct timeval tv; @@ -155,7 +88,14 @@ namespace DDM { } } - void Auth::utmpLogout(const QString &vt, const QString &displayName, qint64 pid) { + /** + * Write utmp/wtmp records when a user logs out + * + * @param vt Virtual terminal (tty7, tty8,...) + * @param displayName Display (:0, :1,...) + * @param pid User process ID (e.g. PID of startkde) + */ + static void utmpLogout(const QString &vt, const QString &displayName, qint64 pid) { struct utmpx entry { }; struct timeval tv; @@ -189,4 +129,87 @@ namespace DDM { // append to wtmp updwtmpx("/var/log/wtmp", &entry); } + + ///////////////////////// + // Auth implementation // + ///////////////////////// + + Auth::Auth(QObject *parent, QString user) + : QObject(parent) + , user(user) + , m_pam(new Pam(this)) + , m_session(new UserSession(this)) { + connect(m_session, + QOverload::of(&QProcess::finished), + this, + &Auth::userProcessFinished); + } + + Auth::~Auth() { + stop(); + } + + bool Auth::authenticate(const QByteArray &secret) { + m_pam->user = user; + if (!m_pam->start()) { + utmpLogin(std::to_string(tty).c_str(), display, user, 0, false); + return false; + } + if (!m_pam->authenticate(secret)) { + utmpLogin(std::to_string(tty).c_str(), display, user, 0, false); + return false; + } + active = true; + return true; + } + + int Auth::openSession(const QProcessEnvironment &env) { + Q_ASSERT(active); + auto ret = m_pam->openSession(env); + if (!ret.has_value()) + return -1; + m_env = *ret; + xdgSessionId = m_env.value(QStringLiteral("XDG_SESSION_ID")).toInt(); + return xdgSessionId; + } + + void Auth::startUserProcess(const QString &command, const QByteArray &cookie) { + Q_ASSERT(!m_env.isEmpty()); + QProcessEnvironment env = m_env; + struct passwd *pw = getpwnam(qPrintable(user)); + if (pw) { + env.insert(QStringLiteral("HOME"), QString::fromLocal8Bit(pw->pw_dir)); + env.insert(QStringLiteral("PWD"), QString::fromLocal8Bit(pw->pw_dir)); + env.insert(QStringLiteral("SHELL"), QString::fromLocal8Bit(pw->pw_shell)); + env.insert(QStringLiteral("USER"), QString::fromLocal8Bit(pw->pw_name)); + env.insert(QStringLiteral("LOGNAME"), QString::fromLocal8Bit(pw->pw_name)); + } + m_session->setProcessEnvironment(env); + m_session->start(command, type, cookie); + + // write successful login to utmp/wtmp + const QString displayId = env.value(QStringLiteral("DISPLAY")); + const QString vt = env.value(QStringLiteral("XDG_VTNR")); + // cache pid for session end + utmpLogin(vt, displayId, user, m_session->processId(), true); + } + + void Auth::stop() { + if (!active) + return; + active = false; + qint64 pid = m_session->processId(); + if (m_session->state() != QProcess::NotRunning) + m_session->stop(); + if (m_pam->sessionOpened) + m_pam->closeSession(); + + // write logout to utmp/wtmp + if (pid > 0) { + QProcessEnvironment env = m_session->processEnvironment(); + QString vt = env.value(QStringLiteral("XDG_VTNR")); + QString displayId = env.value(QStringLiteral("DISPLAY")); + utmpLogout(vt, displayId, pid); + } + } } // namespace DDM diff --git a/src/daemon/Auth.h b/src/daemon/Auth.h index 844a8af..e32393a 100644 --- a/src/daemon/Auth.h +++ b/src/daemon/Auth.h @@ -30,71 +30,87 @@ namespace DDM { class Pam; class UserSession; + /** Authentication handler, manage login and session */ class Auth : public QObject { Q_OBJECT public: - Auth(QObject *parent); + Auth(QObject *parent, QString user); ~Auth(); + /** Indicates whether the Auth is active (PAM module started) */ bool active{ false }; + + /** Username. Must be set before authenticate() */ QString user{}; - QByteArray cookie{}; - bool singleMode{ false }; - bool skipAuth{ false }; - - int id{ 0 }; - static int lastId; + + /** Display sever type of the session. Must be set before startUserProcess() */ + Display::DisplayServerType type{}; + + /** The "Session ID" (defined and used by DisplayManager) */ QString sessionId{}; + + /** X Display identifier (e.g. :0), if presents */ QString display{}; + + /** Virtual terminal number (e.g. 7 for tty7) */ int tty{ 0 }; + + /** Logind session ID (the XDG_SESSION_ID env var) */ int xdgSessionId{ 0 }; + public Q_SLOTS: /** - * Sets up the environment and starts the authentication - */ + * Sets up the environment and starts the authentication. + * + * @param secret Password or other secret data acceptable by PAM + * @return true on success, false on failure + */ bool authenticate(const QByteArray &secret); + /** + * Opens user session via PAM and returns the XDG_SESSION_ID. + * Must be called after authenticate(). + * + * @param env Environment variables to set for the session + * @return XDG_SESSION_ID on success, -1 on failure + */ int openSession(const QProcessEnvironment &env); - void startUserProcess(const QString &command, - Display::DisplayServerType type, - const QByteArray &cookie = QByteArray()); + /** + * Starts process inside opened session. + * Must be called after openSession(). + * Only 1 process can be started per Auth instance, + * userProcessFinished() is emitted when the process ends. + * Implemented in UserSession. + * + * @param command Command to exec + * @param cookie XAuth cookie (must be set for X11) + */ + void startUserProcess(const QString &command, const QByteArray &cookie = QByteArray()); /** - * Indicates that we do not need the process anymore. + * Stop PAM, close opened session and end up user process. + * This will be automatically called in the destructor. */ void stop(); Q_SIGNALS: /** - * Emitted when the session ends. + * Emitted when the user process ends. * - * @param success true if every underlying task went fine + * @param status Exit code of the user process */ void userProcessFinished(int status); private: - Pam *m_pam { nullptr }; - UserSession *m_session{ nullptr }; - QProcessEnvironment m_env{}; + /** The PAM module */ + Pam *m_pam{ nullptr }; - /** - * Write utmp/wtmp/btmp records when a user logs in - * @param vt Virtual terminal (tty7, tty8,...) - * @param displayName Display (:0, :1,...) - * @param user User logging in - * @param pid User process ID (e.g. PID of startkde) - * @param authSuccessful Was authentication successful - */ - void utmpLogin(const QString &vt, const QString &displayName, const QString &user, qint64 pid, bool authSuccessful); + /** The user process */ + UserSession *m_session{ nullptr }; - /** - * Write utmp/wtmp records when a user logs out - * @param vt Virtual terminal (tty7, tty8,...) - * @param displayName Display (:0, :1,...) - * @param pid User process ID (e.g. PID of startkde) - */ - void utmpLogout(const QString &vt, const QString &displayName, qint64 pid); + /** Cached environment inside the opened logind session, for the user process */ + QProcessEnvironment m_env{}; }; } diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index 885c12f..bff56f0 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -1,6 +1,5 @@ include_directories( ${LIBXAU_INCLUDE_DIRS} - "${LIBXCB_INCLUDE_DIR}" ) pkg_search_module(WAYLAND REQUIRED IMPORTED_TARGET wayland-client) @@ -31,7 +30,6 @@ set(DAEMON_SOURCES DisplayManager.cpp Pam.cpp PowerManager.cpp - Seat.cpp SeatManager.cpp SocketServer.cpp TreelandConnector.cpp @@ -74,7 +72,6 @@ target_link_libraries(ddm Qt${QT_MAJOR_VERSION}::DBus Qt${QT_MAJOR_VERSION}::Network Qt${QT_MAJOR_VERSION}::Qml - ${LIBXCB_LIBRARIES} ${PAM_LIBRARIES} PkgConfig::WAYLAND ) diff --git a/src/daemon/DaemonApp.cpp b/src/daemon/DaemonApp.cpp index 161fef9..2edacf7 100644 --- a/src/daemon/DaemonApp.cpp +++ b/src/daemon/DaemonApp.cpp @@ -49,9 +49,6 @@ namespace DDM { // log message qDebug() << "Initializing..."; - // set testing parameter - m_testing = (arguments().indexOf(QStringLiteral("--test-mode")) != -1); - bool consoleKitServiceActivatable = false; QDBusReply activatableNamesReply = QDBusConnection::systemBus().interface()->activatableServiceNames(); if (activatableNamesReply.isValid()) { @@ -95,11 +92,6 @@ namespace DDM { m_seatManager->initialize(); } - bool DaemonApp::testing() const { - return m_testing; - } - - QString DaemonApp::hostName() const { return QHostInfo::localHostName(); } @@ -143,7 +135,6 @@ int main(int argc, char **argv) { if (arguments.contains(QStringLiteral("--help")) || arguments.contains(QStringLiteral("-h"))) { std::cout << "Usage: ddm [options]\n" << "Options: \n" - << " --test-mode Start daemon in test mode" << std::endl << " --example-config Print the complete current configuration to stdout" << std::endl; return EXIT_FAILURE; diff --git a/src/daemon/DaemonApp.h b/src/daemon/DaemonApp.h index c5620f7..5badd5e 100644 --- a/src/daemon/DaemonApp.h +++ b/src/daemon/DaemonApp.h @@ -40,10 +40,6 @@ namespace DDM { static DaemonApp *instance() { return self; } - // TODO: move these two away - bool testing() const; - bool first { true }; - QString hostName() const; DisplayManager *displayManager() const; PowerManager *powerManager() const; @@ -61,7 +57,6 @@ namespace DDM { int m_lastSessionId { 0 }; - bool m_testing { false }; DisplayManager *m_displayManager { nullptr }; PowerManager *m_powerManager { nullptr }; SeatManager *m_seatManager { nullptr }; diff --git a/src/daemon/Display.cpp b/src/daemon/Display.cpp index 54d452c..fb81819 100644 --- a/src/daemon/Display.cpp +++ b/src/daemon/Display.cpp @@ -27,10 +27,11 @@ #include "DisplayManager.h" #include "XorgDisplayServer.h" #include "TreelandDisplayServer.h" -#include "Seat.h" +#include "SeatManager.h" #include "SocketServer.h" #include "Messages.h" #include "SocketWriter.h" +#include "TreelandConnector.h" #include #include @@ -88,9 +89,9 @@ namespace DDM { return VirtualTerminal::setUpNewVt(); } - Display::Display(Seat *parent) + Display::Display(SeatManager *parent, QString name) : QObject(parent) - , seat(parent) + , name(name) , m_socketServer(new SocketServer(this)) { // Create display server @@ -101,7 +102,7 @@ namespace DDM { // Record current VT as ddm user session DaemonApp::instance()->displayManager()->AddSession( {}, - seat->name(), + name, "ddm", static_cast(VirtualTerminal::currentVt())); @@ -123,20 +124,20 @@ namespace DDM { } Display::~Display() { - for (auto *item : m_auths) + for (auto *item : std::as_const(auths)) disconnect(item, &Auth::userProcessFinished, this, &Display::userProcessFinished); stop(); } - void Display::switchToUser(const QString &user, int xdgSessionId) { - if (xdgSessionId <= 0) { - qFatal() << "Invalid xdg session id" << xdgSessionId << "for user" << user; + void Display::activateSession(const QString &user, int xdgSessionId) { + if (xdgSessionId <= 0 && user != QStringLiteral("ddm")) { + qCritical() << "Invalid xdg session id" << xdgSessionId << "for user" << user; return; } m_treeland->activateUser(user, xdgSessionId); - if (Logind::isAvailable()) { + if (xdgSessionId > 0 && Logind::isAvailable()) { OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); manager.ActivateSession(QString::number(xdgSessionId)); } @@ -172,9 +173,8 @@ namespace DDM { if (!m_started) return; - for (auto *item : m_auths) { + for (auto *item : std::as_const(auths)) item->stop(); - } // stop socket server m_socketServer->stop(); @@ -193,10 +193,9 @@ namespace DDM { } void Display::connected(QLocalSocket *socket) { - m_socket = socket; - // send logined user (for possible crash recovery) + // send logged in users (for possible crash recovery) SocketWriter writer(socket); - for (Auth *auth : m_auths) { + for (Auth *auth : std::as_const(auths)) { if (auth->active) writer << quint32(DaemonMessages::UserLoggedIn) << auth->user << auth->xdgSessionId; } @@ -205,71 +204,14 @@ namespace DDM { void Display::login(QLocalSocket *socket, const QString &user, const QString &password, const Session &session) { - m_socket = socket; - - //the DDM user has special privileges that skip password checking so that we can load the greeter - //block ever trying to log in as the DDM user - if (user == QLatin1String("dde")) { - emit loginFailed(m_socket, user); - return; - } - - // authenticate - startAuth(user, password, session); - } - - void Display::logout([[maybe_unused]] QLocalSocket *socket, int id) { - OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); - manager.TerminateSession(QString::number(id)); - } - - void Display::unlock(QLocalSocket *socket, - const QString &user, const QString &password) { - m_socket = socket; - - //the DDM user has special privileges that skip password checking so that we can load the greeter - //block ever trying to log in as the DDM user if (user == QLatin1String("dde")) { - emit loginFailed(m_socket, user); + emit loginFailed(socket, user); return; } - // authenticate - startIdentify(user, password); - } - - void Display::startIdentify(const QString &user, const QString &password) { - qDebug() << "start Identify user" << user; - Auth auth(this); - auth.setObjectName("userIdentify"); - - auth.user = user; - if (auth.authenticate(password.toLocal8Bit())) { - DaemonApp::instance()->displayManager()->setLastActivatedUser(user); - if (mainConfig.Users.RememberLastUser.get()) - stateConfig.Last.User.set(user); - else - stateConfig.Last.User.setDefault(); - stateConfig.save(); - - m_treeland->onLoginSucceeded(user); - // TODO: Use exact ID when there're multiple sessions for a user - int xdgSessionId = 0; - for (auto *auth : std::as_const(m_auths)) { - if (auth->user == user && auth->xdgSessionId > 0) { - xdgSessionId = auth->xdgSessionId; - break; - } - } - switchToUser(user, xdgSessionId); - } - } - - void Display::startAuth(const QString &user, const QString &password, const Session &session) { - - // respond to authentication requests + // Get Auth object Auth *auth = nullptr; - for (auto *item : m_auths) { + for (auto *item : std::as_const(auths)) { if (item->user == user) { auth = item; break; @@ -277,7 +219,7 @@ namespace DDM { } if (!auth) - auth = new Auth(this); + auth = new Auth(this, user); if (auth->active) { qWarning() << "Existing authentication ongoing, aborting"; @@ -298,19 +240,23 @@ namespace DDM { return; } + // Run password check auth->user = user; - auth->tty = terminalId; - auth->singleMode = session.isSingleMode(); - if (!auth->authenticate(password.toLocal8Bit())) + if (session.isSingleMode()) + auth->tty = VirtualTerminal::setUpNewVt(); + else + auth->tty = terminalId; + if (!auth->authenticate(password.toLocal8Bit())) { + Q_EMIT loginFailed(socket, user); return; + } // some information qDebug() << "Session" << session.fileName() << "selected, command:" << session.exec() << "for VT" << auth->tty; - DaemonApp::instance()->displayManager()->setLastActivatedUser(user); - // save last user and last session + DaemonApp::instance()->displayManager()->setLastActivatedUser(user); if (mainConfig.Users.RememberLastUser.get()) stateConfig.Last.User.set(auth->user); else @@ -321,12 +267,13 @@ namespace DDM { stateConfig.Last.Session.setDefault(); stateConfig.save(); + // Prepare session environment QProcessEnvironment env; env.insert(session.additionalEnv()); // session id const QString sessionId = QStringLiteral("Session%1").arg(daemonApp->newSessionId()); - daemonApp->displayManager()->AddSession(sessionId, seat->name(), user, auth->tty); + daemonApp->displayManager()->AddSession(sessionId, name, user, auth->tty); daemonApp->displayManager()->setLastSession(sessionId); env.insert(QStringLiteral("XDG_SESSION_PATH"), daemonApp->displayManager()->sessionPath(sessionId)); auth->sessionId = sessionId; @@ -338,23 +285,26 @@ namespace DDM { env.insert(QStringLiteral("XDG_SESSION_CLASS"), QStringLiteral("user")); env.insert(QStringLiteral("XDG_SESSION_TYPE"), session.xdgSessionType()); env.insert(QStringLiteral("XDG_VTNR"), QString::number(auth->tty)); - env.insert(QStringLiteral("XDG_SEAT"), seat->name()); - env.insert(QStringLiteral("XDG_SEAT_PATH"), daemonApp->displayManager()->seatPath(seat->name())); + env.insert(QStringLiteral("XDG_SEAT"), name); + env.insert(QStringLiteral("XDG_SEAT_PATH"), daemonApp->displayManager()->seatPath(name)); env.insert(QStringLiteral("XDG_SESSION_DESKTOP"), session.desktopNames()); - DisplayServerType type; + // Special preparation for each display server type + // + // TODO: Let Treeland drop DRM master when inactive, so that X + // server and other Wayland compositor can co-exist with + // greeter (the Treeland) QByteArray cookie; if (session.isSingleMode()) { - type = Treeland; + auth->type = Treeland; env.insert("DDE_CURRENT_COMPOSITOR", "TreeLand"); - m_treeland->onLoginSucceeded(user); } else if (session.xdgSessionType() == QLatin1String("x11")) { - type = X11; + auth->type = X11; - // stop treeland m_treeland->stop(); - sleep(1); // give some time to treeland to stop before starting Xorg + QThread::msleep(500); // give some time to treeland to stop properly + // Start X server m_x11Server = new XorgDisplayServer(this); connect(m_x11Server, &XorgDisplayServer::stopped, this, &Display::stop); if (!m_x11Server->start(auth->tty)) { @@ -365,25 +315,81 @@ namespace DDM { env.insert(QStringLiteral("DISPLAY"), m_x11Server->display); cookie = m_x11Server->cookie(); } else { - type = Wayland; - // stop treeland + auth->type = Wayland; + m_treeland->stop(); - sleep(1); // give some time to treeland to stop before starting Wayland session + QThread::msleep(500); // give some time to treeland to stop properly } + // Open Logind session int xdgSessionId = auth->openSession(env); if (xdgSessionId <= 0) { auth->stop(); delete auth; return; } - if (type == Treeland) - switchToUser(auth->user, xdgSessionId); + if (auth->type == Treeland) { + Q_EMIT loginSucceeded(socket, user); + // Tell Treeland to enter the session + activateSession(auth->user, xdgSessionId); + } + // Exec the desktop process connect(auth, &Auth::userProcessFinished, this, &Display::userProcessFinished); - auth->startUserProcess(session.exec(), type, cookie); + auth->startUserProcess(session.exec(), cookie); + + // The user process is ongoing, append to active auths + // The auth will be delete later in userProcessFinished() + auths << auth; + } + + void Display::logout([[maybe_unused]] QLocalSocket *socket, int id) { + OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); + manager.TerminateSession(QString::number(id)); + } + + void Display::unlock(QLocalSocket *socket, const QString &user, const QString &password) { + if (user == QLatin1String("dde")) { + emit loginFailed(socket, user); + return; + } + + qDebug() << "Start identify user" << user; - m_auths << auth; + // Only run password check + // + // No user process execution, so the auth can be thrown away + // immediately after use + Auth auth(this, user); + auth.user = user; + if (!auth.authenticate(password.toLocal8Bit())) { + Q_EMIT loginFailed(socket, user); + return; + } + + // Save last user + DaemonApp::instance()->displayManager()->setLastActivatedUser(user); + if (mainConfig.Users.RememberLastUser.get()) + stateConfig.Last.User.set(user); + else + stateConfig.Last.User.setDefault(); + stateConfig.save(); + + // Find the auth that started the session, which contains full informations + for (auto *auth : std::as_const(auths)) { + if (auth->user == user && auth->xdgSessionId > 0) { + if (auth->type == Treeland) { + // TODO: Use exact ID when there're multiple sessions for a user + // TODO: Jump to auth->tty + Q_EMIT loginSucceeded(socket, user); + activateSession(user, auth->xdgSessionId); + } else { + VirtualTerminal::jumpToVt(auth->tty, false); + } + return; + } + } + Q_EMIT loginFailed(socket, user); } void Display::userProcessFinished([[maybe_unused]] int status) { @@ -391,10 +397,9 @@ namespace DDM { daemonApp->displayManager()->RemoveSession(auth->sessionId); - m_auths.removeOne(auth); + auths.removeAll(auth); delete auth; - // TODO: switch to greeter - m_treeland->activateUser("dde", 0); + activateSession("dde", 0); } } diff --git a/src/daemon/Display.h b/src/daemon/Display.h index b052fb2..2fdb5d5 100644 --- a/src/daemon/Display.h +++ b/src/daemon/Display.h @@ -34,9 +34,10 @@ namespace DDM { class Auth; class XorgDisplayServer; class TreelandDisplayServer; - class Seat; + class SeatManager; class SocketServer; + /** Class represents a display (seat) */ class Display : public QObject { Q_OBJECT Q_DISABLE_COPY(Display) @@ -48,18 +49,55 @@ namespace DDM { }; Q_ENUM(DisplayServerType) - explicit Display(Seat *parent); + /** + * Constructor + * + * @param parent The SeatManager + * @param name Seat name + */ + explicit Display(SeatManager *parent, QString name); + ~Display(); - void switchToUser(const QString &user, int xdgSessionId); + /** + * Tell Treeland to activate a certain session. + * + * Called with user = "dde" and xdgSessionId <= 0 + * will send Treeland into lockscreen. + * + * @param user Username + * @param xdgSessionId Logind session ID + */ + void activateSession(const QString &user, int xdgSessionId); + + /** Seat name */ + QString name{}; + + /** VT number of the greeter */ + int terminalId{ 0 }; - Seat *seat{ nullptr }; - int terminalId = 0; + /** List of active authentications */ + QList auths; public slots: + /** + * Start the display. + * This will start Treeland and show greeter. + * + * @return true on success, false on failure + */ bool start(); + + /** + * Stop the display. + * Will be called automatically when destructed. + */ void stop(); + /////////////////////////////////////////////////// + // Slots for socket to communicate with Treeland // + /////////////////////////////////////////////////// + void connected(QLocalSocket *socket); void login(QLocalSocket *socket, const QString &user, const QString &password, @@ -70,22 +108,28 @@ namespace DDM { const QString &user, const QString &password); signals: + /** Emitted when stop() */ void stopped(); + ///////////////////////////////////////////////////// + // Signals for socket to communicate with Treeland // + ///////////////////////////////////////////////////// + void loginFailed(QLocalSocket *socket, const QString &user); void loginSucceeded(QLocalSocket *socket, const QString &user); private: - void startAuth(const QString &user, const QString &password, - const Session &session); - void startIdentify(const QString &user, const QString &password); - + /** Indicates whether the display is started */ bool m_started{ false }; - QVector m_auths; + + /** Treeland display server */ TreelandDisplayServer *m_treeland{ nullptr }; + + /** X11 display server, if started */ XorgDisplayServer *m_x11Server{ nullptr }; + + /** Socket server for communication with Treeland */ SocketServer *m_socketServer { nullptr }; - QPointer m_socket; private slots: void userProcessFinished(int status); diff --git a/src/daemon/DisplayManager.cpp b/src/daemon/DisplayManager.cpp index 2cf3c0a..9032c9f 100644 --- a/src/daemon/DisplayManager.cpp +++ b/src/daemon/DisplayManager.cpp @@ -26,7 +26,6 @@ #include "displaymanageradaptor.h" #include "seatadaptor.h" #include "sessionadaptor.h" -#include "VirtualTerminal.h" const QString DISPLAYMANAGER_SERVICE = QStringLiteral("org.freedesktop.DisplayManager"); const QString DISPLAYMANAGER_PATH = QStringLiteral("/org/freedesktop/DisplayManager"); @@ -40,7 +39,7 @@ namespace DDM { new DDMDisplayManagerAdaptor(this); // register object - QDBusConnection connection = (daemonApp->testing()) ? QDBusConnection::sessionBus() : QDBusConnection::systemBus(); + QDBusConnection connection = QDBusConnection::systemBus(); connection.registerService(DISPLAYMANAGER_SERVICE); connection.registerObject(DISPLAYMANAGER_PATH, this); @@ -193,7 +192,7 @@ namespace DDM { new SeatAdaptor(this); // register object - QDBusConnection connection = (daemonApp->testing()) ? QDBusConnection::sessionBus() : QDBusConnection::systemBus(); + QDBusConnection connection = QDBusConnection::systemBus(); connection.registerService(DISPLAYMANAGER_SERVICE); connection.registerObject(m_path, this); } @@ -232,7 +231,7 @@ namespace DDM { new SessionAdaptor(this); // register object - QDBusConnection connection = (daemonApp->testing()) ? QDBusConnection::sessionBus() : QDBusConnection::systemBus(); + QDBusConnection connection = QDBusConnection::systemBus(); connection.registerService(DISPLAYMANAGER_SERVICE); connection.registerObject(m_path, this); } diff --git a/src/daemon/PowerManager.cpp b/src/daemon/PowerManager.cpp index df96758..0686378 100644 --- a/src/daemon/PowerManager.cpp +++ b/src/daemon/PowerManager.cpp @@ -174,8 +174,7 @@ const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); } void reboot() const { - if (!daemonApp->testing()) - m_interface->call(QStringLiteral("Reboot"), true); + m_interface->call(QStringLiteral("Reboot"), true); } void suspend() const { @@ -228,9 +227,6 @@ const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); } void PowerManager::powerOff() const { - if (daemonApp->testing()) - return; - for (PowerManagerBackend *backend: m_backends) { if (backend->capabilities() & Capability::PowerOff) { backend->powerOff(); @@ -240,9 +236,6 @@ const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); } void PowerManager::reboot() const { - if (daemonApp->testing()) - return; - for (PowerManagerBackend *backend: m_backends) { if (backend->capabilities() & Capability::Reboot) { backend->reboot(); @@ -252,9 +245,6 @@ const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); } void PowerManager::suspend() const { - if (daemonApp->testing()) - return; - for (PowerManagerBackend *backend: m_backends) { if (backend->capabilities() & Capability::Suspend) { backend->suspend(); @@ -264,9 +254,6 @@ const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); } void PowerManager::hibernate() const { - if (daemonApp->testing()) - return; - for (PowerManagerBackend *backend: m_backends) { if (backend->capabilities() & Capability::Hibernate) { backend->hibernate(); @@ -276,9 +263,6 @@ const QString CK2_OBJECT = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); } void PowerManager::hybridSleep() const { - if (daemonApp->testing()) - return; - for (PowerManagerBackend *backend: m_backends) { if (backend->capabilities() & Capability::HybridSleep) { backend->hybridSleep(); diff --git a/src/daemon/Seat.cpp b/src/daemon/Seat.cpp deleted file mode 100644 index ecd86df..0000000 --- a/src/daemon/Seat.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2014 Pier Luigi Fiorini -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "Seat.h" - -#include "Configuration.h" -#include "DaemonApp.h" -#include "Display.h" -#include "XorgDisplayServer.h" -#include "VirtualTerminal.h" - -#include -#include -#include - -#include -#include -#include -#include - -namespace DDM { - Seat::Seat(const QString &name, QObject *parent) : QObject(parent), m_name(name) { - createDisplay(); - } - - const QString &Seat::name() const { - return m_name; - } - - void Seat::createDisplay() { - //reload config if needed - mainConfig.load(); - - if (!m_displays.isEmpty()) { - auto display = m_displays.first(); - display->switchToUser("dde", 0); - return; - } - - // create a new display - qDebug() << "Adding new display..."; - Display *display = new Display(this); - - // restart display on stop - connect(display, &Display::stopped, this, &Seat::displayStopped); - - // add display to the list - m_displays << display; - - // start the display - startDisplay(display); - } - - void Seat::startDisplay(Display *display, int tryNr) { - if (display->start()) - return; - - // It's possible that the system isn't ready yet (driver not loaded, - // device not enumerated, ...). It's not possible to tell when that changes, - // so try a few times with a delay in between. - qWarning() << "Attempt" << tryNr << "starting the Display server on vt" << display->terminalId << "failed"; - - if(tryNr >= 3) { - qCritical() << "Could not start Display server on vt" << display->terminalId; - return; - } - - QTimer::singleShot(2000, display, [this, display, tryNr] { startDisplay(display, tryNr + 1); }); - } - - void Seat::removeDisplay(Display* display) { - qDebug() << "Removing display" << display << "..."; - - - // remove display from list - m_displays.removeAll(display); - - // stop the display - display->blockSignals(true); - display->stop(); - display->blockSignals(false); - - // delete display - display->deleteLater(); - } - - void Seat::displayStopped() { - Display *display = qobject_cast(sender()); - OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus()); - std::optional nextVt; - - // remove display - removeDisplay(display); - - // restart otherwise - if (m_displays.isEmpty()) { - createDisplay(); - } - // If there is still a session running on some display, - // switch to last display in display vector. - // Set vt_auto to true, so let the kernel handle the - // vt switch automatically (VT_AUTO). - else if (!nextVt) { - int disp = m_displays.last()->terminalId; - if (disp != -1) - nextVt = disp; - } - - if (nextVt) { - VirtualTerminal::jumpToVt(*nextVt, true); - } - } -} diff --git a/src/daemon/Seat.h b/src/daemon/Seat.h deleted file mode 100644 index a631b8c..0000000 --- a/src/daemon/Seat.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2013 Abdurrahman AVCI -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#ifndef DDM_SEAT_H -#define DDM_SEAT_H - -#include -#include -#include "Display.h" - -namespace DDM { - class Display; - - class Seat : public QObject { - Q_OBJECT - Q_DISABLE_COPY(Seat) - public: - explicit Seat(const QString &name, QObject *parent = 0); - - const QString &name() const; - void createDisplay(); - - public slots: - void removeDisplay(DDM::Display* display); - - private slots: - void displayStopped(); - - private: - void startDisplay(DDM::Display *display, int tryNr = 1); - - QString m_name; - - QVector m_displays; - }; -} - -#endif // DDM_SEAT_H diff --git a/src/daemon/SeatManager.cpp b/src/daemon/SeatManager.cpp index 62dd054..867e775 100644 --- a/src/daemon/SeatManager.cpp +++ b/src/daemon/SeatManager.cpp @@ -19,15 +19,18 @@ #include "SeatManager.h" +#include "Configuration.h" #include "DaemonApp.h" -#include "Seat.h" +#include "Display.h" #include #include #include #include +#include #include "LogindDBusTypes.h" +#include namespace DDM { @@ -94,7 +97,7 @@ namespace DDM { } void SeatManager::initialize() { - if (DaemonApp::instance()->testing() || !Logind::isAvailable()) { + if (!Logind::isAvailable()) { //if we don't have logind/CK2, just create a single seat immediately and don't do any other connections createSeat(QStringLiteral("seat0")); return; @@ -118,41 +121,80 @@ namespace DDM { } void SeatManager::createSeat(const QString &name) { - // create a seat - Seat *seat = new Seat(name, this); + //reload config if needed + mainConfig.load(); + + // create a new display + qDebug() << "Adding new display..."; + Display *display = new Display(this, name); + + // restart display on stop + connect(display, &Display::stopped, this, &SeatManager::displayStopped); + + // start the display + startDisplay(display); // add to the list - m_seats.insert(name, seat); + displays.append(display); // emit signal emit seatCreated(name); } void SeatManager::removeSeat(const QString &name) { - // check if seat exists - if (!m_seats.contains(name)) - return; + for (auto display : std::as_const(displays)) { + if (display->name == name) { + // remove from the list + displays.removeAll(display); + // stop the display + display->blockSignals(true); + display->stop(); + display->blockSignals(false); + // delete display + display->deleteLater(); + // emit signal + emit seatRemoved(name); + return; + } + } + } - // remove from the list - Seat *seat = m_seats.take(name); + void SeatManager::switchToGreeter(const QString &name) { + for (auto display : std::as_const(displays)) { + if (display->name == name) { + // switch to greeter + display->activateSession("ddm", 0); + return; + } + } + } - // delete seat - seat->deleteLater(); + void SeatManager::startDisplay(Display *display, int tryNr) { + if (display->start()) + return; - // emit signal - emit seatRemoved(name); - } + // It's possible that the system isn't ready yet (driver not loaded, + // device not enumerated, ...). It's not possible to tell when that changes, + // so try a few times with a delay in between. + qWarning() << "Attempt" << tryNr << "starting the Display server on vt" << display->terminalId << "failed"; - void SeatManager::switchToGreeter(const QString &name) { - // check if seat exists - if (!m_seats.contains(name)) + if(tryNr >= 3) { + qCritical() << "Could not start Display server on vt" << display->terminalId; return; + } - // switch to greeter - m_seats.value(name)->createDisplay(); + QTimer::singleShot(2000, display, [this, display, tryNr] { startDisplay(display, tryNr + 1); }); + } + + void SeatManager::displayStopped() { + Display *display = qobject_cast(sender()); + QString name = display->name; + // re-create display + removeSeat(name); + createSeat(name); } - void DDM::SeatManager::logindSeatAdded(const QString& name, const QDBusObjectPath& objectPath) + void SeatManager::logindSeatAdded(const QString& name, const QDBusObjectPath& objectPath) { auto logindSeat = new LogindSeat(name, objectPath); connect(logindSeat, &LogindSeat::canGraphicalChanged, this, [this, logindSeat]() { @@ -163,13 +205,13 @@ namespace DDM { } }); - m_systemSeats.insert(name, logindSeat); + systemSeats.insert(name, logindSeat); } - void DDM::SeatManager::logindSeatRemoved(const QString& name, const QDBusObjectPath& objectPath) + void SeatManager::logindSeatRemoved(const QString& name, const QDBusObjectPath& objectPath) { Q_UNUSED(objectPath); - auto logindSeat = m_systemSeats.take(name); + auto logindSeat = systemSeats.take(name); delete logindSeat; removeSeat(name); } diff --git a/src/daemon/SeatManager.h b/src/daemon/SeatManager.h index eafa096..8d99a69 100644 --- a/src/daemon/SeatManager.h +++ b/src/daemon/SeatManager.h @@ -23,9 +23,9 @@ #include #include #include +#include "Display.h" namespace DDM { - class Seat; class LogindSeat; class SeatManager : public QObject { @@ -38,6 +38,9 @@ namespace DDM { void removeSeat(const QString &name); void switchToGreeter(const QString &seat); + QList displays; //these will exist only for graphical seats + QHash systemSeats; //these will exist for all seats + Q_SIGNALS: void seatCreated(const QString &name); void seatRemoved(const QString &name); @@ -45,10 +48,10 @@ namespace DDM { private Q_SLOTS: void logindSeatAdded(const QString &name, const QDBusObjectPath &objectPath); void logindSeatRemoved(const QString &name, const QDBusObjectPath &objectPath); + void displayStopped(); private: - QHash m_seats; //these will exist only for graphical seats - QHash m_systemSeats; //these will exist for all seats + void startDisplay(Display *display, int tryNr = 1); }; } diff --git a/src/daemon/TreelandConnector.cpp b/src/daemon/TreelandConnector.cpp index 351dfac..7414890 100644 --- a/src/daemon/TreelandConnector.cpp +++ b/src/daemon/TreelandConnector.cpp @@ -2,8 +2,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "TreelandConnector.h" +#include "Auth.h" #include "DaemonApp.h" +#include "Display.h" #include "DisplayManager.h" +#include "SeatManager.h" #include "VirtualTerminal.h" #include "treeland-ddm-v1.h" @@ -28,6 +31,17 @@ namespace DDM { static const char *defaultVtPath = "/dev/tty0"; +static bool isVtRunningTreeland(int vtnr) { + for (Display *display : daemonApp->seatManager()->displays) { + if (display->terminalId == vtnr) + return true; + for (Auth *auth : display->auths) + if (auth->tty == vtnr && auth->type == Display::Treeland) + return true; + } + return false; +} + /** * Callback function of disableRender * @@ -62,14 +76,11 @@ static void renderDisabled([[maybe_unused]] void *data, struct wl_callback *call } auto user = daemonApp->displayManager()->findUserByVt(activeVt); + bool isTreeland = isVtRunningTreeland(activeVt); auto conn = daemonApp->treelandConnector(); qDebug("Next VT: %d, user: %s", activeVt, user.isEmpty() ? "None" : qPrintable(user)); - if (user.isEmpty()) { - // Switch to a TTY, deactivate treeland session. - conn->switchToGreeter(); - conn->deactivateSession(); - } else { + if (isTreeland) { // If user is not empty, it means the switching can be issued by // ddm-helper. It uses VT signals from VirtualTerminal.h, // which is not what we want, so we should acquire VT control here. @@ -78,7 +89,11 @@ static void renderDisabled([[maybe_unused]] void *data, struct wl_callback *call close(activeVtFd); conn->enableRender(); - conn->switchToUser(user); + conn->switchToUser(user.isEmpty() ? "dde" : user); + } else { + // Switch to a TTY, deactivate treeland session. + conn->switchToGreeter(); + conn->deactivateSession(); } } @@ -96,7 +111,7 @@ static void onAcquireDisplay() { int vtnr = VirtualTerminal::getVtActive(fd); auto user = daemonApp->displayManager()->findUserByVt(vtnr); auto conn = daemonApp->treelandConnector(); - if (!user.isEmpty()) { + if (isVtRunningTreeland(vtnr)) { qDebug("Activate session at VT %d for user %s", vtnr, qPrintable(user)); conn->activateSession(); conn->enableRender(); diff --git a/src/daemon/XorgDisplayServer.cpp b/src/daemon/XorgDisplayServer.cpp index 9d01caa..60a77e0 100644 --- a/src/daemon/XorgDisplayServer.cpp +++ b/src/daemon/XorgDisplayServer.cpp @@ -21,19 +21,11 @@ #include "XorgDisplayServer.h" #include "Configuration.h" -#include "DaemonApp.h" #include "Display.h" -#include "Seat.h" #include #include -#include #include -#include - -#include - -#include #include #include @@ -100,7 +92,7 @@ namespace DDM { process->setProgram(mainConfig.X11.ServerPath.get()); args << mainConfig.X11.ServerArguments.get().split(QLatin1Char(' '), Qt::SkipEmptyParts) << QStringLiteral("-background") << QStringLiteral("none") - << QStringLiteral("-seat") << static_cast(parent())->seat->name() + << QStringLiteral("-seat") << static_cast(parent())->name << QStringLiteral("vt%1").arg(vt) << QStringLiteral("-auth") << m_xauth.authPath() << QStringLiteral("-noreset") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index c76fefb..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(QT_USE_QTTEST TRUE) - -include_directories(../src/common) - -set(ConfigurationTest_SRCS ConfigurationTest.cpp ../src/common/ConfigReader.cpp) -add_executable(ConfigurationTest ${ConfigurationTest_SRCS}) -add_test(NAME Configuration COMMAND ConfigurationTest) - -target_link_libraries(ConfigurationTest Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Test) - -set(QMLThemeConfigTest_SRCS QMLThemeConfigTest.cpp ../src/common/ThemeConfig.cpp ../src/common/ThemeConfig.h) -add_executable(QMLThemeConfigTest ${QMLThemeConfigTest_SRCS}) -target_include_directories(QMLThemeConfigTest PRIVATE ../src/common/) -add_test(NAME QMLThemeConfig COMMAND QMLThemeConfigTest -platform offscreen -input ${CMAKE_CURRENT_SOURCE_DIR}/QMLThemeConfigTest.qml WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(QMLThemeConfigTest PRIVATE Qt${QT_MAJOR_VERSION}::Quick Qt${QT_MAJOR_VERSION}::QuickTest) - -set(SessionTest_SRCS SessionTest.cpp ../src/common/Configuration.cpp ../src/common/ConfigReader.cpp ../src/common/Session.cpp) -add_executable(SessionTest ${SessionTest_SRCS}) -target_include_directories(SessionTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../src/common) -add_test(NAME Session COMMAND SessionTest) -target_link_libraries(SessionTest Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::Test) diff --git a/test/ConfigurationTest.cpp b/test/ConfigurationTest.cpp deleted file mode 100644 index 17c9f74..0000000 --- a/test/ConfigurationTest.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Configuration parser tests - * Copyright (C) 2014 Martin Bříza - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "ConfigurationTest.h" -#include - -#include -#include -#include - -QTEST_MAIN(ConfigurationTest); - -void ConfigurationTest::initTestCase() { } - -void ConfigurationTest::cleanupTestCase() { } - -void ConfigurationTest::init() { - QFile::remove(CONF_FILE); - QDir(CONF_DIR).removeRecursively(); - QDir().mkdir(CONF_DIR); - QDir(SYS_CONF_DIR).removeRecursively(); - QDir().mkdir(SYS_CONF_DIR); - QFile::remove(CONF_FILE_COPY); - config = new TestConfig; -} - -void ConfigurationTest::cleanup() { - QFile::remove(CONF_FILE); - QDir(CONF_DIR).removeRecursively(); - QDir(SYS_CONF_DIR).removeRecursively(); - QFile::remove(CONF_FILE_COPY); - if (config) - delete config; - config = nullptr; -} - -void ConfigurationTest::Basic() { - QVERIFY(config->String.get() == TEST_STRING_1); - QVERIFY(config->Int.get() == TEST_INT_1); - QVERIFY(config->StringList.get() == QStringList(TEST_STRINGLIST_1)); - QVERIFY(config->Boolean.get() == TEST_BOOL_1); - config->save(); - QVERIFY(!QFile::exists(CONF_FILE)); - config->String.set(config->String.get().append(QStringLiteral(" Appended"))); - config->save(); - QVERIFY(QFile::exists(CONF_FILE)); - config->String.set(config->String.get().append(QStringLiteral(" Appended Again"))); - config->save(); - QVERIFY(QFile::exists(CONF_FILE)); -} - -void ConfigurationTest::Sections() { - QVERIFY(config->Section.String.get() == TEST_STRING_1); - QVERIFY(config->Section.Int.get() == TEST_INT_1); - QVERIFY(config->Section.StringList.get() == QStringList(TEST_STRINGLIST_1)); - QVERIFY(config->Section.Boolean.get() == TEST_BOOL_1); - config->save(); - QVERIFY(!QFile::exists(CONF_FILE)); - config->Section.String.set(config->Section.String.get().append(QStringLiteral(" Appended"))); - config->save(); - QVERIFY(QFile::exists(CONF_FILE)); - config->Section.String.set(config->Section.String.get().append(QStringLiteral(" Appended Again"))); - config->save(); - QVERIFY(QFile::exists(CONF_FILE)); -} - -void ConfigurationTest::Unused() { - QFile confFile(CONF_FILE); - QFile confCopy(CONF_FILE_COPY); - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write("InvalidGeneralValue=(null)\n"); - confFile.write("#InvalidSection Comment\n"); - confFile.write("[InvalidSection]\n"); - confFile.write("BadSectionValue=0\n"); - confFile.close(); - config->load(); - config->String.set(QStringLiteral("Changed String")); - config->Section.String.set(QStringLiteral("Changed String")); - config->save(); - QFile::copy(CONF_FILE, CONF_FILE_COPY); - config->load(); - config->save(); - QVERIFY(confFile.open(QIODevice::ReadOnly)); - QVERIFY(confCopy.open(QIODevice::ReadOnly)); - // the file must not change on consecutive loads and reads - QByteArray contents = confFile.readAll(); - QVERIFY(contents == confCopy.readAll()); - QVERIFY(contents.contains("InvalidGeneralValue")); - QVERIFY(contents.contains("InvalidSection")); - QVERIFY(contents.contains("BadSectionValue")); -} - -void ConfigurationTest::LineChanges() { - QFile confFile(CONF_FILE); - QFile confCopy(CONF_FILE_COPY); - // put some junk there to make it a bit harder to parse - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write("InvalidGeneralValue=(null)\n"); - confFile.close(); - // assuming the integers will be of the same length when saved - config->Int.set(1); - config->save(); - QFile::copy(CONF_FILE, CONF_FILE_COPY); - config->Int.set(2); - config->save(); - QVERIFY(confFile.size() == confCopy.size()); -} - -void ConfigurationTest::CustomEnum() { - - QTest::qWait(2000); - QFile confFile(CONF_FILE); - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write("Custom=bar\n"); - confFile.close(); - QVERIFY(config->Custom.get() == TestConfig::FOO); - config->load(); - QVERIFY(config->Custom.get() == TestConfig::BAR); - config->Custom.set(TestConfig::BAZ); - config->save(); - QVERIFY(confFile.open(QIODevice::ReadOnly)); - QByteArray contents = confFile.readAll(); - QVERIFY(contents.contains("baz")); - QVERIFY(!contents.contains("bar")); - QVERIFY(!contents.contains("foo")); -} - -void ConfigurationTest::RightOnInit() { - delete config; - QFile confFile(CONF_FILE); - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write("String=a\n"); - confFile.write("Int=99999\n"); - confFile.write("StringList=a,b,c,qwertzuiop\n"); - confFile.write("Boolean=false\n"); - confFile.write("Custom=null\n"); - confFile.close(); - config = new TestConfig; - QVERIFY(config->String.get() == QStringLiteral("a")); - QVERIFY(config->Int.get() == 99999); - QVERIFY(config->StringList.get() == QStringList({QStringLiteral("a"), QStringLiteral("b"), QStringLiteral("c"), QStringLiteral("qwertzuiop")})); - QVERIFY(config->Boolean.get() == false); - QVERIFY(config->Custom.get() == TestConfig::BAZ); -} - - -void ConfigurationTest::RightOnInitDir() { - delete config; - - QFile confFileA(SYS_CONF_DIR+QStringLiteral("/0001A")); - confFileA.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFileA.write("Custom=Foo\n"); //overriden by B - confFileA.write("Boolean=false\n"); - confFileA.close(); - - QFile confFileB(CONF_DIR+QStringLiteral("/0001A")); - confFileB.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFileB.write("String=a\n"); //overriden by C - confFileB.write("Custom=Bar\n"); - confFileB.write("StringList=a,b,c\n"); - confFileB.write("Int=1111111\n"); //this is set in this config file but overriden in CONF_FILE - confFileB.close(); - - QFile confFileC(CONF_DIR+QStringLiteral("/0001B")); - confFileC.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFileC.write("String=b\n"); - confFileC.write("Int=1111111\n"); //overriden in CONF_FILE - confFileC.close(); - - QFile confFileMain(CONF_FILE); - confFileMain.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFileMain.write("Int=99999\n"); - confFileMain.close(); - confFileB.close(); - - config = new TestConfig; - QVERIFY(config->StringList.get() == QStringList({QStringLiteral("a"), QStringLiteral("b"), QStringLiteral("c")})); - QVERIFY(config->String.get() == QStringLiteral("b")); - QVERIFY(config->Int.get() == 99999); - QVERIFY(config->Custom.get() == TestConfig::BAR); - QVERIFY(config->Boolean.get() == false); -} - -void ConfigurationTest::FileChanged() -{ - QVERIFY(config->String.get() == QStringLiteral("Test Variable Initial String")); - - QTest::qWait(2000); - - //test from no file to a file - QFile confFile(CONF_FILE); - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write("String=a\n"); - confFile.close(); - - config->load(); - QVERIFY(config->String.get() == QStringLiteral("a")); - - //test file changed - //wait 2 seconds so timestamp is definitely 1 second apart - QTest::qWait(2000); - - confFile.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFile.write("String=b\n"); - confFile.close(); - - config->load(); - QVERIFY(config->String.get() == QStringLiteral("b")); - - QTest::qWait(2000); - - //add file to conf dir - QFile confFileA(CONF_DIR+QStringLiteral("/0001A")); - confFileA.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFileA.write("Int=1111111\n"); //this is set in this config file but overriden in CONF_FILE - confFileA.close(); - config->load(); - QVERIFY(config->Int.get() ==1111111); - - QTest::qWait(2000); - //modify existing file in conf dir - - confFileA.open(QIODevice::WriteOnly | QIODevice::Truncate); - confFileA.write("Int=222222\n"); //this is set in this config file but overriden in CONF_FILE - confFileA.close(); - config->load(); - QVERIFY(config->Int.get() == 222222); -} - -#include "moc_ConfigurationTest.cpp" diff --git a/test/ConfigurationTest.h b/test/ConfigurationTest.h deleted file mode 100644 index 6061533..0000000 --- a/test/ConfigurationTest.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Configuration parser tests - * Copyright (C) 2014 Martin Bříza - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef CONFIGURATIONTEST_H -#define CONFIGURATIONTEST_H - -#include -#include - -#include "ConfigReader.h" - -#define CONF_FILE QStringLiteral("test.conf") -#define CONF_DIR QStringLiteral("testconfdir") -#define SYS_CONF_DIR QStringLiteral("testconfdir2") -#define CONF_FILE_COPY QStringLiteral("test_copy.conf") - -#define TEST_STRING_1_PLAIN "Test Variable Initial String" -#define TEST_STRING_1 QStringLiteral(TEST_STRING_1_PLAIN) -#define TEST_INT_1 12345 -#define TEST_STRINGLIST_1 {QStringLiteral("String1"), QStringLiteral("String2")} -#define TEST_BOOL_1 true - -Config (TestConfig, CONF_FILE, CONF_DIR, SYS_CONF_DIR, - enum CustomType { - FOO, - BAR, - BAZ - }; - Entry( String, QString, _S(TEST_STRING_1_PLAIN), _S("Test String Description")); - Entry( Int, int, TEST_INT_1, _S("Test Integer Description")); - Entry(StringList, QStringList, QStringList(TEST_STRINGLIST_1), _S("Test StringList Description")); - Entry( Boolean, bool, TEST_BOOL_1, _S("Test Boolean Description")); - Entry( Custom, CustomType, FOO, _S("Custom type imitating NumState")); - Section(Section, - Entry( String, QString, _S(TEST_STRING_1_PLAIN), _S("Test String Description")); - Entry( Int, int, TEST_INT_1, _S("Test Integer Description")); - Entry(StringList, QStringList, QStringList(TEST_STRINGLIST_1), _S("Test StringList Description")); - Entry( Boolean, bool, TEST_BOOL_1, _S("Test Boolean Description")); - ); -); - -inline QTextStream& operator>>(QTextStream &str, TestConfig::CustomType &state) { - QString text = str.readLine().trimmed(); - if (text.compare(QLatin1String("foo"), Qt::CaseInsensitive) == 0) - state = TestConfig::FOO; - else if (text.compare(QLatin1String("bar"), Qt::CaseInsensitive) == 0) - state = TestConfig::BAR; - else - state = TestConfig::BAZ; - return str; -} - -inline QTextStream& operator<<(QTextStream &str, const TestConfig::CustomType &state) { - if (state == TestConfig::FOO) - str << "foo"; - else if (state == TestConfig::BAR) - str << "bar"; - else - str << "baz"; - return str; -} - -class ConfigurationTest : public QObject -{ - Q_OBJECT -private slots: - void initTestCase(); - void cleanupTestCase(); - - void init(); - void cleanup(); - - void Basic(); - void Sections(); - void Unused(); - void LineChanges(); - void CustomEnum(); - void RightOnInit(); - void RightOnInitDir(); - void FileChanged(); - -private: - TestConfig *config; -}; - -#endif // CONFIGURATIONTEST_H diff --git a/test/QMLThemeConfigTest.cpp b/test/QMLThemeConfigTest.cpp deleted file mode 100644 index b5c3e69..0000000 --- a/test/QMLThemeConfigTest.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2023 Fabian Vogt -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include -#include -#include - -#include "ThemeConfig.h" - -class Setup : public QObject -{ - Q_OBJECT -public slots: - void qmlEngineAvailable(QQmlEngine *engine) - { - auto *config = new DDM::ThemeConfig(QStringLiteral("theme.conf"), this); - engine->rootContext()->setContextProperty(QStringLiteral("config"), config); - } -}; - -QUICK_TEST_MAIN_WITH_SETUP(QMLThemeConfigTest, Setup) - -#include "QMLThemeConfigTest.moc" diff --git a/test/QMLThemeConfigTest.qml b/test/QMLThemeConfigTest.qml deleted file mode 100644 index a658fad..0000000 --- a/test/QMLThemeConfigTest.qml +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2023 Fabian Vogt -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -import QtQuick 2.3 -import QtTest 1.0 - -TestCase { - name: "QMLThemeConfigTest" - - function test_keys() { - let keys = Object.keys(config); - compare(keys.indexOf("doesnotexist"), -1); - verify(keys.indexOf("someInteger") >= 0); - keys = config.keys(); - compare(keys.indexOf("doesnotexist"), -1); - verify(keys.indexOf("someInteger") >= 0); - } - - // Everything is a string - function test_propertyAPI() { - compare(config.doesnotexist, undefined); - compare(config.someTrueBool, "yes"); - compare(!!config.someTrueBool, true); - compare(config.someFalseBool, "false"); - // "false" as a string is truthy! - compare(!!config.someFalseBool, true); - compare(config.someInteger, "042"); - compare(+config.someInteger, 42); - compare(config.someRealNumber, "01.5"); - compare(+config.someRealNumber, 1.5); - compare(config.someString, "Pie/180"); - } - - // Strings are converted to specific types - function test_typedAPI() { - compare(config.stringValue("doesnotexist"), ""); - compare(config.boolValue("someTrueBool"), true); - compare(config.boolValue("someFalseBool"), false); - // "false" as a string is truthy! - compare(!!config.someFalseBool, true); - compare(config.stringValue("someInteger"), "042"); - compare(config.intValue("someInteger"), 42); - compare(config.realValue("someRealNumber"), 1.5); - // conversion fails -> 0 - compare(config.intValue("someRealNumber"), 0); - compare(config.stringValue("someString"), "Pie/180"); - // conversion fails -> 0 - compare(config.intValue("someString"), 0); - compare(config.realValue("someString"), 0); - } -} diff --git a/test/SessionTest.cpp b/test/SessionTest.cpp deleted file mode 100644 index 8876cab..0000000 --- a/test/SessionTest.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2023 Fabian Vogt -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -***************************************************************************/ - -#include "Session.h" - -#include -#include - -class SessionTest : public QObject { - Q_OBJECT -private slots: - void testCLocale() - { - QLocale::setDefault(QLocale::c()); - auto fileName = QFINDTESTDATA("plasmawayland-dev.desktop"); - DDM::Session session(DDM::Session::WaylandSession, fileName); - QVERIFY(session.isValid()); - QCOMPARE(session.xdgSessionType(), QStringLiteral("wayland")); - QCOMPARE(session.fileName(), fileName); - QCOMPARE(session.displayName(), QStringLiteral("Plasma (Development, Wayland /usr/bin)")); - QCOMPARE(session.comment(), QStringLiteral("Plasma by KDE")); - QCOMPARE(session.exec(), QStringLiteral("/usr/lib64/libexec/plasma-dbus-run-session-if-needed /usr/lib64/libexec/startplasma-dev.sh -wayland")); - QCOMPARE(session.tryExec(), QString()); - QCOMPARE(session.desktopSession(), QStringLiteral("plasmawayland-dev")); - QCOMPARE(session.desktopNames(), QStringLiteral("KDE")); - QCOMPARE(session.isHidden(), false); - QCOMPARE(session.isNoDisplay(), false); - } - void testKOLocale() - { - QLocale::setDefault(QLocale{QStringLiteral("ko_KO")}); - auto fileName = QFINDTESTDATA("plasmawayland-dev.desktop"); - DDM::Session session(DDM::Session::WaylandSession, fileName); - QVERIFY(session.isValid()); - QCOMPARE(session.xdgSessionType(), QStringLiteral("wayland")); - QCOMPARE(session.fileName(), fileName); - QCOMPARE(session.displayName(), QStringLiteral("Plasma(\uAC1C\uBC1C, Wayland /usr/bin)")); - QCOMPARE(session.comment(), QStringLiteral("KDE Plasma")); - QCOMPARE(session.exec(), QStringLiteral("/usr/lib64/libexec/plasma-dbus-run-session-if-needed /usr/lib64/libexec/startplasma-dev.sh -wayland")); - QCOMPARE(session.tryExec(), QString()); - QCOMPARE(session.desktopSession(), QStringLiteral("plasmawayland-dev")); - QCOMPARE(session.desktopNames(), QStringLiteral("KDE")); - QCOMPARE(session.isHidden(), false); - QCOMPARE(session.isNoDisplay(), false); - } -}; - -QTEST_MAIN(SessionTest); - -#include "SessionTest.moc" diff --git a/test/plasmawayland-dev.desktop b/test/plasmawayland-dev.desktop deleted file mode 100644 index 0fa1b87..0000000 --- a/test/plasmawayland-dev.desktop +++ /dev/null @@ -1,106 +0,0 @@ -[Desktop Entry] -Exec=/usr/lib64/libexec/plasma-dbus-run-session-if-needed /usr/lib64/libexec/startplasma-dev.sh -wayland -DesktopNames=KDE -Name=Plasma (Development, Wayland /usr/bin) -Name[ar]=بلازما (تطوير, ويلاند /usr/bin) -Name[az]=Plasma (Tərtib mərhələsində olan Wayland /usr/bin) -Name[be]=Plasma (Development, Wayland /usr/bin) -Name[bg]=Plasma (Development, Wayland /usr/bin) -Name[ca]=Plasma (Desenvolupament, Wayland /usr/bin) -Name[ca@valencia]=Plasma (Desenvolupament, Wayland /usr/bin) -Name[da]=Plasma (udvikling, Wayland /usr/bin) -Name[de]=Plasma (Development, Wayland /usr/bin) -Name[en_GB]=Plasma (Development, Wayland /usr/bin) -Name[es]=Plasma (Desarrollo, Wayland /usr/bin) -Name[et]=Plasma (arendus, Wayland /usr/bin) -Name[eu]=Plasma (Garapena, Wayland /usr/bin) -Name[fi]=Plasma (kehitys, Wayland /usr/bin) -Name[fr]=Plasma (Développement, Wayland /usr/bin) -Name[gl]=Plasma (desenvolvemento, Wayland /usr/bin) -Name[hi]=प्लाज़्मा (विकास, वैलेंड /usr/bin) -Name[hu]=Plasma (Fejlesztői verzió, Wayland /usr/bin) -Name[ia]=Plasma (Disveloppamento, Wayland /usr/bin) -Name[id]=Plasma (Development, Wayland /usr/bin) -Name[is]=Plasma (Þróunarútgáfa, Wayland /usr/bin) -Name[it]=Plasma (Sviluppo, Wayland /usr/bin) -Name[ja]=Plasma (Development, Wayland /usr/bin) -Name[ka]=Plasma (Development, Wayland /usr/bin) -Name[ko]=Plasma(개발, Wayland /usr/bin) -Name[lt]=Plasma (Plėtojimas, Wayland /usr/bin) -Name[ml]=പ്ലാസ്മ (വികസനം, വേലാൻഡ് /usr/bin) -Name[nl]=Plasma (Ontwikkeling, Wayland /usr/bin) -Name[nn]=Plasma (utvikling, Wayland /usr/bin) -Name[pa]=ਪਲਾਜ਼ਮਾ (ਡਿਵੈਲਪਮੈਂਟ, ਵੇਅਲੈਂਡ /usr/bin) -Name[pl]=Plazma (Rozwój , Wayland /usr/bin) -Name[pt]=Plasma (Desenvolvimento, Wayland /usr/bin) -Name[pt_BR]=Plasma (Desenvolvimento, Wayland /usr/bin) -Name[ro]=Plasma (Dezvoltare, Wayland /usr/bin) -Name[ru]=Plasma (разрабатываемая версия, Wayland /usr/bin) -Name[sk]=Plasma (Development, Wayland /usr/bin) -Name[sl]=Plasma (Razvoj, Wayland /usr/bin) -Name[sv]=Plasma (utveckling, Wayland /usr/bin) -Name[ta]=பிளாஸ்மா (Development, Wayland /usr/bin) -Name[tr]=Plasma (Geliştirme, Wayland $ {CMAKE_INSTALL_FULL_BINDIR}) -Name[uk]=Плазма (Розробка, Wayland /usr/bin) -Name[vi]=Plasma (Phát triển, Wayland /usr/bin) -Name[x-test]=xxPlasma (Development, Wayland /usr/bin)xx -Name[zh_CN]=Plasma (Development, Wayland /usr/bin) -Name[zh_TW]=Plasma (開發版本,Wayland /usr/bin) -Comment=Plasma by KDE -Comment[ar]=بلازما كدي -Comment[az]=KDE Plasma -Comment[be]=Plasma KDE -Comment[bg]=Plasma от KDE -Comment[bs]=Plazma od strane KDe -Comment[ca]=Plasma, creat per la comunitat KDE -Comment[ca@valencia]=Plasma, creat per la comunitat KDE -Comment[cs]=Plasma z KDE -Comment[da]=Plasma fra KDE -Comment[de]=Plasma von KDE -Comment[el]=Plasma από το KDE -Comment[en_GB]=Plasma by KDE -Comment[es]=Plasma, por KDE -Comment[et]=KDE Plasma -Comment[eu]=KDEren Plasma -Comment[fi]=Plasma KDE:ltä -Comment[fr]=Plasma, par KDE -Comment[gl]=Plasma, fornecido por KDE. -Comment[he]=פלזמה באמצעות KDE -Comment[hi]=केडीइ द्वारा प्लाज़्मा -Comment[hsb]=Plasma wot KDE -Comment[hu]=Plasma a KDE-től -Comment[ia]=Plasma per KDE -Comment[id]=Plasma oleh KDE -Comment[is]=Plasma frá KDE -Comment[it]=Plasma di KDE -Comment[ja]=Plasma by KDE -Comment[ka]=Plasma, KDE-სგან -Comment[ko]=KDE Plasma -Comment[lt]=Plasma pagal KDE -Comment[ml]=കെഡിഇയുടെ പ്ലാസ്മ -Comment[nb]=Plasma av KDE -Comment[nds]=Plasma vun KDE -Comment[nl]=Plasma door KDE -Comment[nn]=Plasma frå KDE -Comment[pa]=KDE ਵਲੋਂ ਪਲਾਜ਼ਮਾ -Comment[pl]=Plazma dzięki KDE -Comment[pt]=Plasma do KDE -Comment[pt_BR]=Plasma do KDE -Comment[ro]=Plasma, de către KDE -Comment[ru]=KDE Plasma -Comment[sk]=Plasma od KDE -Comment[sl]=KDE Plasma -Comment[sr]=Плазма од КДЕ‑а -Comment[sr@ijekavian]=Плазма од КДЕ‑а -Comment[sr@ijekavianlatin]=Plasma od KDE‑a -Comment[sr@latin]=Plasma od KDE‑a -Comment[sv]=Plasma av KDE -Comment[ta]=கே.டீ.யீ. வழங்கும் பிளாஸ்மா -Comment[tg]=Plasma аз ҷониби KDE -Comment[tr]=KDE Plasma -Comment[uk]=Плазма KDE -Comment[vi]=Plasma, do KDE -Comment[x-test]=xxPlasma by KDExx -Comment[zh_CN]=KDE Plasma -Comment[zh_TW]=Plasma by KDE -X-KDE-PluginInfo-Version=5.27.0 diff --git a/test/theme.conf b/test/theme.conf deleted file mode 100644 index cb74cf0..0000000 --- a/test/theme.conf +++ /dev/null @@ -1,6 +0,0 @@ -[General] -someTrueBool=yes -someFalseBool=false -someInteger=042 -someRealNumber=01.5 -someString="Pie/180"