commit
ef374d817c
|
@ -2,6 +2,8 @@
|
|||
*.dump
|
||||
.idea
|
||||
build
|
||||
target
|
||||
src/config.rs
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
##
|
||||
## PROJECT
|
||||
## name and version
|
||||
##
|
||||
project(cachyos-hello CXX)
|
||||
|
||||
##
|
||||
## INCLUDE
|
||||
##
|
||||
include(GNUInstallDirs)
|
||||
include(StandardProjectSettings)
|
||||
include(CompilerWarnings)
|
||||
include(EnableCcache)
|
||||
include(ClangTidy)
|
||||
include(FetchContent)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(
|
||||
GTKMM
|
||||
REQUIRED
|
||||
IMPORTED_TARGET
|
||||
gtkmm-3.0)
|
||||
|
||||
FetchContent_Declare(fmt
|
||||
GIT_REPOSITORY "https://github.com/fmtlib/fmt.git"
|
||||
GIT_TAG "f5cdf7cb0481afdafa7ff2f5ea640f05215d4ffb"
|
||||
)
|
||||
FetchContent_MakeAvailable(fmt)
|
||||
|
||||
##
|
||||
## CONFIGURATION
|
||||
##
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fwhole-program")
|
||||
endif()
|
||||
|
||||
# Link this 'library' to set the c++ standard / compile-time options requested
|
||||
add_library(project_options INTERFACE)
|
||||
target_compile_features(project_options INTERFACE cxx_std_20)
|
||||
|
||||
##
|
||||
## Target
|
||||
##
|
||||
add_executable(${PROJECT_NAME}
|
||||
src/hello.cpp src/hello.hpp
|
||||
src/main.cpp
|
||||
)
|
||||
|
||||
# Link this 'library' to use the warnings specified in CompilerWarnings.cmake
|
||||
add_library(project_warnings INTERFACE)
|
||||
set_project_warnings(project_warnings)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src ${GTK3_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options PkgConfig::GTKMM fmt::fmt)
|
||||
|
||||
option(ENABLE_UNITY "Enable Unity builds of projects" OFF)
|
||||
if(ENABLE_UNITY)
|
||||
# Add for any project you want to apply unity builds for
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES UNITY_BUILD ON)
|
||||
endif()
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_SOURCE_DIR}/cachyos-hello.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${CMAKE_SOURCE_DIR}/data
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${CMAKE_SOURCE_DIR}/ui
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
|
||||
# uninstall
|
||||
add_custom_target(uninstall
|
||||
COMMAND cat ${PROJECT_BINARY_DIR}/install_manifest.txt | xargs rm
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
|
@ -0,0 +1,804 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||
|
||||
[[package]]
|
||||
name = "atk"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd"
|
||||
dependencies = [
|
||||
"atk-sys",
|
||||
"bitflags",
|
||||
"glib",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atk-sys"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58aeb089fb698e06db8089971c7ee317ab9644bade33383f63631437b03aafb6"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "cachyos-hello"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"gdk",
|
||||
"gdk-pixbuf",
|
||||
"gettext-rs",
|
||||
"gio",
|
||||
"glib",
|
||||
"gtk",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"subprocess",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-rs"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62be3562254e90c1c6050a72aa638f6315593e98c5cdaba9017cedbabf0a5dee"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cairo-sys-rs",
|
||||
"glib",
|
||||
"libc",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-sys-rs"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
"gdk-pixbuf",
|
||||
"gdk-sys",
|
||||
"gio",
|
||||
"glib",
|
||||
"libc",
|
||||
"pango",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gdk-pixbuf-sys",
|
||||
"gio",
|
||||
"glib",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf-sys"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7"
|
||||
dependencies = [
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gdk-sys"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32e7a08c1e8f06f4177fb7e51a777b8c1689f743a7bc11ea91d44d2226073a88"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gettext-rs"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e49ea8a8fad198aaa1f9655a2524b64b70eb06b2f3ff37da407566c93054f364"
|
||||
dependencies = [
|
||||
"gettext-sys",
|
||||
"locale_config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gettext-sys"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c63ce2e00f56a206778276704bbe38564c8695249fdc8f354b4ef71c57c3839d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"temp-dir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f132be35e05d9662b9fa0fee3f349c6621f7782e0105917f4cc73c1bf47eceb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"gio-sys",
|
||||
"glib",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd124026a2fa8c33a3d17a3fe59c103f2d9fa5bd92c19e029e037736729abeab"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-task",
|
||||
"glib-macros",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-macros"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"heck",
|
||||
"proc-macro-crate",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0"
|
||||
dependencies = [
|
||||
"atk",
|
||||
"bitflags",
|
||||
"cairo-rs",
|
||||
"field-offset",
|
||||
"futures-channel",
|
||||
"gdk",
|
||||
"gdk-pixbuf",
|
||||
"gio",
|
||||
"glib",
|
||||
"gtk-sys",
|
||||
"gtk3-macros",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"pango",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk-sys"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5bc2f0587cba247f60246a0ca11fe25fb733eabc3de12d1965fc07efab87c84"
|
||||
dependencies = [
|
||||
"atk-sys",
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
"gdk-sys",
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gtk3-macros"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"proc-macro-crate",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "locale_config"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"regex",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"glib",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"pango-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango-sys"
|
||||
version = "0.15.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||
dependencies = [
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
|
||||
dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
|
||||
[[package]]
|
||||
name = "subprocess"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "6.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
|
||||
dependencies = [
|
||||
"cfg-expr",
|
||||
"heck",
|
||||
"pkg-config",
|
||||
"toml",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "temp-dir"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af547b166dd1ea4b472165569fc456cfb6818116f854690b0ff205e636523dab"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "cachyos-hello"
|
||||
version = "0.7.0"
|
||||
authors = ["Vladislav Nepogodin <nepogodin.vlad@gmail.com>"]
|
||||
license = "GPLv3"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
subprocess = "0.2.9"
|
||||
once_cell = "1.12.0"
|
||||
gettext-rs = { version = "0.7", features = ["gettext-system"] }
|
||||
gtk = { version = "0.15.5", features = ["v3_24_30"] }
|
||||
gio = { version = "0.15.11", features = ["v2_72"] }
|
||||
gdk = "0.15.4"
|
||||
gdk-pixbuf = "0.15.11"
|
||||
glib = "0.15.11"
|
||||
serde = { version = "1.0.137", features = ["derive"] }
|
||||
serde_json = "1.0.81"
|
||||
|
||||
[profile.release]
|
||||
strip = "symbols"
|
||||
panic = "abort"
|
||||
lto = true
|
||||
opt-level = 3
|
||||
codegen-units = 1
|
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from os import environ, path
|
||||
from subprocess import run
|
||||
from argparse import ArgumentParser
|
||||
from shutil import copy
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("build_root")
|
||||
parser.add_argument("source_root")
|
||||
parser.add_argument("output")
|
||||
parser.add_argument("profile")
|
||||
parser.add_argument("project_name")
|
||||
args = parser.parse_args()
|
||||
|
||||
environ["CARGO_TARGET_DIR"] = path.join(args.build_root, "target")
|
||||
environ["CARGO_HOME"] = path.join(args.build_root, "cargo-home")
|
||||
|
||||
cargo_toml_path = path.join(args.source_root, "Cargo.toml")
|
||||
|
||||
if args.profile == "Devel":
|
||||
print("DEBUG MODE")
|
||||
run(
|
||||
[
|
||||
"cargo",
|
||||
"build",
|
||||
"--manifest-path",
|
||||
cargo_toml_path,
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
build_dir = path.join(environ["CARGO_TARGET_DIR"], "debug", args.project_name)
|
||||
copy(build_dir, args.output)
|
||||
else:
|
||||
print("RELEASE MODE")
|
||||
run(
|
||||
[
|
||||
"cargo",
|
||||
"build",
|
||||
"--manifest-path",
|
||||
cargo_toml_path,
|
||||
"--release",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
build_dir = path.join(environ["CARGO_TARGET_DIR"], "release", args.project_name)
|
||||
copy(build_dir, args.output)
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
export DIST="$1"
|
||||
export SOURCE_ROOT="$2"
|
||||
|
||||
cd "$SOURCE_ROOT"
|
||||
mkdir "$DIST"/.cargo
|
||||
cargo vendor | sed 's/^directory = ".*"/directory = "vendor"/g' > $DIST/.cargo/config
|
||||
# Move vendor into dist tarball directory
|
||||
mv vendor "$DIST"
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
option(ENABLE_TIDY "Enable clang-tidy [default: OFF]" OFF)
|
||||
if(ENABLE_TIDY)
|
||||
find_program(CLANG_TIDY_EXE
|
||||
NAMES clang-tidy-9 clang-tidy-8 clang-tidy-7 clang-tidy
|
||||
DOC "Path to clang-tidy executable")
|
||||
if(NOT CLANG_TIDY_EXE)
|
||||
message(STATUS "[clang-tidy] Not found.")
|
||||
else()
|
||||
message(STATUS "[clang-tidy] found: ${CLANG_TIDY_EXE}")
|
||||
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "[clang-tidy] Disabled.")
|
||||
endif()
|
|
@ -1,76 +0,0 @@
|
|||
function(set_project_warnings project_name)
|
||||
option(WARNINGS_AS_ERRORS "Treat compiler warnings as error" ON)
|
||||
|
||||
set(MSVC_WARNINGS
|
||||
/W4 # Base
|
||||
/w14242 # Conversion
|
||||
/w14254 # Operator convers.
|
||||
/w14263 # Func member doesn't override
|
||||
/w14265 # class has vfuncs, but destructor is not
|
||||
/w14287 # unsigned/negative constant mismatch
|
||||
/we4289 # nonstandard extension used: loop control var
|
||||
/w14296 # expression is always 'boolean_value'
|
||||
/w14311 # pointer trunc from one tipe to another
|
||||
/w14545 # expression before comma evaluates to a function which missign an argument list
|
||||
|
||||
/w14546 # function call before comma missing argument list
|
||||
/w14547 # operator before comma has no effect; expected operator with side-effect
|
||||
/w14549 # operator before comma has no effect; did you intend operator?
|
||||
|
||||
/w14555 # expresion has no effect; expected expression with side-effect
|
||||
/w14619 # pragma warning
|
||||
/w14640 # Enable warning on thread; static member
|
||||
|
||||
/w14826 # Conversion from one tipe to another is sign-extended cause unexpected runtime behavior.
|
||||
/w14928 # illegal copy-initialization; more than user-defined.
|
||||
/X
|
||||
/constexpr
|
||||
)
|
||||
|
||||
set(CLANG_WARNINGS
|
||||
-Wall
|
||||
-Wextra # standard
|
||||
-Wshadow
|
||||
|
||||
-Wnon-virtual-dtor
|
||||
|
||||
-Wold-style-cast # c-style cast
|
||||
-Wcast-align
|
||||
-Wunused
|
||||
-Woverloaded-virtual
|
||||
|
||||
-Wpedantic # non-standard C++
|
||||
-Wconversion # type conversion that may lose data
|
||||
-Wsign-conversion
|
||||
-Wnull-dereference
|
||||
-Wdouble-promotion # float to double
|
||||
|
||||
-Wformat=2
|
||||
)
|
||||
|
||||
if(WARNINGS_AS_ERRORS)
|
||||
set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror)
|
||||
set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX)
|
||||
endif()
|
||||
|
||||
set(GCC_WARNINGS
|
||||
${CLANG_WARNINGS}
|
||||
-Wmisleading-indentation
|
||||
|
||||
-Wduplicated-cond
|
||||
-Wduplicated-branches
|
||||
-Wlogical-op
|
||||
|
||||
-Wuseless-cast
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
set(PROJECT_WARNINGS ${MSVC_WARNINGS})
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(PROJECT_WARNINGS ${CLANG_WARNINGS})
|
||||
else()
|
||||
set(PROJECT_WARNINGS ${GCC_WARNINGS})
|
||||
endif()
|
||||
|
||||
target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS})
|
||||
endfunction()
|
|
@ -1,13 +0,0 @@
|
|||
# Setup ccache.
|
||||
#
|
||||
# The ccache is auto-enabled if the tool is found.
|
||||
# To disable set -DCCACHE=OFF option.
|
||||
if(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER)
|
||||
find_program(CCACHE ccache DOC "ccache tool path; set to OFF to disable")
|
||||
if(CCACHE)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
|
||||
message(STATUS "[ccache] Enabled: ${CCACHE}")
|
||||
else()
|
||||
message(STATUS "[ccache] Disabled.")
|
||||
endif()
|
||||
endif()
|
|
@ -1,42 +0,0 @@
|
|||
# Set a default build type if none was specified
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE
|
||||
RelWithDebInfo
|
||||
CACHE STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui, ccmake
|
||||
set_property(
|
||||
CACHE CMAKE_BUILD_TYPE
|
||||
PROPERTY STRINGS
|
||||
"Debug"
|
||||
"Release"
|
||||
"MinSizeRel"
|
||||
"RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
# Generate compile_commands.json to make it easier to work with clang based tools
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF)
|
||||
|
||||
if(ENABLE_IPO)
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(
|
||||
RESULT
|
||||
result
|
||||
OUTPUT
|
||||
output)
|
||||
if(result)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||
else()
|
||||
message(SEND_ERROR "IPO is not supported: ${output}")
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
|
||||
add_compile_options(-fcolor-diagnostics)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
else()
|
||||
message(STATUS "No colored compiler diagnostic set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
|
||||
endif()
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
-std=gnu++17
|
||||
-DFMT_LOCALE
|
||||
-I/usr/include/gtkmm-3.0
|
||||
-I/usr/lib/gtkmm-3.0/include
|
||||
-I/usr/include/giomm-2.4
|
||||
-I/usr/lib/giomm-2.4/include
|
||||
-I/usr/include/glib-2.0
|
||||
-I/usr/lib/glib-2.0/include
|
||||
-I/usr/include/libmount
|
||||
-I/usr/include/blkid
|
||||
-I/usr/include/glibmm-2.4
|
||||
-I/usr/lib/glibmm-2.4/include
|
||||
-I/usr/include/sigc++-2.0
|
||||
-I/usr/lib/sigc++-2.0/include
|
||||
-I/usr/include/gtk-3.0
|
||||
-I/usr/include/pango-1.0
|
||||
-I/usr/include/harfbuzz
|
||||
-I/usr/include/freetype2
|
||||
-I/usr/include/libpng16
|
||||
-I/usr/include/fribidi
|
||||
-I/usr/include/cairo
|
||||
-I/usr/include/lzo
|
||||
-I/usr/include/pixman-1
|
||||
-I/usr/include/gdk-pixbuf-2.0
|
||||
-I/usr/include/gio-unix-2.0
|
||||
-I/usr/include/cloudproviders
|
||||
-I/usr/include/atk-1.0
|
||||
-I/usr/include/at-spi2-atk/2.0
|
||||
-I/usr/include/dbus-1.0
|
||||
-I/usr/lib/dbus-1.0/include
|
||||
-I/usr/include/at-spi-2.0
|
||||
-I/usr/include/cairomm-1.0
|
||||
-I/usr/lib/cairomm-1.0/include
|
||||
-I/usr/include/pangomm-1.4
|
||||
-I/usr/lib/pangomm-1.4/include
|
||||
-I/usr/include/atkmm-1.6
|
||||
-I/usr/lib/atkmm-1.6/include
|
||||
-I/usr/include/gtk-3.0/unix-print
|
||||
-I/usr/include/gdkmm-3.0
|
||||
-I/usr/lib/gdkmm-3.0/include
|
||||
-Isrc
|
||||
-xc++
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/sh
|
||||
# Source: https://gitlab.gnome.org/GNOME/fractal/blob/master/hooks/pre-commit.hook
|
||||
|
||||
install_rustfmt() {
|
||||
if ! which rustup &> /dev/null; then
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -y
|
||||
export PATH=$PATH:$HOME/.cargo/bin
|
||||
if ! which rustup &> /dev/null; then
|
||||
echo "Failed to install rustup. Performing the commit without style checking."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! rustup component list|grep rustfmt &> /dev/null; then
|
||||
echo "Installing rustfmt…"
|
||||
rustup component add rustfmt
|
||||
fi
|
||||
}
|
||||
|
||||
if ! which cargo >/dev/null 2>&1 || ! cargo fmt --help >/dev/null 2>&1; then
|
||||
echo "Unable to check the project’s code style, because rustfmt could not be run."
|
||||
|
||||
if [ ! -t 1 ]; then
|
||||
# No input is possible
|
||||
echo "Performing commit."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "y: Install rustfmt via rustup"
|
||||
echo "n: Don't install rustfmt and perform the commit"
|
||||
echo "Q: Don't install rustfmt and abort the commit"
|
||||
|
||||
echo ""
|
||||
while true
|
||||
do
|
||||
echo -n "Install rustfmt via rustup? [y/n/Q]: "; read yn < /dev/tty
|
||||
case $yn in
|
||||
[Yy]* ) install_rustfmt; break;;
|
||||
[Nn]* ) echo "Performing commit."; exit 0;;
|
||||
[Qq]* | "" ) echo "Aborting commit."; exit -1 >/dev/null 2>&1;;
|
||||
* ) echo "Invalid input";;
|
||||
esac
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
echo "--Checking style--"
|
||||
cargo fmt --all -- --check
|
||||
if test $? != 0; then
|
||||
echo "--Checking style fail--"
|
||||
echo "Please fix the above issues, either manually or by running: cargo fmt --all"
|
||||
|
||||
exit -1
|
||||
else
|
||||
echo "--Checking style pass--"
|
||||
fi
|
14
launch.sh
14
launch.sh
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Script to generate mo files in a temp locale folder
|
||||
# Use it only for testing purpose
|
||||
|
||||
rm -rf locale
|
||||
mkdir locale
|
||||
cd po
|
||||
for lang in $(ls *.po); do
|
||||
lang=${lang::-3}
|
||||
mkdir -p ../locale/${lang//_/-}/LC_MESSAGES
|
||||
msgfmt -c -o ../locale/${lang//_/-}/LC_MESSAGES/cachyos-hello.mo $lang.po
|
||||
done
|
||||
cd ..
|
||||
./build/cachyos-hello --dev
|
141
meson.build
141
meson.build
|
@ -1,95 +1,82 @@
|
|||
project('cachyos-hello', 'cpp',
|
||||
version: '0.6.10',
|
||||
project('cachyos-hello', 'rust',
|
||||
version: '0.7.0',
|
||||
license: 'GPLv3',
|
||||
meson_version: '>=0.55.0',
|
||||
default_options: ['cpp_std=c++20',
|
||||
'buildtype=debugoptimized',
|
||||
meson_version: '>=0.56.0',
|
||||
default_options: ['buildtype=debugoptimized',
|
||||
'warning_level=3',
|
||||
'werror=true',
|
||||
'b_ndebug=if-release'])
|
||||
|
||||
cc = meson.get_compiler('cpp')
|
||||
i18n = import('i18n')
|
||||
gnome = import('gnome')
|
||||
|
||||
# Common dependencies
|
||||
fmt = dependency('fmt', version : ['>=8.0.0'], fallback : ['fmt', 'fmt_dep'])
|
||||
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
|
||||
base_id = 'org.cachyos.hello'
|
||||
|
||||
src_files = files(
|
||||
'src/hello.cpp', 'src/hello.hpp',
|
||||
'src/main.cpp',
|
||||
dependency('glib-2.0', version: '>= 2.66')
|
||||
dependency('gio-2.0', version: '>= 2.66')
|
||||
dependency('gtk+-3.0', version: '>= 3.24.34')
|
||||
|
||||
glib_compile_resources = find_program('glib-compile-resources', required: true)
|
||||
glib_compile_schemas = find_program('glib-compile-schemas', required: true)
|
||||
desktop_file_validate = find_program('desktop-file-validate', required: false)
|
||||
appstream_util = find_program('appstream-util', required: false)
|
||||
cargo = find_program('cargo', required: true)
|
||||
cargo_script = find_program('build-aux/cargo.py')
|
||||
|
||||
version = meson.project_version()
|
||||
version_array = version.split('.')
|
||||
major_version = version_array[0].to_int()
|
||||
minor_version = version_array[1].to_int()
|
||||
version_micro = version_array[2].to_int()
|
||||
|
||||
prefix = get_option('prefix')
|
||||
bindir = prefix / get_option('bindir')
|
||||
localedir = prefix / get_option('localedir')
|
||||
|
||||
datadir = prefix / get_option('datadir')
|
||||
pkgdatadir = datadir / meson.project_name()
|
||||
iconsdir = datadir / 'icons'
|
||||
podir = meson.project_source_root() / 'po'
|
||||
gettext_package = meson.project_name()
|
||||
|
||||
if get_option('profile') == 'development'
|
||||
profile = 'Devel'
|
||||
vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
|
||||
if vcs_tag == ''
|
||||
version_suffix = '-devel'
|
||||
else
|
||||
version_suffix = '-@0@'.format(vcs_tag)
|
||||
endif
|
||||
application_id = '@0@.@1@'.format(base_id, profile)
|
||||
else
|
||||
profile = ''
|
||||
version_suffix = ''
|
||||
application_id = base_id
|
||||
endif
|
||||
|
||||
meson.add_dist_script(
|
||||
'build-aux/dist-vendor.sh',
|
||||
meson.project_build_root() / 'meson-dist' / meson.project_name() + '-' + version,
|
||||
meson.project_source_root()
|
||||
)
|
||||
|
||||
possible_cc_flags = [
|
||||
'-Wshadow',
|
||||
|
||||
'-Wnon-virtual-dtor',
|
||||
|
||||
'-Wcast-align',
|
||||
'-Wunused',
|
||||
'-Woverloaded-virtual',
|
||||
|
||||
'-Wpedantic', # non-standard C++
|
||||
'-Wconversion', # type conversion that may lose data
|
||||
'-Wnull-dereference',
|
||||
'-Wdouble-promotion', # float to double
|
||||
|
||||
'-Wformat=2',
|
||||
]
|
||||
|
||||
if cc.get_id() == 'gcc'
|
||||
possible_cc_flags += [
|
||||
'-Wmisleading-indentation',
|
||||
|
||||
'-Wduplicated-cond',
|
||||
'-Wduplicated-branches',
|
||||
'-Wlogical-op',
|
||||
]
|
||||
if get_option('profile') == 'development'
|
||||
# Setup pre-commit hook for ensuring coding style is always consistent
|
||||
message('Setting up git pre-commit hook..')
|
||||
run_command('cp', '-f', 'hooks/pre-commit.hook', '.git/hooks/pre-commit')
|
||||
endif
|
||||
|
||||
if get_option('buildtype') != 'debug'
|
||||
if cc.get_id() == 'gcc'
|
||||
possible_cc_flags += [
|
||||
'-flto',
|
||||
'-fwhole-program',
|
||||
]
|
||||
else
|
||||
possible_cc_flags += [
|
||||
'-flto=thin',
|
||||
]
|
||||
endif
|
||||
endif
|
||||
cargo_sources = files(
|
||||
'Cargo.toml',
|
||||
'Cargo.lock',
|
||||
)
|
||||
|
||||
add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'cpp')
|
||||
|
||||
executable(
|
||||
'cachyos-hello',
|
||||
src_files,
|
||||
dependencies: [fmt, gtkmm],
|
||||
include_directories: [include_directories('src')],
|
||||
install: true)
|
||||
subdir('po')
|
||||
subdir('src')
|
||||
|
||||
install_data (
|
||||
meson.project_name () + '.desktop',
|
||||
install_dir: join_paths(get_option('datadir'), 'applications')
|
||||
)
|
||||
|
||||
meson.add_install_script('postinstall.sh')
|
||||
|
||||
summary(
|
||||
{
|
||||
'Build type': get_option('buildtype'),
|
||||
},
|
||||
bool_yn: true
|
||||
)
|
||||
|
||||
clangtidy = find_program('clang-tidy', required: false)
|
||||
|
||||
if clangtidy.found()
|
||||
run_target(
|
||||
'tidy',
|
||||
command: [
|
||||
clangtidy,
|
||||
'-checks=*,-fuchsia-default-arguments',
|
||||
'-p', meson.build_root()
|
||||
] + src_files)
|
||||
endif
|
||||
#meson.add_install_script('postinstall.sh')
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
option(
|
||||
'profile',
|
||||
type: 'combo',
|
||||
choices: [
|
||||
'default',
|
||||
'development'
|
||||
],
|
||||
value: 'default',
|
||||
description: 'The build profile for Kooha. One of "default" or "development".'
|
||||
)
|
|
@ -0,0 +1,66 @@
|
|||
am
|
||||
am_ET
|
||||
ar
|
||||
ast_ES
|
||||
az
|
||||
be
|
||||
bg
|
||||
bn
|
||||
ca
|
||||
ca@valencia
|
||||
ca_ES
|
||||
cs
|
||||
da
|
||||
de
|
||||
el_GR
|
||||
eo
|
||||
es
|
||||
es_AR
|
||||
et
|
||||
fa
|
||||
fa_IR
|
||||
fi
|
||||
fi_FI
|
||||
fr
|
||||
he
|
||||
hi
|
||||
hi_IN
|
||||
hr
|
||||
hu
|
||||
id_ID
|
||||
is
|
||||
it
|
||||
ja
|
||||
ka
|
||||
kn
|
||||
ko_KR
|
||||
ku
|
||||
lt
|
||||
mk
|
||||
ml
|
||||
nb
|
||||
ne
|
||||
nl
|
||||
pl
|
||||
pt_BR
|
||||
pt_PT
|
||||
ro_RO
|
||||
ru
|
||||
sk
|
||||
sl
|
||||
sl_SI
|
||||
sq
|
||||
sr
|
||||
sr_RS
|
||||
sv
|
||||
th
|
||||
ti
|
||||
tk
|
||||
tr
|
||||
uk
|
||||
uk_UA
|
||||
ur
|
||||
vi_VN
|
||||
zh
|
||||
zh_CN
|
||||
zh_TW
|
|
@ -0,0 +1 @@
|
|||
i18n.gettext(gettext_package, preset: 'glib')
|
|
@ -0,0 +1,16 @@
|
|||
edition = "2021"
|
||||
format_code_in_doc_comments = true
|
||||
match_block_trailing_comma = true
|
||||
condense_wildcard_suffixes = true
|
||||
use_field_init_shorthand = true
|
||||
normalize_doc_attributes = true
|
||||
overflow_delimited_expr = true
|
||||
imports_granularity = "Module"
|
||||
use_small_heuristics = "Max"
|
||||
normalize_comments = true
|
||||
reorder_impl_items = true
|
||||
use_try_shorthand = true
|
||||
newline_style = "Unix"
|
||||
format_strings = true
|
||||
wrap_comments = true
|
||||
comment_width = 100
|
|
@ -0,0 +1,112 @@
|
|||
use gettextrs::gettext;
|
||||
use gtk::gio;
|
||||
use gtk::glib::{self, clone, WeakRef};
|
||||
use gtk::prelude::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use crate::config::{APP_ID, PKGDATADIR, VERSION};
|
||||
use crate::widgets::MainWindow;
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Application {
|
||||
pub window: OnceCell<WeakRef<MainWindow>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for Application {
|
||||
type Type = super::Application;
|
||||
|
||||
const NAME: &'static str = "CachyOSHello";
|
||||
}
|
||||
|
||||
impl ObjectImpl for Application {}
|
||||
|
||||
impl ApplicationImpl for Application {
|
||||
fn activate(&self, app: &Self::Type) {
|
||||
if let Some(window) = self.window.get() {
|
||||
let window = window.upgrade().unwrap();
|
||||
window.show();
|
||||
window.present();
|
||||
return;
|
||||
}
|
||||
|
||||
let window = MainWindow::new(app);
|
||||
self.window.set(window.downgrade()).expect("Window already set.");
|
||||
|
||||
app.main_window().present();
|
||||
}
|
||||
|
||||
fn startup(&self, app: &Self::Type) {
|
||||
self.parent_startup(app);
|
||||
gtk::Window::set_default_icon_name(APP_ID);
|
||||
}
|
||||
}
|
||||
|
||||
impl GtkApplicationImpl for Application {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct Application(ObjectSubclass<imp::Application>)
|
||||
@extends gio::Application, gtk::Application,
|
||||
@implements gio::ActionMap, gio::ActionGroup;
|
||||
}
|
||||
|
||||
impl Application {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::new(&[
|
||||
("application-id", &Some(APP_ID)),
|
||||
("flags", &gio::ApplicationFlags::empty()),
|
||||
])
|
||||
.expect("Failed to create Application.")
|
||||
}
|
||||
|
||||
fn private(&self) -> &imp::Application {
|
||||
imp::Application::from_instance(self)
|
||||
}
|
||||
|
||||
fn show_about_dialog(&self) {
|
||||
let dialog = gtk::AboutDialog::builder()
|
||||
.transient_for(&self.main_window())
|
||||
.modal(true)
|
||||
.program_name(&gettext("Kooha"))
|
||||
.comments(&gettext("Elegantly record your screen"))
|
||||
.version(VERSION)
|
||||
.logo_icon_name(APP_ID)
|
||||
.authors(vec![
|
||||
"Dave Patrick".into(),
|
||||
"".into(),
|
||||
"Mathiascode".into(),
|
||||
"Felix Weilbach".into(),
|
||||
])
|
||||
// Translators: Replace "translator-credits" with your names. Put a comma between.
|
||||
.translator_credits(&gettext("translator-credits"))
|
||||
.copyright(&gettext("Copyright 2021 Dave Patrick"))
|
||||
.license_type(gtk::License::Gpl30)
|
||||
.website("https://github.com/SeaDve/Kooha")
|
||||
.website_label(&gettext("GitHub"))
|
||||
.build();
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
pub fn main_window(&self) -> MainWindow {
|
||||
let imp = self.private();
|
||||
imp.window.get().unwrap().upgrade().unwrap()
|
||||
}
|
||||
|
||||
pub fn run(&self) {
|
||||
ApplicationExtManual::run(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Application {
|
||||
fn default() -> Self {
|
||||
gio::Application::default().unwrap().downcast().unwrap()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
pub const APP_ID: &str = @APP_ID@;
|
||||
pub const GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@;
|
||||
pub const LOCALEDIR: &str = @LOCALEDIR@;
|
||||
pub const PKGDATADIR: &str = @PKGDATADIR@;
|
||||
pub const PROFILE: &str = @PROFILE@;
|
||||
pub const VERSION: &str = @VERSION@;
|
|
@ -0,0 +1,26 @@
|
|||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct HelloWindow {
|
||||
pub builder: gtk::Builder,
|
||||
pub window: gtk::Window,
|
||||
pub preferences: serde_json::Value,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct SystemdUnits {
|
||||
pub loaded_units: Vec<String>,
|
||||
pub enabled_units: Vec<String>,
|
||||
}
|
||||
|
||||
impl SystemdUnits {
|
||||
pub fn new() -> Self {
|
||||
Self { loaded_units: Vec::new(), enabled_units: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SystemdUnits {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
733
src/hello.cpp
733
src/hello.cpp
|
@ -1,733 +0,0 @@
|
|||
#include "hello.hpp"
|
||||
#include "helper.hpp"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <libintl.h>
|
||||
|
||||
#include <algorithm> // for transform
|
||||
#include <filesystem> // for exists, is_directory
|
||||
#include <iostream> // for basic_istream, cin
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map> // for unordered_map
|
||||
|
||||
#include <fmt/core.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
|
||||
#include <range/v3/algorithm/reverse.hpp>
|
||||
#include <range/v3/algorithm/find.hpp>
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
#else
|
||||
#include <ranges>
|
||||
namespace ranges = std::ranges;
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace {
|
||||
Hello* g_refHello;
|
||||
|
||||
std::string fix_path(std::string&& path) noexcept {
|
||||
if (path[0] != '~') {
|
||||
return path;
|
||||
}
|
||||
replace_all(path, "~", Glib::get_home_dir().c_str());
|
||||
return path;
|
||||
}
|
||||
|
||||
nlohmann::json read_json(const std::string_view& path) {
|
||||
const auto& buf = fix_path(path.data());
|
||||
if (!fs::exists(buf)) {
|
||||
throw std::runtime_error(fmt::format("File does not exist: \"{}\"", buf));
|
||||
}
|
||||
// read a JSON file
|
||||
std::ifstream i(buf);
|
||||
nlohmann::json j;
|
||||
i >> j;
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
void write_json(const std::string_view& path, const nlohmann::json& content) {
|
||||
// write data to JSON file
|
||||
std::ofstream o(fix_path(path.data()));
|
||||
o << content << '\n';
|
||||
}
|
||||
|
||||
// Read information from the lsb-release file.
|
||||
//
|
||||
// @Returns args from lsb-release file
|
||||
std::array<std::string, 2> get_lsb_infos() {
|
||||
std::unordered_map<std::string, std::string> lsb{};
|
||||
|
||||
try {
|
||||
std::ifstream lsb_release("/etc/lsb-release");
|
||||
std::string line;
|
||||
while (std::getline(lsb_release, line)) {
|
||||
if (line.find('=') != std::string::npos) {
|
||||
auto var = tokenize(line, "=");
|
||||
remove_all(var.first, "DISTRIB_");
|
||||
remove_all(var.second, "\"");
|
||||
lsb[var.first] = var.second;
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
return {"not CachyOS", "0.0"};
|
||||
}
|
||||
return {lsb["ID"], lsb["RELEASE"]};
|
||||
}
|
||||
|
||||
void child_watch_cb(GPid pid, [[maybe_unused]] gint status, gpointer /*user_data*/) {
|
||||
#if !defined(NDEBUG)
|
||||
g_message("Child %" G_PID_FORMAT " exited %s", pid,
|
||||
g_spawn_check_wait_status(status, nullptr) ? "normally" : "abnormally");
|
||||
#endif
|
||||
|
||||
// Free any resources associated with the child here, such as I/O channels
|
||||
// on its stdout and stderr FDs. If you have no code to put in the
|
||||
// child_watch_cb() callback, you can remove it and the g_child_watch_add()
|
||||
// call, but you must also remove the G_SPAWN_DO_NOT_REAP_CHILD flag,
|
||||
// otherwise the child process will stay around as a zombie until this
|
||||
// process exits.
|
||||
|
||||
g_spawn_close_pid(pid);
|
||||
}
|
||||
|
||||
void quick_message(Gtk::Window* parent, const std::string& message) {
|
||||
// Create the widgets
|
||||
const auto& flags = static_cast<GtkDialogFlags>(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT);
|
||||
auto* dialog = gtk_dialog_new_with_buttons(message.c_str(),
|
||||
parent->gobj(),
|
||||
flags,
|
||||
_("_Offline"),
|
||||
GTK_RESPONSE_NO,
|
||||
_("_Online"),
|
||||
GTK_RESPONSE_YES,
|
||||
nullptr);
|
||||
auto* content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
auto* label = gtk_label_new(message.c_str());
|
||||
|
||||
// Add the label, and show everything we’ve added
|
||||
gtk_container_add(GTK_CONTAINER(content_area), label);
|
||||
gtk_widget_show_all(dialog);
|
||||
|
||||
int result = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
std::vector<std::string> argv{};
|
||||
if (result == GTK_RESPONSE_NO) {
|
||||
argv = {fix_path("/usr/local/bin/calamares-offline.sh")};
|
||||
} else if (result == GTK_RESPONSE_YES) {
|
||||
argv = {fix_path("/usr/local/bin/calamares-online.sh")};
|
||||
} else {
|
||||
gtk_widget_destroy(dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
int child_stdout{};
|
||||
int child_stderr{};
|
||||
Glib::Pid child_pid;
|
||||
|
||||
// Spawn child process.
|
||||
try {
|
||||
Glib::spawn_async_with_pipes(".", argv, Glib::SpawnFlags::SPAWN_DO_NOT_REAP_CHILD, Glib::SlotSpawnChildSetup(), &child_pid, nullptr, &child_stdout, &child_stderr);
|
||||
} catch (Glib::Error& error) {
|
||||
g_critical("%s", error.what().c_str());
|
||||
}
|
||||
// Add a child watch function which will be called when the child process
|
||||
// exits.
|
||||
g_child_watch_add(child_pid, child_watch_cb, nullptr);
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
}
|
||||
|
||||
namespace utils {
|
||||
std::string exec(const std::string_view& command, const bool& interactive = false) noexcept {
|
||||
if (interactive) {
|
||||
const auto& ret_code = system(command.data());
|
||||
return std::to_string(ret_code);
|
||||
}
|
||||
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(command.data(), "r"), pclose);
|
||||
|
||||
if (!pipe) {
|
||||
return "-1";
|
||||
}
|
||||
|
||||
std::string result{};
|
||||
std::array<char, 128> buffer{};
|
||||
while (!feof(pipe.get())) {
|
||||
if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
}
|
||||
|
||||
if (result.ends_with('\n')) {
|
||||
result.pop_back();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto make_multiline(const std::string_view& str, bool reverse, const std::string_view&& delim) noexcept -> std::vector<std::string> {
|
||||
std::vector<std::string> lines{};
|
||||
|
||||
size_t previous = 0;
|
||||
size_t current = str.find(delim);
|
||||
|
||||
while (current != std::string_view::npos) {
|
||||
lines.emplace_back(str.substr(previous, current - previous));
|
||||
previous = current + delim.size();
|
||||
current = str.find(delim, previous);
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
ranges::reverse(lines);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void on_servbtn_clicked(GtkWidget* widget) noexcept {
|
||||
auto *btn = Glib::wrap(GTK_CHECK_BUTTON(widget));
|
||||
|
||||
const std::string action_type = reinterpret_cast<const char*>(btn->get_data("actionType"));
|
||||
const std::string action_data = reinterpret_cast<const char*>(btn->get_data("actionData"));
|
||||
|
||||
std::string user_only;
|
||||
std::string pkexec_only;
|
||||
if (action_type == "user_service") {
|
||||
user_only = "--user";
|
||||
pkexec_only = "--user $(logname)";
|
||||
}
|
||||
|
||||
std::string cmd{};
|
||||
if (ranges::find(g_refHello->get_enabled_units(), action_data) != g_refHello->get_enabled_units().end()) {
|
||||
cmd = fmt::format("/sbin/pkexec {} bash -c \"systemctl {} enable --now --force {}\"", pkexec_only, user_only, action_data);
|
||||
} else {
|
||||
cmd = fmt::format("/sbin/pkexec {} bash -c \"systemctl {} disable --now {}\"", pkexec_only, user_only, action_data);
|
||||
}
|
||||
Glib::spawn_command_line_sync(cmd);
|
||||
|
||||
if (action_type == "user_service") {
|
||||
g_refHello->load_global_enabled_units();
|
||||
} else {
|
||||
g_refHello->load_enabled_units();
|
||||
}
|
||||
}
|
||||
|
||||
void on_appbtn_clicked(GtkWidget* widget) noexcept {
|
||||
const std::string_view& name = gtk_button_get_label(GTK_BUTTON(widget));
|
||||
std::string binname{};
|
||||
bool is_sudo{};
|
||||
if (name == "CachyOS PackageInstaller") {
|
||||
binname = "cachyos-pi-bin";
|
||||
is_sudo = true;
|
||||
} else if (name == "CachyOS Kernel Manager") {
|
||||
binname = "cachyos-kernel-manager";
|
||||
is_sudo = false;
|
||||
}
|
||||
const auto& status_code = system(fmt::format("which {}", binname).c_str());
|
||||
if (status_code != 0) {
|
||||
return;
|
||||
}
|
||||
int child_stdout{};
|
||||
int child_stderr{};
|
||||
Glib::Pid child_pid;
|
||||
|
||||
std::string envs;
|
||||
for (const auto& env : Glib::listenv()) {
|
||||
if (env == "PATH") {
|
||||
envs += "PATH=/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin ";
|
||||
continue;
|
||||
}
|
||||
envs += fmt::format("{}={} ", env, Glib::getenv(env));
|
||||
}
|
||||
|
||||
// Spawn child process.
|
||||
try {
|
||||
const auto& exe_path = utils::exec(fmt::format("which {}", binname));
|
||||
std::vector<std::string> argv{exe_path};
|
||||
if (is_sudo) {
|
||||
argv = {"/sbin/pkexec", "bash", "-c", fmt::format("{} {}", envs, exe_path)};
|
||||
}
|
||||
Glib::spawn_async_with_pipes(".", argv, Glib::SpawnFlags::SPAWN_DO_NOT_REAP_CHILD, Glib::SlotSpawnChildSetup(), &child_pid, nullptr, &child_stdout, &child_stderr);
|
||||
} catch (Glib::Error& error) {
|
||||
g_critical("%s", error.what().c_str());
|
||||
}
|
||||
// Add a child watch function which will be called when the child process
|
||||
// exits.
|
||||
g_child_watch_add(child_pid, child_watch_cb, nullptr);
|
||||
}
|
||||
|
||||
Gtk::Box* create_options_section() {
|
||||
Gtk::Box* topbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 2));
|
||||
Gtk::Box* box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 10));
|
||||
Gtk::Label* label = Gtk::manage(new Gtk::Label());
|
||||
label->set_line_wrap(true);
|
||||
label->set_justify(Gtk::JUSTIFY_CENTER);
|
||||
label->set_text("Tweaks");
|
||||
|
||||
Gtk::CheckButton* psd_btn = Gtk::manage(new Gtk::CheckButton("Profile-sync-daemon enabled"));
|
||||
Gtk::CheckButton* systemd_oomd_btn = Gtk::manage(new Gtk::CheckButton("Systemd-oomd enabled"));
|
||||
Gtk::CheckButton* apparmor_btn = Gtk::manage(new Gtk::CheckButton("Apparmor enabled"));
|
||||
Gtk::CheckButton* ananicy_cpp_btn = Gtk::manage(new Gtk::CheckButton("Ananicy Cpp enabled"));
|
||||
|
||||
psd_btn->set_data("actionData", reinterpret_cast<void*>(const_cast<char*>("psd.service")));
|
||||
psd_btn->set_data("actionType", reinterpret_cast<void*>(const_cast<char*>("user_service")));
|
||||
systemd_oomd_btn->set_data("actionData", reinterpret_cast<void*>(const_cast<char*>("systemd-oomd.service")));
|
||||
systemd_oomd_btn->set_data("actionType", reinterpret_cast<void*>(const_cast<char*>("service")));
|
||||
apparmor_btn->set_data("actionData", reinterpret_cast<void*>(const_cast<char*>("apparmor.service")));
|
||||
apparmor_btn->set_data("actionType", reinterpret_cast<void*>(const_cast<char*>("service")));
|
||||
ananicy_cpp_btn->set_data("actionData", reinterpret_cast<void*>(const_cast<char*>("ananicy-cpp.service")));
|
||||
ananicy_cpp_btn->set_data("actionType", reinterpret_cast<void*>(const_cast<char*>("service")));
|
||||
|
||||
for (auto& btn : {psd_btn, systemd_oomd_btn, apparmor_btn, ananicy_cpp_btn}) {
|
||||
const std::string data = reinterpret_cast<const char*>(btn->get_data("actionData"));
|
||||
if ((ranges::find(g_refHello->get_enabled_units(), data) != g_refHello->get_enabled_units().end()) ||
|
||||
(ranges::find(g_refHello->get_global_enabled_units(), data) != g_refHello->get_global_enabled_units().end())) {
|
||||
btn->set_active(true);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_connect(GTK_WIDGET(psd_btn->gobj()), "clicked", G_CALLBACK(&on_servbtn_clicked), nullptr);
|
||||
g_signal_connect(GTK_WIDGET(systemd_oomd_btn->gobj()), "clicked", G_CALLBACK(&on_servbtn_clicked), nullptr);
|
||||
g_signal_connect(GTK_WIDGET(apparmor_btn->gobj()), "clicked", G_CALLBACK(&on_servbtn_clicked), nullptr);
|
||||
g_signal_connect(GTK_WIDGET(ananicy_cpp_btn->gobj()), "clicked", G_CALLBACK(&on_servbtn_clicked), nullptr);
|
||||
|
||||
topbox->pack_start(*label, true, false, 1);
|
||||
box->pack_start(*psd_btn, true, false, 2);
|
||||
box->pack_start(*systemd_oomd_btn, true, false, 2);
|
||||
box->pack_start(*apparmor_btn, true, false, 2);
|
||||
box->pack_start(*ananicy_cpp_btn, true, false, 2);
|
||||
box->set_halign(Gtk::ALIGN_FILL);
|
||||
topbox->pack_start(*box, true, false, 1);
|
||||
|
||||
topbox->set_hexpand();
|
||||
|
||||
return topbox;
|
||||
}
|
||||
|
||||
Gtk::Box* create_apps_section() {
|
||||
Gtk::Box* topbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 2));
|
||||
Gtk::Box* box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 10));
|
||||
Gtk::Label* label = Gtk::manage(new Gtk::Label());
|
||||
label->set_line_wrap(true);
|
||||
label->set_justify(Gtk::JUSTIFY_CENTER);
|
||||
label->set_text("Applications");
|
||||
|
||||
Gtk::Button* cachyos_pi = Gtk::manage(new Gtk::Button("CachyOS PackageInstaller"));
|
||||
Gtk::Button* cachyos_km = Gtk::manage(new Gtk::Button("CachyOS Kernel Manager"));
|
||||
|
||||
g_signal_connect(GTK_WIDGET(cachyos_pi->gobj()), "clicked", G_CALLBACK(&on_appbtn_clicked), nullptr);
|
||||
g_signal_connect(GTK_WIDGET(cachyos_km->gobj()), "clicked", G_CALLBACK(&on_appbtn_clicked), nullptr);
|
||||
|
||||
box->pack_start(*cachyos_pi, true, true, 2);
|
||||
box->pack_start(*cachyos_km, true, true, 2);
|
||||
|
||||
topbox->pack_start(*label, true, true, 2);
|
||||
|
||||
box->set_halign(Gtk::ALIGN_FILL);
|
||||
topbox->pack_start(*box, true, true);
|
||||
|
||||
topbox->set_hexpand();
|
||||
|
||||
return topbox;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Hello::Hello(int argc, char** argv) {
|
||||
set_title("CachyOS Hello");
|
||||
set_border_width(6);
|
||||
if (argc > 1 && (strncmp(argv[1], "--dev", 5) == 0)) {
|
||||
m_dev = true;
|
||||
}
|
||||
|
||||
g_refHello = this;
|
||||
|
||||
auto screen = Gdk::Screen::get_default();
|
||||
|
||||
// Load preferences
|
||||
if (m_dev) {
|
||||
m_preferences = read_json("data/preferences.json");
|
||||
m_preferences["data_path"] = "data/";
|
||||
m_preferences["desktop_path"] = fmt::format("{}/{}.desktop", fs::current_path().string(), m_app);
|
||||
m_preferences["locale_path"] = "locale/";
|
||||
m_preferences["ui_path"] = fmt::format("ui/{}.glade", m_app);
|
||||
m_preferences["style_path"] = "ui/style.css";
|
||||
} else {
|
||||
m_preferences = read_json(fmt::format("/usr/share/{}/data/preferences.json", m_app));
|
||||
}
|
||||
|
||||
// Get saved infos
|
||||
const auto& save_path = fix_path(m_preferences["save_path"]);
|
||||
m_save = (!fs::exists(save_path)) ? nlohmann::json({{"locale", ""}}) : read_json(save_path);
|
||||
|
||||
// Import Css
|
||||
auto provider = Gtk::CssProvider::create();
|
||||
provider->load_from_path(m_preferences["style_path"]);
|
||||
Gtk::StyleContext::add_provider_for_screen(screen, provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
// Init window
|
||||
m_builder = Gtk::Builder::create_from_file(m_preferences["ui_path"]);
|
||||
gtk_builder_add_callback_symbol(m_builder->gobj(), "on_languages_changed", G_CALLBACK(on_languages_changed));
|
||||
gtk_builder_add_callback_symbol(m_builder->gobj(), "on_action_clicked", G_CALLBACK(on_action_clicked));
|
||||
gtk_builder_add_callback_symbol(m_builder->gobj(), "on_btn_clicked", G_CALLBACK(on_btn_clicked));
|
||||
gtk_builder_add_callback_symbol(m_builder->gobj(), "on_link_clicked", G_CALLBACK(on_link_clicked));
|
||||
gtk_builder_add_callback_symbol(m_builder->gobj(), "on_delete_window", G_CALLBACK(on_delete_window));
|
||||
gtk_builder_connect_signals(m_builder->gobj(), nullptr);
|
||||
Gtk::Window* ref_window;
|
||||
m_builder->get_widget("window", ref_window);
|
||||
gobject_ = reinterpret_cast<GObject*>(ref_window->gobj());
|
||||
|
||||
// Subtitle of headerbar
|
||||
Gtk::HeaderBar* header;
|
||||
m_builder->get_widget("headerbar", header);
|
||||
const auto& lsb_info = get_lsb_infos();
|
||||
header->set_subtitle(lsb_info[0] + " " + lsb_info[1]);
|
||||
|
||||
// Load images
|
||||
if (fs::is_regular_file(m_preferences["logo_path"])) {
|
||||
const auto& logo = Gdk::Pixbuf::create_from_file(m_preferences["logo_path"]);
|
||||
set_icon(logo);
|
||||
|
||||
Gtk::Image* image;
|
||||
m_builder->get_widget("distriblogo", image);
|
||||
image->set(logo);
|
||||
|
||||
Gtk::AboutDialog* dialog;
|
||||
m_builder->get_widget("aboutdialog", dialog);
|
||||
dialog->set_logo(logo);
|
||||
}
|
||||
|
||||
Gtk::Box* social_box;
|
||||
m_builder->get_widget("social", social_box);
|
||||
for (const auto& btn : social_box->get_children()) {
|
||||
const auto& name = btn->get_name();
|
||||
const auto& icon_path = fmt::format("{}img/{}.png", m_preferences["data_path"], name.c_str());
|
||||
Gtk::Image* image;
|
||||
m_builder->get_widget(name, image);
|
||||
image->set(icon_path);
|
||||
}
|
||||
|
||||
Gtk::Grid* homepage_grid;
|
||||
m_builder->get_widget("homepage", homepage_grid);
|
||||
for (const auto& widget : homepage_grid->get_children()) {
|
||||
if (!G_TYPE_CHECK_INSTANCE_TYPE(widget->gobj(), GTK_TYPE_BUTTON)) {
|
||||
continue;
|
||||
}
|
||||
const auto& casted_widget = Glib::wrap(GTK_BUTTON(widget->gobj()));
|
||||
if (gtk_button_get_image_position(casted_widget->gobj()) != GtkPositionType::GTK_POS_RIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& image_path = fmt::format("{}img/external-link.png", m_preferences["data_path"]);
|
||||
Gtk::Image image;
|
||||
image.set(image_path);
|
||||
image.set_margin_start(2);
|
||||
casted_widget->set_image(image);
|
||||
}
|
||||
|
||||
// Create pages
|
||||
m_pages = fmt::format("{}pages/{}", m_preferences["data_path"], m_preferences["default_locale"]);
|
||||
|
||||
for (const auto& page : fs::directory_iterator(m_pages)) {
|
||||
auto* scrolled_window = gtk_scrolled_window_new(nullptr, nullptr);
|
||||
auto* viewport = gtk_viewport_new(nullptr, nullptr);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(viewport), 10);
|
||||
auto* label = gtk_label_new(nullptr);
|
||||
gtk_label_set_line_wrap(GTK_LABEL(label), true);
|
||||
auto* image = gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_BUTTON);
|
||||
auto* backBtn = gtk_button_new();
|
||||
gtk_button_set_image(GTK_BUTTON(backBtn), image);
|
||||
gtk_widget_set_name(backBtn, "home");
|
||||
g_signal_connect(backBtn, "clicked", G_CALLBACK(&on_btn_clicked), nullptr);
|
||||
|
||||
auto* grid = GTK_GRID(gtk_grid_new());
|
||||
gtk_grid_attach(grid, backBtn, 0, 1, 1, 1);
|
||||
gtk_grid_attach(grid, label, 1, 2, 1, 1);
|
||||
gtk_container_add(GTK_CONTAINER(viewport), GTK_WIDGET(grid));
|
||||
gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(viewport));
|
||||
gtk_widget_show_all(scrolled_window);
|
||||
|
||||
Glib::RefPtr<Glib::Object> stack = m_builder->get_object("stack");
|
||||
const auto& child_name = page.path().filename().string() + "page";
|
||||
gtk_stack_add_named(GTK_STACK(stack->gobj()), scrolled_window, child_name.c_str());
|
||||
}
|
||||
|
||||
// Init translation
|
||||
const std::string& locale_path = m_preferences["locale_path"];
|
||||
bindtextdomain(m_app, locale_path.c_str());
|
||||
bind_textdomain_codeset(m_app, "UTF-8");
|
||||
textdomain(m_app);
|
||||
Gtk::ComboBoxText* languages;
|
||||
m_builder->get_widget("languages", languages);
|
||||
languages->set_active_id(get_best_locale());
|
||||
|
||||
// Set autostart switcher state
|
||||
m_autostart = fs::exists(fix_path(m_preferences["autostart_path"]));
|
||||
Gtk::Switch* autostart_switch;
|
||||
m_builder->get_widget("autostart", autostart_switch);
|
||||
autostart_switch->set_active(m_autostart);
|
||||
|
||||
// Live systems
|
||||
if (fs::exists(m_preferences["live_path"]) && fs::is_regular_file(m_preferences["installer_path"])) {
|
||||
Gtk::Label* installlabel;
|
||||
m_builder->get_widget("installlabel", installlabel);
|
||||
installlabel->set_visible(true);
|
||||
Gtk::Button* install;
|
||||
m_builder->get_widget("install", install);
|
||||
install->set_visible(true);
|
||||
return;
|
||||
}
|
||||
Gtk::Button* install;
|
||||
m_builder->get_widget("appBrowser", install);
|
||||
install->set_visible(true);
|
||||
|
||||
load_enabled_units();
|
||||
load_global_enabled_units();
|
||||
|
||||
auto* viewport = gtk_viewport_new(nullptr, nullptr);
|
||||
//auto* label = gtk_label_new(nullptr);
|
||||
//gtk_label_set_line_wrap(GTK_LABEL(label), true);
|
||||
auto* image = gtk_image_new_from_icon_name("go-previous", GTK_ICON_SIZE_BUTTON);
|
||||
auto* backBtn = gtk_button_new();
|
||||
gtk_button_set_image(GTK_BUTTON(backBtn), image);
|
||||
gtk_widget_set_name(backBtn, "home");
|
||||
g_signal_connect(backBtn, "clicked", G_CALLBACK(&on_btn_clicked), nullptr);
|
||||
|
||||
auto* options_section_box = create_options_section();
|
||||
auto* apps_section_box = create_apps_section();
|
||||
|
||||
Gtk::Grid* grid = Gtk::manage(new Gtk::Grid());
|
||||
grid->set_hexpand();
|
||||
grid->set_margin_start(10);
|
||||
grid->set_margin_end(10);
|
||||
grid->set_margin_top(5);
|
||||
grid->set_margin_bottom(5);
|
||||
grid->attach(*Glib::wrap(backBtn), 0, 1, 1, 1);
|
||||
Gtk::Box* box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 5));
|
||||
|
||||
box->pack_start(*options_section_box, true, true, 5);
|
||||
box->pack_start(*apps_section_box, true, true, 5);
|
||||
|
||||
box->set_valign(Gtk::ALIGN_CENTER);
|
||||
box->set_halign(Gtk::ALIGN_CENTER);
|
||||
grid->attach(*box, 1, 2, 5, 1);
|
||||
gtk_container_add(GTK_CONTAINER(viewport), GTK_WIDGET(grid->gobj()));
|
||||
gtk_widget_show_all(viewport);
|
||||
|
||||
Glib::RefPtr<Glib::Object> stack = m_builder->get_object("stack");
|
||||
const std::string child_name = "appBrowserpage";
|
||||
gtk_stack_add_named(GTK_STACK(stack->gobj()), viewport, child_name.c_str());
|
||||
}
|
||||
|
||||
/// Returns the best locale, based on user's preferences.
|
||||
auto Hello::get_best_locale() const noexcept -> std::string {
|
||||
const auto& binary_path = fmt::format("{}{}{}.mo", m_preferences["locale_path"], "{}/LC_MESSAGES/", m_app);
|
||||
const auto& saved_locale = fmt::vformat(binary_path, fmt::make_format_args(m_save["locale"]));
|
||||
if (fs::is_regular_file(saved_locale)) {
|
||||
return m_save["locale"];
|
||||
} else if (m_save["locale"] == m_preferences["default_locale"]) {
|
||||
return m_preferences["default_locale"];
|
||||
}
|
||||
|
||||
const auto& locale_name = std::locale("").name();
|
||||
std::string sys_locale = locale_name.substr(0, locale_name.find('.'));
|
||||
const auto& user_locale = fmt::vformat(binary_path, fmt::make_format_args(sys_locale));
|
||||
const auto& two_letters = sys_locale.substr(0, 2);
|
||||
|
||||
// If user's locale is supported
|
||||
if (fs::is_regular_file(user_locale)) {
|
||||
if (sys_locale.find('_') != std::string::npos) {
|
||||
replace_all(sys_locale, "_", "-");
|
||||
}
|
||||
return sys_locale;
|
||||
}
|
||||
// If two first letters of user's locale is supported (ex: en_US -> en)
|
||||
else if (fs::is_regular_file(fmt::vformat(binary_path, fmt::make_format_args(two_letters)))) {
|
||||
return two_letters;
|
||||
}
|
||||
|
||||
return m_preferences["default_locale"];
|
||||
}
|
||||
|
||||
/// Sets locale of ui and pages.
|
||||
void Hello::set_locale(const std::string_view& use_locale) noexcept {
|
||||
#if !defined(NDEBUG)
|
||||
fmt::print(
|
||||
"┌{0:─^{2}}┐\n"
|
||||
"│{1: ^{2}}│\n"
|
||||
"└{0:─^{2}}┘\n",
|
||||
"", fmt::format("Locale changed to {}", use_locale), 40);
|
||||
#endif
|
||||
|
||||
textdomain(m_app);
|
||||
Glib::setenv("LANGUAGE", use_locale.data());
|
||||
|
||||
m_save["locale"] = use_locale;
|
||||
|
||||
// Real-time locale changing
|
||||
/* clang-format off */
|
||||
nlohmann::json elts = {
|
||||
{"comments", {"aboutdialog"}},
|
||||
{"label", {
|
||||
"autostartlabel",
|
||||
"development",
|
||||
"discover",
|
||||
"donate",
|
||||
"firstcategory",
|
||||
"forum",
|
||||
"install",
|
||||
"installlabel",
|
||||
"involved",
|
||||
"mailling",
|
||||
"readme",
|
||||
"release",
|
||||
"secondcategory",
|
||||
"thirdcategory",
|
||||
"welcomelabel",
|
||||
"welcometitle",
|
||||
"wiki"}
|
||||
},
|
||||
{"tooltip_text", {
|
||||
"about",
|
||||
"development",
|
||||
"discover",
|
||||
"donate",
|
||||
"forum",
|
||||
"mailling",
|
||||
"wiki"}
|
||||
}};
|
||||
/* clang-format on */
|
||||
|
||||
for (const auto& method : elts.items()) {
|
||||
if (!m_default_texts.contains(method.key())) {
|
||||
m_default_texts[method.key()] = {};
|
||||
}
|
||||
for (const auto& elt : elts[method.key()].items()) {
|
||||
const std::string& elt_value = elt.value();
|
||||
Gtk::Widget* item;
|
||||
m_builder->get_widget(elt_value, item);
|
||||
if (!m_default_texts[method.key()].contains(elt_value)) {
|
||||
gchar* item_buf;
|
||||
g_object_get(G_OBJECT(item->gobj()), method.key().c_str(), &item_buf, nullptr);
|
||||
m_default_texts[method.key()][elt_value] = item_buf;
|
||||
g_free(item_buf);
|
||||
}
|
||||
if (method.key() == "tooltip_text" || method.key() == "comments") {
|
||||
g_object_set(G_OBJECT(item->gobj()), method.key().c_str(), _(m_default_texts[method.key()][elt_value].get<std::string>().c_str()), nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change content of pages
|
||||
for (const auto& page : fs::directory_iterator(m_pages)) {
|
||||
Gtk::Stack* stack;
|
||||
m_builder->get_widget("stack", stack);
|
||||
const auto& child = stack->get_child_by_name((page.path().filename().string() + "page").c_str());
|
||||
if (child == nullptr) {
|
||||
fmt::print(stderr, "child not found\n");
|
||||
continue;
|
||||
}
|
||||
const auto& first_child = reinterpret_cast<Gtk::Container*>(child)->get_children();
|
||||
const auto& second_child = reinterpret_cast<Gtk::Container*>(first_child[0])->get_children();
|
||||
const auto& third_child = reinterpret_cast<Gtk::Container*>(second_child[0])->get_children();
|
||||
|
||||
const auto& label = reinterpret_cast<Gtk::Label*>(third_child[0]);
|
||||
label->set_markup(get_page(page.path().filename().string()));
|
||||
}
|
||||
}
|
||||
|
||||
void Hello::set_autostart(const bool& autostart) noexcept {
|
||||
fs::path autostart_path{fix_path(m_preferences["autostart_path"])};
|
||||
const auto& config_dir = autostart_path.parent_path();
|
||||
if (!fs::exists(config_dir)) {
|
||||
fs::create_directories(config_dir);
|
||||
}
|
||||
if (autostart && !fs::is_regular_file(autostart_path)) {
|
||||
fs::create_symlink(m_preferences["desktop_path"], autostart_path);
|
||||
} else if (!autostart && fs::is_regular_file(autostart_path)) {
|
||||
fs::remove(autostart_path);
|
||||
}
|
||||
m_autostart = autostart;
|
||||
}
|
||||
|
||||
auto Hello::get_page(const std::string& name) const noexcept -> std::string {
|
||||
auto filename = fmt::format("{}pages/{}/{}", m_preferences["data_path"], m_save["locale"], name);
|
||||
if (!fs::is_regular_file(filename)) {
|
||||
filename = fmt::format("{}pages/{}/{}", m_preferences["data_path"], m_preferences["default_locale"], name);
|
||||
}
|
||||
|
||||
return read_whole_file(filename);
|
||||
}
|
||||
|
||||
void Hello::load_enabled_units() noexcept {
|
||||
m_loaded_units.clear();
|
||||
m_enabled_units.clear();
|
||||
|
||||
const auto& service_list = utils::make_multiline(utils::exec("systemctl list-unit-files -q --no-pager | tr -s \" \""), false, "\n");
|
||||
for (const auto &service : service_list) {
|
||||
const auto& out = utils::make_multiline(service, false, " ");
|
||||
m_loaded_units.push_back(out[0]);
|
||||
if (out[1] == "enabled")
|
||||
m_enabled_units.push_back(out[0]);
|
||||
}
|
||||
}
|
||||
void Hello::load_global_enabled_units() noexcept {
|
||||
m_global_loaded_units.clear();
|
||||
m_global_enabled_units.clear();
|
||||
|
||||
const auto& service_list = utils::make_multiline(utils::exec("systemctl --global list-unit-files -q --no-pager | tr -s \" \""), false, "\n");
|
||||
for (const auto &service : service_list) {
|
||||
const auto& out = utils::make_multiline(service, false, " ");
|
||||
m_global_loaded_units.push_back(out[0]);
|
||||
if (out[1] == "enabled")
|
||||
m_global_enabled_units.push_back(out[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Handlers
|
||||
void Hello::on_languages_changed(GtkComboBox* combobox) noexcept {
|
||||
const auto& active_id = gtk_combo_box_get_active_id(combobox);
|
||||
g_refHello->set_locale(active_id);
|
||||
}
|
||||
|
||||
void Hello::on_action_clicked(GtkWidget* widget) noexcept {
|
||||
const auto& name = gtk_widget_get_name(widget);
|
||||
if (strncmp(name, "install", 7) == 0) {
|
||||
quick_message(g_refHello, "Calamares install type");
|
||||
return;
|
||||
} else if (strncmp(name, "autostart", 9) == 0) {
|
||||
const auto& action = Glib::wrap(GTK_SWITCH(widget));
|
||||
g_refHello->set_autostart(action->get_active());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Gtk::AboutDialog* dialog;
|
||||
g_refHello->m_builder->get_widget("aboutdialog", dialog);
|
||||
dialog->run();
|
||||
dialog->hide();
|
||||
}
|
||||
|
||||
void Hello::on_btn_clicked(GtkWidget* widget) noexcept {
|
||||
const auto& name = gtk_widget_get_name(widget);
|
||||
Gtk::Stack* stack;
|
||||
g_refHello->m_builder->get_widget("stack", stack);
|
||||
stack->set_visible_child(fmt::format("{}page", name).c_str());
|
||||
}
|
||||
void Hello::on_link_clicked(GtkWidget* widget) noexcept {
|
||||
const auto& name = gtk_widget_get_name(widget);
|
||||
const std::string uri = g_refHello->m_preferences["urls"][name];
|
||||
gtk_show_uri_on_window(nullptr, uri.c_str(), GDK_CURRENT_TIME, nullptr);
|
||||
}
|
||||
void Hello::on_delete_window(GtkWidget* /*widget*/) noexcept {
|
||||
write_json(g_refHello->m_preferences["save_path"].get<std::string>(), g_refHello->m_save);
|
||||
const auto& application = g_refHello->get_application();
|
||||
application->quit();
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#ifndef HELLO_HPP_
|
||||
#define HELLO_HPP_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <json.hpp>
|
||||
|
||||
class Hello final : public Gtk::Window {
|
||||
public:
|
||||
Hello(int argc, char** argv);
|
||||
|
||||
const std::vector<std::string>& get_loaded_units() const
|
||||
{ return m_loaded_units; }
|
||||
const std::vector<std::string>& get_enabled_units() const
|
||||
{ return m_enabled_units; }
|
||||
const std::vector<std::string>& get_global_loaded_units() const
|
||||
{ return m_global_loaded_units; }
|
||||
const std::vector<std::string>& get_global_enabled_units() const
|
||||
{ return m_global_enabled_units; }
|
||||
|
||||
void load_enabled_units() noexcept;
|
||||
void load_global_enabled_units() noexcept;
|
||||
|
||||
protected:
|
||||
// Handlers
|
||||
static void on_languages_changed(GtkComboBox* combobox) noexcept;
|
||||
static void on_action_clicked(GtkWidget* widget) noexcept;
|
||||
static void on_btn_clicked(GtkWidget* widget) noexcept;
|
||||
static void on_link_clicked(GtkWidget* widget) noexcept;
|
||||
static void on_delete_window(GtkWidget* /*widget*/) noexcept;
|
||||
|
||||
private:
|
||||
static constexpr auto m_app = "cachyos-hello";
|
||||
bool m_dev{};
|
||||
bool m_autostart{};
|
||||
|
||||
std::string m_pages;
|
||||
Glib::RefPtr<Gtk::Builder> m_builder;
|
||||
nlohmann::json m_preferences;
|
||||
nlohmann::json m_save;
|
||||
nlohmann::json m_default_texts;
|
||||
std::vector<std::string> m_loaded_units;
|
||||
std::vector<std::string> m_enabled_units;
|
||||
std::vector<std::string> m_global_loaded_units;
|
||||
std::vector<std::string> m_global_enabled_units;
|
||||
|
||||
auto get_best_locale() const noexcept -> std::string;
|
||||
void set_locale(const std::string_view& use_locale) noexcept;
|
||||
void set_autostart(const bool& autostart) noexcept;
|
||||
auto get_page(const std::string& name) const noexcept -> std::string;
|
||||
};
|
||||
|
||||
#endif // HELLO_HPP_
|
|
@ -1,49 +0,0 @@
|
|||
// Helper macroses
|
||||
#ifndef HELPER_HPP_
|
||||
#define HELPER_HPP_
|
||||
|
||||
#include <fstream>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
inline std::pair<std::string, std::string> tokenize(std::string& str, const std::string_view& delim) {
|
||||
std::size_t start{};
|
||||
std::size_t end = str.find(delim.data());
|
||||
std::string key;
|
||||
while (end != std::string::npos) {
|
||||
key = str.substr(start, end - start);
|
||||
start = end + delim.length();
|
||||
end = str.find(delim.data(), start);
|
||||
}
|
||||
return {key, str.substr(start, end - start)};
|
||||
}
|
||||
|
||||
inline std::size_t replace_all(std::string& inout, const std::string_view& what, const std::string_view& with) {
|
||||
std::size_t count{};
|
||||
std::size_t pos{};
|
||||
while (std::string::npos != (pos = inout.find(what.data(), pos, what.length()))) {
|
||||
inout.replace(pos, what.length(), with.data(), with.length());
|
||||
pos += with.length(), ++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
inline std::size_t remove_all(std::string& inout, const std::string_view& what) {
|
||||
return replace_all(inout, what, "");
|
||||
}
|
||||
|
||||
auto read_whole_file(const std::string_view& path) noexcept -> std::string {
|
||||
static constexpr auto read_size = 4096;
|
||||
std::ifstream stream{path.data()};
|
||||
stream.exceptions(std::ios_base::badbit);
|
||||
|
||||
std::string file{};
|
||||
std::string buf(read_size, '\0');
|
||||
while (stream.read(&buf[0], read_size)) {
|
||||
file.append(buf, 0, static_cast<std::size_t>(stream.gcount()));
|
||||
}
|
||||
file.append(buf, 0, static_cast<std::size_t>(stream.gcount()));
|
||||
return file;
|
||||
}
|
||||
|
||||
#endif // HELPER_HPP_
|
26640
src/json.hpp
26640
src/json.hpp
File diff suppressed because it is too large
Load Diff
10
src/main.cpp
10
src/main.cpp
|
@ -1,10 +0,0 @@
|
|||
#include "hello.hpp"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
auto app = Gtk::Application::create();
|
||||
|
||||
Hello hello(argc, argv);
|
||||
|
||||
// Shows the window and returns when it is closed.
|
||||
return app->run(hello);
|
||||
}
|
|
@ -0,0 +1,786 @@
|
|||
#![feature(const_slice_from_raw_parts)]
|
||||
#![feature(const_str_from_utf8)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
mod config;
|
||||
mod data_types;
|
||||
mod utils;
|
||||
|
||||
use config::{APP_ID, GETTEXT_PACKAGE, LOCALEDIR, PKGDATADIR, PROFILE, VERSION};
|
||||
use data_types::*;
|
||||
use gettextrs::LocaleCategory;
|
||||
use gtk::{gio, glib, Builder, HeaderBar, Window};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write as _;
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
use utils::*;
|
||||
|
||||
use gio::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
|
||||
use gdk_pixbuf::Pixbuf;
|
||||
|
||||
use serde_json::json;
|
||||
use std::sync::Arc;
|
||||
use std::{fs, str};
|
||||
use subprocess::{Exec, Redirection};
|
||||
|
||||
static mut g_save_json: Lazy<Mutex<serde_json::Value>> = Lazy::new(|| Mutex::new(json!(null)));
|
||||
static mut g_local_units: Lazy<Mutex<SystemdUnits>> = Lazy::new(|| Mutex::new(SystemdUnits::new()));
|
||||
static mut g_global_units: Lazy<Mutex<SystemdUnits>> =
|
||||
Lazy::new(|| Mutex::new(SystemdUnits::new()));
|
||||
|
||||
static mut g_hello_window: Option<Arc<HelloWindow>> = None;
|
||||
|
||||
fn quick_message(message: &str) {
|
||||
// Create the widgets
|
||||
let dialog = gtk::Dialog::builder().title(message).modal(true).build();
|
||||
|
||||
dialog.set_destroy_with_parent(true);
|
||||
dialog.add_button("_Offline", gtk::ResponseType::No);
|
||||
dialog.add_button("_Online", gtk::ResponseType::Yes);
|
||||
let content_area = dialog.content_area();
|
||||
let label = gtk::Label::new(Some(message));
|
||||
|
||||
// Add the label, and show everything we’ve added
|
||||
content_area.add(&label);
|
||||
dialog.show_all();
|
||||
|
||||
let result = dialog.run();
|
||||
let cmd: String;
|
||||
if result == gtk::ResponseType::No {
|
||||
cmd = fix_path("/usr/local/bin/calamares-offline.sh");
|
||||
} else if result == gtk::ResponseType::Yes {
|
||||
cmd = fix_path("/usr/local/bin/calamares-online.sh");
|
||||
} else {
|
||||
unsafe {
|
||||
dialog.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn child process in separate thread.
|
||||
std::thread::spawn(move || {
|
||||
Exec::shell(cmd).join().unwrap();
|
||||
});
|
||||
|
||||
unsafe {
|
||||
dialog.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
fn create_options_section() -> gtk::Box {
|
||||
let topbox = gtk::Box::new(gtk::Orientation::Vertical, 2);
|
||||
let box_collection = gtk::Box::new(gtk::Orientation::Horizontal, 10);
|
||||
let label = gtk::Label::new(None);
|
||||
label.set_line_wrap(true);
|
||||
label.set_justify(gtk::Justification::Center);
|
||||
label.set_text("Tweaks");
|
||||
|
||||
let psd_btn = gtk::CheckButton::with_label("Profile-sync-daemon enable");
|
||||
let systemd_oomd_btn = gtk::CheckButton::with_label("Systemd-oomd enabled");
|
||||
let apparmor_btn = gtk::CheckButton::with_label("Apparmor enabled");
|
||||
let ananicy_cpp_btn = gtk::CheckButton::with_label("Ananicy Cpp enabled");
|
||||
|
||||
unsafe {
|
||||
psd_btn.set_data("actionData", "psd.service");
|
||||
psd_btn.set_data("actionType", "user_service");
|
||||
systemd_oomd_btn.set_data("actionData", "systemd-oomd.service");
|
||||
systemd_oomd_btn.set_data("actionType", "service");
|
||||
apparmor_btn.set_data("actionData", "apparmor.service");
|
||||
apparmor_btn.set_data("actionType", "service");
|
||||
ananicy_cpp_btn.set_data("actionData", "ananicy-cpp.service");
|
||||
ananicy_cpp_btn.set_data("actionType", "service");
|
||||
}
|
||||
|
||||
for btn in &[&psd_btn, &systemd_oomd_btn, &apparmor_btn, &ananicy_cpp_btn] {
|
||||
unsafe {
|
||||
let data: &str = *btn.data("actionData").unwrap().as_ptr();
|
||||
if g_local_units.lock().unwrap().enabled_units.contains(&String::from(data))
|
||||
|| g_global_units.lock().unwrap().enabled_units.contains(&String::from(data))
|
||||
{
|
||||
btn.set_active(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
psd_btn.connect_clicked(on_servbtn_clicked);
|
||||
systemd_oomd_btn.connect_clicked(on_servbtn_clicked);
|
||||
apparmor_btn.connect_clicked(on_servbtn_clicked);
|
||||
ananicy_cpp_btn.connect_clicked(on_servbtn_clicked);
|
||||
|
||||
topbox.pack_start(&label, true, false, 1);
|
||||
box_collection.pack_start(&psd_btn, true, false, 2);
|
||||
box_collection.pack_start(&systemd_oomd_btn, true, false, 2);
|
||||
box_collection.pack_start(&apparmor_btn, true, false, 2);
|
||||
box_collection.pack_start(&ananicy_cpp_btn, true, false, 2);
|
||||
box_collection.set_halign(gtk::Align::Fill);
|
||||
topbox.pack_start(&box_collection, true, false, 1);
|
||||
|
||||
topbox.set_hexpand(true);
|
||||
topbox
|
||||
}
|
||||
|
||||
fn create_apps_section() -> gtk::Box {
|
||||
let topbox = gtk::Box::new(gtk::Orientation::Vertical, 2);
|
||||
let box_collection = gtk::Box::new(gtk::Orientation::Horizontal, 10);
|
||||
let label = gtk::Label::new(None);
|
||||
label.set_line_wrap(true);
|
||||
label.set_justify(gtk::Justification::Center);
|
||||
label.set_text("Applications");
|
||||
|
||||
let cachyos_pi = gtk::Button::with_label("CachyOS PackageInstaller");
|
||||
let cachyos_km = gtk::Button::with_label("CachyOS Kernel Manager");
|
||||
|
||||
cachyos_pi.connect_clicked(on_appbtn_clicked);
|
||||
cachyos_km.connect_clicked(on_appbtn_clicked);
|
||||
|
||||
box_collection.pack_start(&cachyos_pi, true, true, 2);
|
||||
box_collection.pack_start(&cachyos_km, true, true, 2);
|
||||
|
||||
topbox.pack_start(&label, true, true, 2);
|
||||
|
||||
box_collection.set_halign(gtk::Align::Fill);
|
||||
topbox.pack_start(&box_collection, true, true, 0);
|
||||
|
||||
topbox.set_hexpand(true);
|
||||
topbox
|
||||
}
|
||||
|
||||
fn show_about_dialog() {
|
||||
let main_window: Window;
|
||||
unsafe {
|
||||
main_window = g_hello_window.clone().unwrap().window.clone();
|
||||
}
|
||||
let dialog = gtk::AboutDialog::builder()
|
||||
.transient_for(&main_window)
|
||||
.modal(true)
|
||||
.program_name(&gettextrs::gettext("CachyOS Hello"))
|
||||
.comments(&gettextrs::gettext("Welcome screen for CachyOS"))
|
||||
.version(VERSION)
|
||||
.logo_icon_name(APP_ID)
|
||||
.authors(vec![
|
||||
"Vladislav Nepogodin".into(),
|
||||
])
|
||||
// Translators: Replace "translator-credits" with your names. Put a comma between.
|
||||
.translator_credits(&gettextrs::gettext("translator-credits"))
|
||||
.copyright("2021-2022 CachyOS team")
|
||||
.license_type(gtk::License::Gpl30)
|
||||
.website("https://github.com/cachyos/cachyos-welcome")
|
||||
.website_label("GitHub")
|
||||
.build();
|
||||
|
||||
dialog.run();
|
||||
dialog.hide();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
gettextrs::setlocale(LocaleCategory::LcAll, "");
|
||||
gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain.");
|
||||
gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain.");
|
||||
|
||||
glib::set_application_name("CachyOSHello");
|
||||
|
||||
gtk::init().expect("Unable to start GTK3.");
|
||||
|
||||
let application = gtk::Application::new(
|
||||
Some(APP_ID), // Application id
|
||||
Default::default(), // Using default flags
|
||||
);
|
||||
|
||||
application.connect_activate(|application| {
|
||||
build_ui(application);
|
||||
});
|
||||
|
||||
// Run the application and start the event loop
|
||||
application.run();
|
||||
}
|
||||
|
||||
fn build_ui(application: >k::Application) {
|
||||
let data = fs::read_to_string(format!("{}/data/preferences.json", PKGDATADIR))
|
||||
.expect("Unable to read file");
|
||||
let preferences: serde_json::Value = serde_json::from_str(&data).expect("Unable to parse");
|
||||
|
||||
// Get saved infos
|
||||
let save_path = fix_path(preferences["save_path"].as_str().unwrap());
|
||||
let save: serde_json::Value = if !Path::new(&save_path).exists() {
|
||||
json!({"locale": ""})
|
||||
} else {
|
||||
read_json(save_path.as_str())
|
||||
};
|
||||
|
||||
// Import Css
|
||||
let provider = gtk::CssProvider::new();
|
||||
provider.load_from_path(preferences["style_path"].as_str().unwrap()).unwrap();
|
||||
if let Some(screen) = gdk::Screen::default() {
|
||||
gtk::StyleContext::add_provider_for_screen(
|
||||
&screen,
|
||||
&provider,
|
||||
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
);
|
||||
}
|
||||
|
||||
// Init window
|
||||
let builder: Builder = Builder::from_file(preferences["ui_path"].as_str().unwrap());
|
||||
builder.connect_signals(|_builder, handler_name| {
|
||||
match handler_name {
|
||||
// handler_name as defined in the glade file => handler function as defined above
|
||||
"on_languages_changed" => Box::new(on_languages_changed),
|
||||
"on_action_clicked" => Box::new(on_action_clicked),
|
||||
"on_btn_clicked" => Box::new(on_btn_clicked),
|
||||
"on_link_clicked" => Box::new(on_link_clicked),
|
||||
"on_delete_window" => Box::new(on_delete_window),
|
||||
_ => Box::new(|_| None),
|
||||
}
|
||||
});
|
||||
|
||||
let main_window: Window = builder.object("window").expect("Could not get the object window");
|
||||
main_window.set_application(Some(application));
|
||||
|
||||
unsafe {
|
||||
g_hello_window = Some(Arc::new(HelloWindow {
|
||||
window: main_window.clone(),
|
||||
builder: builder.clone(),
|
||||
preferences: preferences.clone(),
|
||||
}));
|
||||
|
||||
*g_save_json.lock().unwrap() = save.clone();
|
||||
};
|
||||
|
||||
// Subtitle of headerbar
|
||||
let header: HeaderBar = builder.object("headerbar").expect("Could not get the headerbar");
|
||||
|
||||
header.set_subtitle(Some("CachyOS rolling"));
|
||||
|
||||
// Load images
|
||||
let logo_path = preferences["logo_path"].as_str().unwrap();
|
||||
if Path::new(&logo_path).exists() {
|
||||
let logo = Pixbuf::from_file(logo_path).unwrap();
|
||||
main_window.set_icon(Some(&logo));
|
||||
|
||||
let image: gtk::Image = builder.object("distriblogo").unwrap();
|
||||
image.set_from_pixbuf(Some(&logo));
|
||||
|
||||
let dialog: gtk::AboutDialog = builder.object("aboutdialog").unwrap();
|
||||
dialog.set_logo(Some(&logo));
|
||||
}
|
||||
|
||||
let social_box: gtk::Box = builder.object("social").unwrap();
|
||||
for btn in social_box.children() {
|
||||
let name = btn.widget_name();
|
||||
let icon_path = format!("{}/data/img/{}.png", PKGDATADIR, name);
|
||||
let image: gtk::Image = builder.object(name.as_str()).unwrap();
|
||||
image.set_from_file(Some(&icon_path));
|
||||
}
|
||||
|
||||
let homepage_grid: gtk::Grid = builder.object("homepage").unwrap();
|
||||
for widget in homepage_grid.children() {
|
||||
let casted_widget = widget.downcast::<gtk::Button>();
|
||||
if casted_widget.is_err() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let btn = casted_widget.unwrap();
|
||||
if btn.image_position() != gtk::PositionType::Right {
|
||||
continue;
|
||||
}
|
||||
let image_path = format!("{}/data/img/external-link.png", PKGDATADIR);
|
||||
let image = gtk::Image::new();
|
||||
image.set_from_file(Some(&image_path));
|
||||
image.set_margin_start(2);
|
||||
btn.set_image(Some(&image));
|
||||
}
|
||||
|
||||
// Create pages
|
||||
let pages =
|
||||
format!("{}/data/pages/{}", PKGDATADIR, preferences["default_locale"].as_str().unwrap());
|
||||
|
||||
for page in fs::read_dir(pages).unwrap() {
|
||||
let scrolled_window =
|
||||
gtk::ScrolledWindow::new(gtk::Adjustment::NONE, gtk::Adjustment::NONE);
|
||||
|
||||
let viewport = gtk::Viewport::new(gtk::Adjustment::NONE, gtk::Adjustment::NONE);
|
||||
viewport.set_border_width(10);
|
||||
|
||||
let label = gtk::Label::new(None);
|
||||
label.set_line_wrap(true);
|
||||
let image = gtk::Image::from_icon_name(Some("go-previous"), gtk::IconSize::Button);
|
||||
let back_btn = gtk::Button::new();
|
||||
back_btn.set_image(Some(&image));
|
||||
back_btn.set_widget_name("home");
|
||||
|
||||
back_btn.connect_clicked(glib::clone!(@weak builder => move |button| {
|
||||
let name = button.widget_name();
|
||||
let stack: gtk::Stack = builder.object("stack").unwrap();
|
||||
stack.set_visible_child_name(&format!("{}page", name));
|
||||
}));
|
||||
|
||||
let grid = gtk::Grid::new();
|
||||
grid.attach(&back_btn, 0, 1, 1, 1);
|
||||
grid.attach(&label, 1, 2, 1, 1);
|
||||
viewport.add(&grid);
|
||||
scrolled_window.add(&viewport);
|
||||
scrolled_window.show_all();
|
||||
|
||||
let stack: gtk::Stack = builder.object("stack").unwrap();
|
||||
let child_name =
|
||||
format!("{}page", page.unwrap().path().file_name().unwrap().to_str().unwrap());
|
||||
stack.add_named(&scrolled_window, &child_name);
|
||||
}
|
||||
|
||||
// Init translation
|
||||
gettextrs::bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR)
|
||||
.expect("Unable to switch to the text domain.");
|
||||
gettextrs::bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8")
|
||||
.expect("Unable to set domain encoding.");
|
||||
gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain.");
|
||||
let languages: gtk::ComboBoxText = builder.object("languages").unwrap();
|
||||
languages.set_active_id(Some(get_best_locale(&preferences, &save).as_str()));
|
||||
|
||||
// Set autostart switcher state
|
||||
let autostart = Path::new(&fix_path(preferences["autostart_path"].as_str().unwrap())).exists();
|
||||
let autostart_switch: gtk::Switch = builder.object("autostart").unwrap();
|
||||
autostart_switch.set_active(autostart);
|
||||
|
||||
// Live systems
|
||||
if (Path::new(&preferences["live_path"].as_str().unwrap()).exists())
|
||||
&& (check_regular_file(preferences["installer_path"].as_str().unwrap()))
|
||||
{
|
||||
let installlabel: gtk::Label = builder.object("installlabel").unwrap();
|
||||
installlabel.set_visible(true);
|
||||
|
||||
let install: gtk::Button = builder.object("install").unwrap();
|
||||
install.set_visible(true);
|
||||
|
||||
// Show the UI
|
||||
main_window.show();
|
||||
return;
|
||||
} else {
|
||||
let installlabel: gtk::Label = builder.object("installlabel").unwrap();
|
||||
installlabel.set_visible(false);
|
||||
|
||||
let install: gtk::Button = builder.object("install").unwrap();
|
||||
install.set_visible(false);
|
||||
}
|
||||
let install: gtk::Button = builder.object("appBrowser").unwrap();
|
||||
install.set_visible(true);
|
||||
|
||||
load_enabled_units();
|
||||
load_global_enabled_units();
|
||||
|
||||
let viewport = gtk::Viewport::new(gtk::Adjustment::NONE, gtk::Adjustment::NONE);
|
||||
// let label = gtk::Label::new(None);
|
||||
// label.set_line_wrap(true);
|
||||
let image = gtk::Image::from_icon_name(Some("go-previous"), gtk::IconSize::Button);
|
||||
let back_btn = gtk::Button::new();
|
||||
back_btn.set_image(Some(&image));
|
||||
back_btn.set_widget_name("home");
|
||||
|
||||
back_btn.connect_clicked(glib::clone!(@weak builder => move |button| {
|
||||
let name = button.widget_name();
|
||||
let stack: gtk::Stack = builder.object("stack").unwrap();
|
||||
stack.set_visible_child_name(&format!("{}page", name));
|
||||
}));
|
||||
|
||||
let options_section_box = create_options_section();
|
||||
let apps_section_box = create_apps_section();
|
||||
|
||||
let grid = gtk::Grid::new();
|
||||
grid.set_hexpand(true);
|
||||
grid.set_margin_start(10);
|
||||
grid.set_margin_end(10);
|
||||
grid.set_margin_top(5);
|
||||
grid.set_margin_bottom(5);
|
||||
grid.attach(&back_btn, 0, 1, 1, 1);
|
||||
let box_collection = gtk::Box::new(gtk::Orientation::Vertical, 5);
|
||||
|
||||
box_collection.pack_start(&options_section_box, true, true, 5);
|
||||
box_collection.pack_start(&apps_section_box, true, true, 5);
|
||||
|
||||
box_collection.set_valign(gtk::Align::Center);
|
||||
box_collection.set_halign(gtk::Align::Center);
|
||||
grid.attach(&box_collection, 1, 2, 5, 1);
|
||||
viewport.add(&grid);
|
||||
viewport.show_all();
|
||||
|
||||
let stack: gtk::Stack = builder.object("stack").unwrap();
|
||||
let child_name = "appBrowserpage";
|
||||
stack.add_named(&viewport, child_name);
|
||||
|
||||
// Show the UI
|
||||
main_window.show();
|
||||
}
|
||||
|
||||
/// Returns the best locale, based on user's preferences.
|
||||
pub fn get_best_locale(preferences: &serde_json::Value, save: &serde_json::Value) -> String {
|
||||
let saved_locale =
|
||||
format!("{}/{}/LC_MESSAGES/cachyos-hello.mo", LOCALEDIR, save["locale"].as_str().unwrap());
|
||||
if check_regular_file(saved_locale.as_str()) {
|
||||
return String::from(save["locale"].as_str().unwrap());
|
||||
} else if save["locale"].as_str().unwrap() == preferences["default_locale"].as_str().unwrap() {
|
||||
return String::from(preferences["default_locale"].as_str().unwrap());
|
||||
}
|
||||
|
||||
let locale_name = std::env::var("LC_ALL").unwrap_or_else(|_| String::from("en_US.UTF-8"));
|
||||
let sys_locale =
|
||||
string_substr(locale_name.as_str(), 0, locale_name.find('.').unwrap_or(usize::MAX))
|
||||
.unwrap();
|
||||
let user_locale = format!("{}/{}/LC_MESSAGES/cachyos-hello.mo", LOCALEDIR, sys_locale);
|
||||
let two_letters = string_substr(sys_locale, 0, 2).unwrap();
|
||||
|
||||
// If user's locale is supported
|
||||
if check_regular_file(user_locale.as_str()) {
|
||||
if sys_locale.contains('_') {
|
||||
return sys_locale.replace('_', "-");
|
||||
}
|
||||
return String::from(sys_locale);
|
||||
}
|
||||
// If two first letters of user's locale is supported (ex: en_US -> en)
|
||||
else if check_regular_file(
|
||||
format!("{}/{}/LC_MESSAGES/cachyos-hello.mo", LOCALEDIR, two_letters).as_str(),
|
||||
) {
|
||||
return String::from(two_letters);
|
||||
}
|
||||
|
||||
String::from(preferences["default_locale"].as_str().unwrap())
|
||||
}
|
||||
|
||||
/// Sets locale of ui and pages.
|
||||
fn set_locale(use_locale: &str) {
|
||||
if PROFILE == "Devel" {
|
||||
println!(
|
||||
"┌{0:─^40}┐\n│{1: ^40}│\n└{0:─^40}┘",
|
||||
"",
|
||||
format!("Locale changed to {}", use_locale)
|
||||
);
|
||||
}
|
||||
|
||||
gettextrs::textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain.");
|
||||
glib::setenv("LANGUAGE", use_locale, true).expect("Unable to change env variable.");
|
||||
|
||||
unsafe {
|
||||
g_save_json.lock().unwrap()["locale"] = json!(use_locale);
|
||||
}
|
||||
|
||||
// Real-time locale changing
|
||||
let elts: HashMap<String, serde_json::Value> = serde_json::from_str(&serde_json::to_string(&json!({
|
||||
"comments": ["aboutdialog"],
|
||||
"label": ["autostartlabel", "development", "discover", "donate", "firstcategory", "forum", "install", "installlabel", "involved", "mailling", "readme", "release", "secondcategory", "thirdcategory", "welcomelabel", "welcometitle", "wiki"],
|
||||
"tooltip_text": ["about", "development", "discover", "donate", "forum", "mailling", "wiki"],
|
||||
})).unwrap()).unwrap();
|
||||
|
||||
let mut default_texts = json!(null);
|
||||
for method in elts.iter() {
|
||||
if default_texts.get(method.0) == None {
|
||||
default_texts[method.0] = json![null];
|
||||
}
|
||||
|
||||
for elt in elts[method.0].as_array().unwrap() {
|
||||
let elt_value = elt.as_str().unwrap();
|
||||
unsafe {
|
||||
let item: gtk::Widget =
|
||||
g_hello_window.clone().unwrap().builder.object(elt_value).unwrap();
|
||||
if default_texts[method.0].get(elt_value) == None {
|
||||
let item_buf = item.property::<String>(method.0.as_str());
|
||||
default_texts[method.0][elt_value] = json!(item_buf);
|
||||
}
|
||||
if method.0 == "tooltip_text" || method.0 == "comments" {
|
||||
item.set_property(
|
||||
method.0,
|
||||
&gettextrs::gettext(default_texts[method.0][elt_value].as_str().unwrap()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let preferences = &g_hello_window.clone().unwrap().preferences;
|
||||
let save = &*g_save_json.lock().unwrap();
|
||||
|
||||
// Change content of pages
|
||||
let pages = format!(
|
||||
"{}/data/pages/{}",
|
||||
PKGDATADIR,
|
||||
preferences["default_locale"].as_str().unwrap()
|
||||
);
|
||||
for page in fs::read_dir(pages).unwrap() {
|
||||
let stack: gtk::Stack =
|
||||
g_hello_window.clone().unwrap().builder.object("stack").unwrap();
|
||||
let child = stack.child_by_name(&format!(
|
||||
"{}page",
|
||||
page.as_ref().unwrap().path().file_name().unwrap().to_str().unwrap()
|
||||
));
|
||||
if child == None {
|
||||
eprintln!("child not found");
|
||||
continue;
|
||||
}
|
||||
let first_child = &child.unwrap().downcast::<gtk::Container>().unwrap().children();
|
||||
let second_child =
|
||||
&first_child[0].clone().downcast::<gtk::Container>().unwrap().children();
|
||||
let third_child =
|
||||
&second_child[0].clone().downcast::<gtk::Container>().unwrap().children();
|
||||
|
||||
let label = &third_child[0].clone().downcast::<gtk::Label>().unwrap();
|
||||
label.set_markup(
|
||||
get_page(
|
||||
page.unwrap().path().file_name().unwrap().to_str().unwrap(),
|
||||
preferences,
|
||||
save,
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_autostart(autostart: bool) {
|
||||
let autostart_path: String;
|
||||
let desktop_path: String;
|
||||
unsafe {
|
||||
autostart_path = fix_path(
|
||||
g_hello_window.clone().unwrap().preferences["autostart_path"].as_str().unwrap(),
|
||||
);
|
||||
desktop_path = g_hello_window.clone().unwrap().preferences["desktop_path"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
}
|
||||
let config_dir = Path::new(&autostart_path).parent().unwrap();
|
||||
if !config_dir.exists() {
|
||||
fs::create_dir_all(config_dir).unwrap();
|
||||
}
|
||||
if autostart && !check_regular_file(autostart_path.as_str()) {
|
||||
std::os::unix::fs::symlink(desktop_path, autostart_path).unwrap();
|
||||
} else if !autostart && check_regular_file(autostart_path.as_str()) {
|
||||
std::fs::remove_file(autostart_path).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_page(name: &str, preferences: &serde_json::Value, save: &serde_json::Value) -> String {
|
||||
let mut filename =
|
||||
format!("{}/data/pages/{}/{}", PKGDATADIR, save["locale"].as_str().unwrap(), name);
|
||||
if !check_regular_file(filename.as_str()) {
|
||||
filename = format!(
|
||||
"{}/data/pages/{}/{}",
|
||||
PKGDATADIR,
|
||||
preferences["default_locale"].as_str().unwrap(),
|
||||
name
|
||||
);
|
||||
}
|
||||
|
||||
fs::read_to_string(filename).unwrap()
|
||||
}
|
||||
|
||||
fn load_enabled_units() {
|
||||
unsafe {
|
||||
g_local_units.lock().unwrap().loaded_units.clear();
|
||||
g_local_units.lock().unwrap().enabled_units.clear();
|
||||
|
||||
let mut exec_out = Exec::shell("systemctl list-unit-files -q --no-pager | tr -s \" \"")
|
||||
.stdout(Redirection::Pipe)
|
||||
.capture()
|
||||
.unwrap()
|
||||
.stdout_str();
|
||||
exec_out.pop();
|
||||
|
||||
let service_list = exec_out.split('\n');
|
||||
|
||||
for service in service_list {
|
||||
let out: Vec<&str> = service.split(' ').collect();
|
||||
g_local_units.lock().unwrap().loaded_units.push(out[0].to_string());
|
||||
if out[1] == "enabled" {
|
||||
g_local_units.lock().unwrap().enabled_units.push(out[0].to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_global_enabled_units() {
|
||||
unsafe {
|
||||
g_global_units.lock().unwrap().loaded_units.clear();
|
||||
g_global_units.lock().unwrap().enabled_units.clear();
|
||||
|
||||
let mut exec_out =
|
||||
Exec::shell("systemctl --global list-unit-files -q --no-pager | tr -s \" \"")
|
||||
.stdout(Redirection::Pipe)
|
||||
.capture()
|
||||
.unwrap()
|
||||
.stdout_str();
|
||||
exec_out.pop();
|
||||
|
||||
let service_list = exec_out.split('\n');
|
||||
for service in service_list {
|
||||
let out: Vec<&str> = service.split(' ').collect();
|
||||
g_global_units.lock().unwrap().loaded_units.push(out[0].to_string());
|
||||
if out[1] == "enabled" {
|
||||
g_global_units.lock().unwrap().enabled_units.push(out[0].to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handlers
|
||||
fn on_languages_changed(param: &[glib::Value]) -> Option<glib::Value> {
|
||||
let widget = param[0].get::<gtk::ComboBox>().unwrap();
|
||||
let active_id = widget.active_id().unwrap();
|
||||
|
||||
set_locale(active_id.as_str());
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn on_action_clicked(param: &[glib::Value]) -> Option<glib::Value> {
|
||||
let widget = param[0].get::<gtk::Widget>().unwrap();
|
||||
return match widget.widget_name().as_str() {
|
||||
"install" => {
|
||||
quick_message("Calamares install type");
|
||||
None
|
||||
},
|
||||
"autostart" => {
|
||||
let action = widget.downcast::<gtk::Switch>().unwrap();
|
||||
set_autostart(action.is_active());
|
||||
None
|
||||
},
|
||||
_ => {
|
||||
show_about_dialog();
|
||||
None
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn on_servbtn_clicked(button: >k::CheckButton) {
|
||||
// Get action data/type.
|
||||
let action_type: &str;
|
||||
let action_data: &str;
|
||||
unsafe {
|
||||
action_type = *button.data("actionType").unwrap().as_ptr();
|
||||
action_data = *button.data("actionData").unwrap().as_ptr();
|
||||
}
|
||||
|
||||
let (user_only, pkexec_only) =
|
||||
if action_type == "user_service" { ("--user", "--user $(logname)") } else { ("", "") };
|
||||
|
||||
let cmd: String;
|
||||
unsafe {
|
||||
let local_units = &g_local_units.lock().unwrap().enabled_units;
|
||||
cmd = if local_units.contains(&String::from(action_data)) {
|
||||
format!(
|
||||
"/sbin/pkexec {} bash -c \"systemctl {} enable --now --force {}\"",
|
||||
pkexec_only, user_only, action_data
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"/sbin/pkexec {} bash -c \"systemctl {} disable --now {}\"",
|
||||
pkexec_only, user_only, action_data
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
// Spawn child process in separate thread.
|
||||
std::thread::spawn(move || {
|
||||
Exec::shell(cmd).join().unwrap();
|
||||
|
||||
if action_type == "user_service" {
|
||||
load_global_enabled_units();
|
||||
} else {
|
||||
load_enabled_units();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn on_appbtn_clicked(button: >k::Button) {
|
||||
// Get button label.
|
||||
let name = button.label().unwrap();
|
||||
let (binname, is_sudo) = if name == "CachyOS PackageInstaller" {
|
||||
("cachyos-pi-bin", true)
|
||||
} else if name == "CachyOS Kernel Manager" {
|
||||
("cachyos-kernel-manager", false)
|
||||
} else {
|
||||
("", false)
|
||||
};
|
||||
|
||||
// Check if executable exists.
|
||||
let exit_status = Exec::cmd("which").arg(binname).join().unwrap();
|
||||
if !exit_status.success() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut envs = String::new();
|
||||
for env in glib::listenv() {
|
||||
if env == "PATH" {
|
||||
envs += "PATH=/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin ";
|
||||
continue;
|
||||
}
|
||||
let _ = write!(
|
||||
envs,
|
||||
"{}=\"{}\" ",
|
||||
env.to_str().unwrap(),
|
||||
glib::getenv(&env).unwrap().to_str().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
// Get executable path.
|
||||
let mut exe_path =
|
||||
Exec::cmd("which").arg(binname).stdout(Redirection::Pipe).capture().unwrap().stdout_str();
|
||||
exe_path.pop();
|
||||
let bash_cmd = format!("{} {}", &envs, &exe_path);
|
||||
|
||||
// Create context channel.
|
||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
|
||||
// Spawn child process in separate thread.
|
||||
std::thread::spawn(move || {
|
||||
let exit_status = if is_sudo {
|
||||
Exec::cmd("/sbin/pkexec").arg("bash").arg("-c").arg(bash_cmd).join().unwrap()
|
||||
} else {
|
||||
Exec::shell(bash_cmd).join().unwrap()
|
||||
};
|
||||
tx.send(format!("Exit status successfully? = {:?}", exit_status.success()))
|
||||
.expect("Couldn't send data to channel");
|
||||
});
|
||||
|
||||
rx.attach(None, move |text| {
|
||||
println!("{}", text);
|
||||
glib::Continue(true)
|
||||
});
|
||||
}
|
||||
|
||||
fn on_btn_clicked(param: &[glib::Value]) -> Option<glib::Value> {
|
||||
let widget = param[0].get::<gtk::Button>().unwrap();
|
||||
let name = widget.widget_name();
|
||||
|
||||
unsafe {
|
||||
let stack: gtk::Stack = g_hello_window.clone().unwrap().builder.object("stack").unwrap();
|
||||
stack.set_visible_child_name(&format!("{}page", name));
|
||||
};
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn on_link_clicked(param: &[glib::Value]) -> Option<glib::Value> {
|
||||
let widget = param[0].get::<gtk::Widget>().unwrap();
|
||||
let name = widget.widget_name();
|
||||
|
||||
unsafe {
|
||||
let preferences = &g_hello_window.clone().unwrap().preferences["urls"];
|
||||
|
||||
let uri = preferences[name.as_str()].as_str().unwrap();
|
||||
let _ = gtk::show_uri_on_window(gtk::Window::NONE, uri, 0);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn on_delete_window(_param: &[glib::Value]) -> Option<glib::Value> {
|
||||
unsafe {
|
||||
let preferences = &g_hello_window.clone().unwrap().preferences["save_path"];
|
||||
let save = &*g_save_json.lock().unwrap();
|
||||
write_json(preferences.as_str().unwrap(), save);
|
||||
}
|
||||
|
||||
Some(false.to_value())
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
global_conf = configuration_data()
|
||||
global_conf.set_quoted('APP_ID', application_id)
|
||||
global_conf.set_quoted('PKGDATADIR', pkgdatadir)
|
||||
global_conf.set_quoted('PROFILE', profile)
|
||||
global_conf.set_quoted('VERSION', version + version_suffix)
|
||||
global_conf.set_quoted('GETTEXT_PACKAGE', gettext_package)
|
||||
global_conf.set_quoted('LOCALEDIR', localedir)
|
||||
config = configure_file(
|
||||
input: 'config.rs.in',
|
||||
output: 'config.rs',
|
||||
configuration: global_conf
|
||||
)
|
||||
# Copy the config.rs output to the source directory.
|
||||
run_command(
|
||||
'cp',
|
||||
meson.project_build_root() / 'src' / 'config.rs',
|
||||
meson.project_source_root() / 'src' / 'config.rs',
|
||||
check: true
|
||||
)
|
||||
|
||||
cargo_options = [ '--manifest-path', meson.project_source_root() / 'Cargo.toml' ]
|
||||
cargo_options += [ '--target-dir', meson.project_build_root() / 'src' ]
|
||||
|
||||
if get_option('profile') == 'default'
|
||||
cargo_options += [ '--release' ]
|
||||
rust_target = 'release'
|
||||
message('Building in release mode')
|
||||
else
|
||||
rust_target = 'debug'
|
||||
message('Building in debug mode')
|
||||
endif
|
||||
|
||||
cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home' ]
|
||||
|
||||
cargo_build = custom_target(
|
||||
'cargo-build',
|
||||
build_by_default: true,
|
||||
build_always_stale: true,
|
||||
output: meson.project_name(),
|
||||
console: true,
|
||||
install: true,
|
||||
install_dir: bindir,
|
||||
command: [
|
||||
'env',
|
||||
cargo_env,
|
||||
cargo, 'build',
|
||||
cargo_options,
|
||||
'&&',
|
||||
'cp', 'src' / rust_target / meson.project_name(), '@OUTPUT@',
|
||||
]
|
||||
)
|
||||
|
||||
cargo_target_dir = meson.project_build_root() / 'target'
|
||||
cargo_home = meson.project_build_root() / 'cargo-home'
|
||||
manifest_path = meson.project_source_root() / 'Cargo.toml'
|
||||
|
||||
test (
|
||||
'cargo-test',
|
||||
cargo,
|
||||
args: [
|
||||
'test',
|
||||
'--manifest-path=@0@'.format(manifest_path),
|
||||
'--target-dir=@0@'.format(cargo_target_dir),
|
||||
'--',
|
||||
'--nocapture',
|
||||
],
|
||||
env: [
|
||||
'CARGO_HOME=@0@'.format(cargo_home),
|
||||
'PATH=/app/bin:/usr/bin:/usr/lib/sdk/rust-stable/bin',
|
||||
],
|
||||
timeout: 300, # give cargo more time
|
||||
)
|
||||
|
||||
test (
|
||||
'cargo-clippy',
|
||||
cargo,
|
||||
args: [
|
||||
'clippy',
|
||||
'--manifest-path=@0@'.format(manifest_path),
|
||||
'--target-dir=@0@'.format(cargo_target_dir),
|
||||
],
|
||||
env: [
|
||||
'CARGO_HOME=@0@'.format(cargo_home),
|
||||
'PATH=/app/bin:/usr/bin:/usr/lib/sdk/rust-stable/bin',
|
||||
],
|
||||
timeout: 300, # give cargo more time
|
||||
)
|
|
@ -0,0 +1,81 @@
|
|||
use std::fs::File;
|
||||
use std::{fs, slice, str};
|
||||
|
||||
#[inline]
|
||||
pub fn fix_path(path: &str) -> String {
|
||||
if !path.starts_with('~') {
|
||||
return String::from(path);
|
||||
}
|
||||
path.replace('~', glib::home_dir().as_path().to_str().unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_json(path: &str) -> serde_json::Value {
|
||||
let buf = fix_path(path);
|
||||
let data = fs::read_to_string(buf).expect("Unable to read file");
|
||||
serde_json::from_str(&data).expect("Unable to parse")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_json(path: &str, content: &serde_json::Value) {
|
||||
let output = File::create(fix_path(path)).expect("Unable to open file for writing");
|
||||
serde_json::to_writer(output, content).expect("Unable to write json to file");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn const_min(v1: usize, v2: usize) -> usize {
|
||||
if v1 <= v2 {
|
||||
v1
|
||||
} else {
|
||||
v2
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn string_substr(src_str: &str, pos: usize, n: usize) -> Result<&str, str::Utf8Error> {
|
||||
let rlen = const_min(n, src_str.len() - pos);
|
||||
let s = unsafe {
|
||||
// First, we build a &[u8]...
|
||||
let slice = slice::from_raw_parts(src_str.as_ptr().add(pos), rlen);
|
||||
|
||||
// ... and then convert that slice into a string slice
|
||||
str::from_utf8(slice)
|
||||
};
|
||||
s
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn check_regular_file(path: &str) -> bool {
|
||||
let metadata = fs::metadata(path);
|
||||
if let Ok(meta) = metadata {
|
||||
meta.file_type().is_file()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn check_file() {
|
||||
assert_eq!(check_regular_file("/etc/fstab"), true);
|
||||
assert_eq!(check_regular_file("/etc"), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_substr() {
|
||||
let text = "The test string is here";
|
||||
assert_eq!(string_substr(text, 0, 3).unwrap(), "The");
|
||||
assert_eq!(string_substr(text, 4, 4).unwrap(), "test");
|
||||
assert_eq!(string_substr(text, 19, 4).unwrap(), "here");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_min() {
|
||||
assert_eq!(const_min(1, 2), 1);
|
||||
assert_eq!(const_min(2, 2), 2);
|
||||
assert_eq!(const_min(3, 2), 2);
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[wrap-git]
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
revision = f5cdf7cb0481afdafa7ff2f5ea640f05215d4ffb
|
||||
|
||||
patch_directory = fmt
|
||||
|
||||
[provide]
|
||||
fmt = fmt_dep
|
|
@ -1,34 +0,0 @@
|
|||
project('fmt', 'cpp',
|
||||
version : '8.0.1',
|
||||
license : 'BSD',
|
||||
default_options : ['cpp_std=c++14']
|
||||
)
|
||||
|
||||
fmt_private_cpp_args = [ ]
|
||||
fmt_interface_cpp_args = [ ]
|
||||
libtype = get_option('default_library')
|
||||
if libtype == 'shared'
|
||||
fmt_private_cpp_args += [ '-DFMT_EXPORT' ]
|
||||
fmt_interface_cpp_args += [ '-DFMT_SHARED' ]
|
||||
endif
|
||||
|
||||
fmt_inc = include_directories('include')
|
||||
fmt_lib = library('fmt',
|
||||
sources : [
|
||||
'src/format.cc',
|
||||
'src/os.cc'
|
||||
],
|
||||
cpp_args : fmt_private_cpp_args,
|
||||
include_directories : fmt_inc
|
||||
)
|
||||
|
||||
fmt_dep = declare_dependency(
|
||||
include_directories : fmt_inc,
|
||||
compile_args : fmt_interface_cpp_args,
|
||||
link_with : fmt_lib
|
||||
)
|
||||
|
||||
fmt_header_only_dep = declare_dependency(
|
||||
include_directories : fmt_inc,
|
||||
compile_args : '-DFMT_HEADER_ONLY'
|
||||
)
|
Loading…
Reference in New Issue