From 82e1ddbf007cac0d7e566306adb083ecb3a33196 Mon Sep 17 00:00:00 2001 From: Ivan Yarcev Date: Mon, 18 Sep 2023 17:29:22 +0600 Subject: [PATCH] Version 1.5 --- .gitignore | 12 + Makefile | 154 + README.md | 27 + com.ublinux.ubl-settings-keyboard.checked.svg | 327 + com.ublinux.ubl-settings-keyboard.policy | 24 + com.ublinux.ubl-settings-keyboard.svg | 6073 +++++++++++++++++ com.ublinux.ubl-settings-keyboard.warning.svg | 55 + gresource.xml | 14 + layouts.csv | 68 + source/CMakeLists.txt | 98 + source/ubl-cmake.in | 1 + source/ubl-settings-keyboard.c | 473 ++ source/ubl-settings-keyboard.h | 136 + source/ubl-strings.h | 38 + source/ubl-utils.c | 2041 ++++++ source/ubl-utils.h | 378 + ubl-settings-keyboard | Bin 0 -> 262488 bytes ubl-settings-keyboard-banner.png | Bin 0 -> 33872 bytes ubl-settings-keyboard-layouts.glade | 150 + ubl-settings-keyboard-options.glade | 145 + ubl-settings-keyboard.css | 114 + ubl-settings-keyboard.desktop | 15 + ubl-settings-keyboard.glade | 1229 ++++ ubl-settings-keyboard.pot | 171 + ubl-settings-keyboard_ru.po | 177 + 25 files changed, 11920 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 com.ublinux.ubl-settings-keyboard.checked.svg create mode 100644 com.ublinux.ubl-settings-keyboard.policy create mode 100644 com.ublinux.ubl-settings-keyboard.svg create mode 100644 com.ublinux.ubl-settings-keyboard.warning.svg create mode 100644 gresource.xml create mode 100644 layouts.csv create mode 100644 source/CMakeLists.txt create mode 100644 source/ubl-cmake.in create mode 100644 source/ubl-settings-keyboard.c create mode 100644 source/ubl-settings-keyboard.h create mode 100644 source/ubl-strings.h create mode 100644 source/ubl-utils.c create mode 100644 source/ubl-utils.h create mode 100755 ubl-settings-keyboard create mode 100644 ubl-settings-keyboard-banner.png create mode 100644 ubl-settings-keyboard-layouts.glade create mode 100644 ubl-settings-keyboard-options.glade create mode 100644 ubl-settings-keyboard.css create mode 100644 ubl-settings-keyboard.desktop create mode 100644 ubl-settings-keyboard.glade create mode 100644 ubl-settings-keyboard.pot create mode 100644 ubl-settings-keyboard_ru.po diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c934a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.vscode/ +ubl-settings-TEMPLATE +*~ +build/ +compile/ +*# +terminal-commands/ +source/ubl-cmake.h +vgcore* +.BUILD.md +.updatebuild.sh +.install.sh \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2c64667 --- /dev/null +++ b/Makefile @@ -0,0 +1,154 @@ +#!/usr/bin/make -f + +#SHELL := /bin/bash +MAKEFILE_FILEPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +MAKEFILE_DIR := $(notdir $(patsubst %/,%,$(dir $(MAKEFILE_FILEPATH)))) +MAKEFILE_PATH := $(dir $(MAKEFILE_FILEPATH)) + +CMAKE_COMMAND = cmake +CMAKE_SOURCE_DIR = $(MAKEFILE_PATH)source +CMAKE_BUILD_DIR = $(MAKEFILE_PATH)compile +DEPENDS = /bin/cmake +PREFIX ?= /usr/local +PKGNAME = $(MAKEFILE_DIR) +FILE_VER = source/${PKGNAME}.h +PKGIDENT=$(subst /,-,${PREFIX}) + +default_target: all + +.PHONY: all init depend debug prepare check build uninstall install clean help + +all: init build + +init: + @echo "Initialize ..."; \ + if [ -d ".git" ]; then \ + LATEST_TAG=$$(git describe --abbrev=0 --tags | sed 's/^v//'); \ + if [ -z "$${LATEST_TAG}" ]; \ + then \ + LATEST_TAG=$$"0.0"; \ + echo "$${LATEST_TAG} is empty"; \ + fi; \ + else \ + LATEST_TAG="Development"; \ + fi; \ + sed -r "s/^(string version_application).*/\1 = \"$${LATEST_TAG}\";/" -i ${FILE_VER}; \ + echo "-- Build path: ${CMAKE_BUILD_DIR}" + +depend: + @echo "Check depends ..." + @for FILE_DEPEND in $(DEPENDS); do \ + if [ ! -f $${FILE_DEPEND} ]; then \ + echo "ERROR: Depend '$${FILE_DEPEND}' not found !"; \ + exit 1; \ + fi; \ + done; \ + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B${CMAKE_BUILD_DIR} --check-build-system CMakeFiles/Makefile.cmake 1 || exit 1; \ + echo "Check depends: OK" + +debug: + @echo "Debug ..." + if [ ! -d ${CMAKE_BUILD_DIR} ]; then \ + $(CMAKE_COMMAND) -S${CMAKE_SOURCE_DIR} -B${CMAKE_BUILD_DIR} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${PREFIX}"; \ + fi; \ + echo "Debug: OK" + +prepare: + @echo "Prepare ..."; \ + if [ ! -d ${CMAKE_BUILD_DIR} ]; then \ + $(CMAKE_COMMAND) -S${CMAKE_SOURCE_DIR} -B${CMAKE_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${PREFIX}"; \ + fi; \ + echo "Prepare: OK" + +check: + @echo "Check ..."; \ + if [ -f ${CMAKE_BUILD_DIR}/${PKGNAME} ]; then \ + echo "Check: OK"; \ + else \ + echo "Check: ${CMAKE_BUILD_DIR}/${PKGNAME} not found !"; \ + exit 1; \ + fi + +build: depend prepare + @echo "Build ..."; \ + $(MAKE_COMMAND) --directory=${CMAKE_BUILD_DIR}; \ + sed -r "s/^(string version_application).*/\1;/" -i ${FILE_VER}; \ + echo "Build: OK" + +uninstall: + @echo "Uninstall ..." + @for FILE_PO in $(wildcard *.po); do \ + LANG=$${FILE_PO##*_};LANG=$${LANG%.*}; \ + FILE_MO=$${FILE_PO##*/}; FILE_MO="$${FILE_MO%_*.po}.mo"; \ + PATH_FILE_MO="${DESTDIR}/usr/share/locale/$${LANG}/LC_MESSAGES/$${FILE_MO}"; \ + $(RM) "$${PATH_FILE_MO}"; \ + done + @for SIZE in 16x16 32x32 48x48 scalable; do \ + $(RM) "${DESTDIR}${PREFIX}/share/icons/hicolor/$${SIZE}/apps/com.ublinux.${PKGNAME}.svg"; \ + $(RM) "${DESTDIR}${PREFIX}/share/icons/hicolor/$${SIZE}/apps/com.ublinux.${PKGNAME}.png"; \ + done + @for FILE_SVG in $(wildcard *.svg); do \ + for SIZE in 16x16 32x32 48x48 scalable; do \ + $(RM) "${DESTDIR}${PREFIX}/share/icons/hicolor/$${SIZE}/status/$${FILE_SVG%.*}".{svg,png,jpg}; \ + done; \ + done + @$(RM) "${DESTDIR}${PREFIX}/bin/${PKGNAME}" + @$(RM) "${DESTDIR}${PREFIX}/share/applications/${PKGNAME}.desktop" + @$(RM) "${DESTDIR}/usr/share/icons/hicolor/scalable/apps/com.ublinux.${PKGNAME}.svg" + @$(RM) "${DESTDIR}/usr/share/polkit-1/actions/com.ublinux.${PKGNAME}${PKGIDENT}.policy" + @if [ -z ${DESTDIR} ]; then \ + [ -d "${DESTDIR}${PREFIX}/share/icons/hicolor/" ] && gtk-update-icon-cache -fiq "${DESTDIR}${PREFIX}/share/icons/hicolor/" &>/dev/null || true; \ + update-desktop-database --quiet &>/dev/null || true; \ + [ -d "${DESTDIR}${PREFIX}/share/applications" ] && touch "${DESTDIR}${PREFIX}/share/applications" &>/dev/null || true; \ + fi + @echo "Uninstall: OK" + +install: check uninstall + @echo "Install ..." + @for FILE_PO in $(wildcard *.po); do \ + LANG=$${FILE_PO##*_};LANG=$${LANG%.*}; \ + install -dm755 "${DESTDIR}/usr/share/locale/$${LANG}/LC_MESSAGES"; \ + FILE_MO=$${FILE_PO##*/}; FILE_MO="$${FILE_MO%_*.po}.mo"; \ + PATH_FILE_MO="${DESTDIR}/usr/share/locale/$${LANG}/LC_MESSAGES/$${FILE_MO}"; \ + echo "$${FILE_PO}"; \ + msgfmt "$${FILE_PO}" -v -f -o "$${PATH_FILE_MO}"; \ + done + @for SIZE in 16 32 48; do \ + install -dm755 "${DESTDIR}${PREFIX}/share/icons/hicolor/$${SIZE}x$${SIZE}/apps"; \ + rsvg-convert -w $${SIZE} -h $${SIZE} -f svg --keep-image-data "com.ublinux.${PKGNAME}.svg" -o "${DESTDIR}${PREFIX}/share/icons/hicolor/$${SIZE}x$${SIZE}/apps/com.ublinux.${PKGNAME}.svg"; \ + done + @install -Dm644 -t "${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/apps/" "com.ublinux.${PKGNAME}.svg" + @cp ./com.ublinux.${PKGNAME}.policy ./compile/com.ublinux.${PKGNAME}${PKGIDENT}.policy + @sed -e 's+/usr/bin+${PREFIX}/bin+' -e 's+.run+${PKGIDENT}.run+g' ./compile/com.ublinux.${PKGNAME}${PKGIDENT}.policy -i + @install -Dm755 -t "${DESTDIR}${PREFIX}/bin/" "${CMAKE_BUILD_DIR}/${PKGNAME}" + @install -Dm644 -t "${DESTDIR}${PREFIX}/share/applications/" "${PKGNAME}.desktop" + @install -Dm644 -t "${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/status/" "com.ublinux.${PKGNAME}.checked.svg" + @install -Dm644 -t "${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/status/" "com.ublinux.${PKGNAME}.warning.svg" + @install -Dm644 -t "${DESTDIR}/usr/share/polkit-1/actions/" "${CMAKE_BUILD_DIR}/com.ublinux.${PKGNAME}${PKGIDENT}.policy" + @install -Dm644 -t "${DESTDIR}/usr/share/${PKGNAME}/csv/" "layouts.csv" + @if [ -z ${DESTDIR} ]; then \ + [ -d "${DESTDIR}${PREFIX}/share/icons/hicolor/" ] && gtk-update-icon-cache -fiq "${DESTDIR}${PREFIX}/share/icons/hicolor/" &>/dev/null || true; \ + update-desktop-database --quiet &>/dev/null || true; \ + [ -d "${DESTDIR}${PREFIX}/share/applications" ] && touch "${DESTDIR}${PREFIX}/share/applications" &>/dev/null || true; \ + fi + @echo "Install: OK" + +clean: + @echo "Clean ..." + @$(RM) -rd ${CMAKE_BUILD_DIR} + @if [ -d ${CMAKE_BUILD_DIR} ]; then \ + echo "Clean: error, compile directory exist ${CMAKE_BUILD_DIR}"; \ + else \ + echo "Clean: OK"; \ + fi + +help: + @echo "The following are some of the valid targets for this Makefile:"; \ + echo "... all (the default if no target is provided)"; \ + echo "... init"; \ + echo "... debug"; \ + echo "... prepare"; \ + echo "... compile"; \ + echo "... install"; \ + echo "... uninstall"; \ + echo "... clean" \ No newline at end of file diff --git a/README.md b/README.md index da6a15c..fdd0a3c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ # ubl-settings-keyboard +# Выполнить +# Build +In order to build ubl-settings-keyboard you will need: + +- CMake +- C compiler +- GTK+ 3 & dependencies +- webkit2gtk (optional) + +Once you have all the necessary dependencies, you can use: +```sh +$ make +``` + +# Installation +After a successful build, just use: +```sh +$ sudo make install clean +``` + +# Uninstallation +After a successful build, just use: +```sh +$ sudo make uninstall +``` + +![alt text](screenshot/screenshot.png) diff --git a/com.ublinux.ubl-settings-keyboard.checked.svg b/com.ublinux.ubl-settings-keyboard.checked.svg new file mode 100644 index 0000000..e3cab42 --- /dev/null +++ b/com.ublinux.ubl-settings-keyboard.checked.svg @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + diff --git a/com.ublinux.ubl-settings-keyboard.policy b/com.ublinux.ubl-settings-keyboard.policy new file mode 100644 index 0000000..abe592b --- /dev/null +++ b/com.ublinux.ubl-settings-keyboard.policy @@ -0,0 +1,24 @@ + + + + + UBLinux + https://ublinux.ru + + + Run ubl-settings-keyboard as root + Запуск утилиты ubl-settings-keyboard с правами root + Authentication is required to run ubl-settings-keyboard + Требуется авторизация для запуска утилиты ubl-settings-keyboard с правами root + + auth_admin + auth_admin + auth_admin + + /usr/bin/ubl-settings-keyboard + true + + + diff --git a/com.ublinux.ubl-settings-keyboard.svg b/com.ublinux.ubl-settings-keyboard.svg new file mode 100644 index 0000000..eead784 --- /dev/null +++ b/com.ublinux.ubl-settings-keyboard.svg @@ -0,0 +1,6073 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.ublinux.ubl-settings-keyboard.warning.svg b/com.ublinux.ubl-settings-keyboard.warning.svg new file mode 100644 index 0000000..9a90dba --- /dev/null +++ b/com.ublinux.ubl-settings-keyboard.warning.svg @@ -0,0 +1,55 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/gresource.xml b/gresource.xml new file mode 100644 index 0000000..c03d777 --- /dev/null +++ b/gresource.xml @@ -0,0 +1,14 @@ + + + + ubl-settings-keyboard.glade + ubl-settings-keyboard-layouts.glade + ubl-settings-keyboard-options.glade + + + ubl-settings-keyboard.css + + + ubl-settings-keyboard-banner.png + + \ No newline at end of file diff --git a/layouts.csv b/layouts.csv new file mode 100644 index 0000000..efad78c --- /dev/null +++ b/layouts.csv @@ -0,0 +1,68 @@ +af;Afrikaans +ar;Arabic +as;Assamese +az;Azerbaijani +be;Belarusian +bg;Bulgarian +bn;Bengali +bs;Bosnian +ca;Catalan +cs;Czech +da;Danish +de;German +el;Greek +en;English +es;Spanish +et;Estonian +fi;Finnish +fr;French +gu;Gujarati +he;Hebrew +hi;Hindi +hr;Croatian +hu;Hungarian +hy;Armenian +id;Indonesian +is;Icelandic +it;Italian +ja;Japanese +ka;Georgian +kk;Kazakh +kn;Kannada +ko;Korean +ks;Kashmiri +ku;Kurdish +ku;Kurdish +ky;Kirghiz +lt;Lithuanian +lv;Latvian +mk;Macedonian +ml;Malayalam +mr;Marathi +ms;Malay +mt;Maltese +nb;Bokmal +nl;Dutch +nn;Nynorsk +or;Oriya +pa;Punjabi +pl;Polish +pt;Portuguese +ro;Romanian +ru;Russian +sa;Sanskrit +sk;Slovak +sl;Slovenian +sq;Albanian +sr;Serbian +sv;Swedish +ta;Tamil +te;Telugu +th;Thai +tr;Turkish +uk;Ukrainian +vi;Vietnamese +zh;Simplified Chinese +zh;Traditional Chinese +zh;Chinese +zh;Traditional Chinese \ No newline at end of file diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000..ded2868 --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,98 @@ +cmake_minimum_required(VERSION 3.7) +project(ubl-settings-keyboard) + +find_package(PkgConfig REQUIRED) + +pkg_check_modules(GTK REQUIRED gtk+-3.0) +include_directories(${GTK_INCLUDE_DIRS}) +link_directories(${GTK_LIBRARY_DIRS}) +add_definitions(${GTK_CFLAGS_OTHER}) + +#pkg_check_modules(VTE291 REQUIRED vte-2.91) +#include_directories(${VTE291_INCLUDE_DIRS}) +#link_directories(${VTE291_LIBRARY_DIRS}) +#add_definitions(${VTE291_CFLAGS_OTHER}) + +find_library(WEBKIT_LIBRARIES_FOUND webkit2gtk-4.0 webkit2gtk-web-extension-4.0) + +option(WEBKIT_FOUND "No" OFF) +if(WEBKIT_LIBRARIES_FOUND) + option(WEBKIT_FOUND "Yes" ON) + PKG_CHECK_MODULES(WEBKIT REQUIRED webkit2gtk-4.0 webkit2gtk-web-extension-4.0) + include_directories(${WEBKIT_INCLUDE_DIRS}) + link_directories(${WEBKIT_LIBRARY_DIRS}) + add_definitions(${WEBKIT_CFLAGS_OTHER}) +endif() + +configure_file(ubl-cmake.in ubl-cmake.h) + +file(COPY ${CMAKE_CURRENT_BINARY_DIR}/ubl-cmake.h DESTINATION ./) + +set(GRESOURCE_C resources.c) +set(GRESOURCE_XML gresource.xml) + +find_program(GLIB_COMPILE_RESOURCES NAMES glib-compile-resources REQUIRED) +add_custom_target(GLADE ubl-settings-keyboard.glade) + +set(DEPENDFILES + ../ubl-settings-keyboard.glade + ../ubl-settings-keyboard-layouts.glade + ../ubl-settings-keyboard-options.glade + ../gresource.xml + ../ubl-settings-keyboard-banner.png + ../ubl-settings-keyboard.css + ) + +file(COPY ${DEPENDFILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +add_custom_command( + OUTPUT ${GRESOURCE_C} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${GLIB_COMPILE_RESOURCES} + ARGS + --generate-source + --target=${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C} + ${GRESOURCE_XML} + VERBATIM + MAIN_DEPENDENCY ${GRESOURCE_XML} + DEPENDS + ${GLADE} +) +add_custom_target( + dummy-resource + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C} +) + +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Werror -Wmissing-declarations -fdiagnostics-color=always -std=c++2a") +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Werror -Wmissing-declarations -fdiagnostics-color=always -lm") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Werror -Wmissing-declarations -fdiagnostics-color=always \ + -O2 -pipe -fno-plt -fexceptions \ + -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security \ + -fstack-clash-protection -fcf-protection") + + +set(SOURCE_FILES + ubl-settings-keyboard.c + ubl-settings-keyboard.h + ubl-strings.h + ubl-utils.h + ubl-utils.c + ${CMAKE_CURRENT_BINARY_DIR}/ubl-cmake.h + ) + +set(LIBRARIES + ${GTK_LIBRARIES} + ${WEBKIT_LIBRARIES} +# ${VTE291_LIBRARIES} + pthread) + + +add_executable(${PROJECT_NAME} ${SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${LIBRARIES}) +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR}) +set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C} + PROPERTIES GENERATED TRUE +) +install(TARGETS ${PROJECT_NAME} DESTINATION bin) +add_dependencies(${PROJECT_NAME} dummy-resource) \ No newline at end of file diff --git a/source/ubl-cmake.in b/source/ubl-cmake.in new file mode 100644 index 0000000..d4623a7 --- /dev/null +++ b/source/ubl-cmake.in @@ -0,0 +1 @@ +#cmakedefine WEBKIT_FOUND diff --git a/source/ubl-settings-keyboard.c b/source/ubl-settings-keyboard.c new file mode 100644 index 0000000..f71ba59 --- /dev/null +++ b/source/ubl-settings-keyboard.c @@ -0,0 +1,473 @@ +#include "ubl-settings-keyboard.h" + +config main_config; + +//signal emmit handlers - no header initialization + +/**on_close_subwindow(GtkWidget *self) + * [EN] + * Closes window in which [self] is contained. + * [RU] + * Закрывает окно, в котором расположен виджет [self]. +*/ +void on_close_subwindow(GtkWidget *self){ + gtk_widget_destroy(gtk_widget_get_toplevel(self)); +} + +/**yon_open_browser(GtkWidget *self, char *link) + * [EN] + * Opens browser with [link] link. + * [RU] + * Открывает браузер с [link] ссылкой. +*/ +void yon_open_browser(GtkWidget *self, char *link){ + yon_ubl_browser_window_open(link,TITLE_LABEL); +} + +/**on_open_documentation_confirmation(GtkWidget *self, char *link) + * [EN] + * Opens confirmation window for [link] link. + * [RU] + * Открывает окно подтверждение перехода по ссылке [link]. +*/ +void on_open_documentation_confirmation(GtkWidget *self, char *link){ + if (main_config.always_open_documentation==0){ + GtkBuilder *builder = gtk_builder_new_from_resource(glade_path); + documentation_confirmation_window *widgets = malloc(sizeof(documentation_confirmation_window)); + widgets->Window = yon_gtk_builder_get_widget(builder,"helpConfirmationWindow"); + widgets->AcceptButton = yon_gtk_builder_get_widget(builder,"ReadHelpButton"); + widgets->CloseButton = yon_gtk_builder_get_widget(builder,"CancelHelpButton"); + widgets->HatText = yon_gtk_builder_get_widget(builder,"webHeaderNameLabel"); + widgets->HeaderText = yon_gtk_builder_get_widget(builder,"helpHeader"); + widgets->InfoText = yon_gtk_builder_get_widget(builder,"helpText"); + widgets->AlwaysOpenCheck = yon_gtk_builder_get_widget(builder,"AlwaysOpenDocumentationCheckbox"); + gtk_label_set_text(GTK_LABEL(widgets->HatText),TITLE_LABEL); + gtk_label_set_text(GTK_LABEL(widgets->HeaderText),HELP_TITLE_LABEL); + gtk_label_set_text(GTK_LABEL(widgets->InfoText),HELP_INFO_LABEL); + gtk_button_set_label(GTK_BUTTON(widgets->AcceptButton),OPEN_HELP_LABEL); + gtk_button_set_label(GTK_BUTTON(widgets->AlwaysOpenCheck),HELP_ALWAYS_OPEN_LABEL); + gtk_button_set_label(GTK_BUTTON(widgets->CloseButton),CANCEL_LABEL); + gtk_widget_show_all(widgets->Window); + g_signal_connect(G_OBJECT(widgets->CloseButton),"clicked",G_CALLBACK(on_close_subwindow),NULL); + g_signal_connect(G_OBJECT(widgets->AcceptButton),"clicked",G_CALLBACK(yon_open_browser),yon_char_new(link)); + g_signal_connect(G_OBJECT(widgets->AcceptButton),"clicked",G_CALLBACK(on_close_subwindow),NULL); + + + } else { + yon_open_browser(self,link); + } +} + +/**on_link(GtkWidget *self, char* uri, gpointer user_data) + * [EN] + * Signal for hadnling AboutDialog links. + * Connect to "activate-link" signal. + * [self] is AboutDialog window; + * [uri] is activated link; + * [user_data] is pointer for user data, hasn't used in standard handler; + * [RU] + * Функция для обработки сигнала нажатия на ссылку окна AboutDialog. + * Присоединять к сигналу "activate-link". + * [self] - окно AboutDialog; + * [uri] - ссылка, по которой совершается переход; + * [user_data] - указатель на любые другие данные, не используется в стандартном обработчике; +*/ +void on_link(GtkWidget *self, char* uri, gpointer user_data){ + gtk_widget_destroy(self); + on_open_documentation_confirmation(self,uri); +} + +/**on_about() + * [EN] + * Function for setting up and showing AboutDialog. + * Connect it to "activate" signal of Documentation MenuItem. + * [RU] + * Функиця для настройки и показа окна AboutDialog. + * Присоединять к сигналу "activate" кнопки справки типа MenuItem. +*/ +void on_about(){ + GtkBuilder *builder=gtk_builder_new_from_resource(glade_path); + GtkWidget *window=yon_gtk_builder_get_widget(builder,"AboutWindow"); + GtkWidget *title=yon_gtk_builder_get_widget(builder,"headerAboutTopic"); + GtkWidget *hideButtonBox=yon_gtk_builder_get_widget(builder,"buttonBoxHide"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(window),version_application); + gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(window),PROJECT_HOME_LABEL); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(window),TITLE_LABEL); + gtk_label_set_text(GTK_LABEL(title),TITLE_LABEL); + g_signal_connect(G_OBJECT(window),"activate-link",G_CALLBACK(on_link),NULL); + gtk_widget_set_visible(hideButtonBox,0); + gtk_widget_destroy(hideButtonBox); + gtk_widget_show(window); +} + +//functions + +void yon_load_proceed(YON_CONFIG_TYPE type){ + if (yon_config_load_register(type,"keyboard","XkbModel","keyboard","XkbLayout","keyboard","KEYBOARD","keyboard","KEYTABLE","keyboard","GRP_TOGGLE","keyboard","XkbOptions",NULL)) + yon_ubl_status_box_render(LOCAL_SAVE_SUCCESS_LABEL,BACKGROUND_IMAGE_SUCCESS_TYPE); + else + yon_ubl_status_box_render(LOAD_FAILED_LABEL,BACKGROUND_IMAGE_FAIL_TYPE); + +} + +void on_num_lock_changed(GtkComboBox *self, main_window *widgets){ + switch (gtk_combo_box_get_active(self)){ + case 0: + yon_config_remove_by_key(num_lock_boot_parameter); + break; + case 1: + if (yon_config_get_by_key(num_lock_boot_parameter)) + yon_config_set(num_lock_boot_parameter,"yes"); + else yon_config_register(num_lock_boot_parameter,"config","yes"); + break; + case 2: + if (yon_config_get_by_key(num_lock_boot_parameter)) + yon_config_set(num_lock_boot_parameter,"no"); + else yon_config_register(num_lock_boot_parameter,"config","no"); + break; + } +} + +void on_model_changed(GtkComboBoxText *self, main_window *widgets){ + switch (gtk_combo_box_get_active(GTK_COMBO_BOX(self))){ + case 0: + yon_config_remove_by_key(model_parameter); + break; + default: + char *id; + GtkTreeIter iter; + gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widgets->ModelCombo),&iter); + gtk_tree_model_get(GTK_TREE_MODEL(widgets->modelsList),&iter,0,&id,-1); + if (yon_config_get_by_key(model_parameter)) + yon_config_set(model_parameter,id); + else yon_config_register(model_parameter,"keyboard",id); + break; + } + +} + +void on_options_accept(GtkWidget *self, dictionary *dict){ + main_window *widgets = yon_dictionary_get_data(dict->first,main_window*); + layouts_window *window = yon_dictionary_get_data(dict->first->next,layouts_window*); + GtkTreeModel *model = GTK_TREE_MODEL(window->list); + GtkTreeIter iter; + char *name; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(window->MainTree)),&model,&iter)){ + gtk_tree_model_get(model,&iter,0,&name,-1); + gtk_entry_set_text(GTK_ENTRY(widgets->OptionsEntry),name); + } + on_close_subwindow(self); +} + +void on_options_open(GtkWidget *self, main_window *widgets){ + GtkBuilder *builder = gtk_builder_new_from_resource(glade_layouts_path); + layouts_window *window = malloc(sizeof(layouts_window)); + window->Window = yon_gtk_builder_get_widget(builder,"Window"); + window->AcceptButton = yon_gtk_builder_get_widget(builder,"AcceptButton"); + window->CancelButton = yon_gtk_builder_get_widget(builder,"CancelButton"); + window->MainTree = yon_gtk_builder_get_widget(builder,"LayoutsTree"); + window->list = GTK_LIST_STORE(gtk_builder_get_object(builder,"liststore1")); + + int size; + config_str rtn = yon_config_load(get_options_command,&size); + GtkTreeIter iter; + for (int i=0; ilist,&iter); + gtk_list_store_set(window->list,&iter,0,option[0],1,option[1],-1); + + } + dictionary *dict = NULL; + yon_dictionary_add_or_create_if_exists_with_data(dict,"widgets",widgets); + yon_dictionary_add_or_create_if_exists_with_data(dict,"window",window); + g_signal_connect(G_OBJECT(window->CancelButton),"clicked",G_CALLBACK(on_close_subwindow),NULL); + g_signal_connect(G_OBJECT(window->AcceptButton),"clicked",G_CALLBACK(on_options_accept),dict); +} + +void on_layouts_accept(GtkWidget *self, dictionary *dict){ + main_window *widgets = yon_dictionary_get_data(dict->first,main_window*); + layouts_window *window = yon_dictionary_get_data(dict->first->next,layouts_window*); + GtkTreeModel *model = GTK_TREE_MODEL(window->list); + GList *list = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(window->MainTree)),&model); + char *name; + char *id; + GtkTreeIter iter, lwiter; + GtkTreePath *pth; + for (int i=0;ilayoutsList,&iter); + gtk_tree_model_get(model,&lwiter,0,&name,1,&id,-1); + gtk_list_store_set(widgets->layoutsList,&iter,1,name,0,id,-1); + } + on_close_subwindow(self); +} + +void on_layouts_add(GtkWidget *self, main_window *widgets){ + GtkBuilder *builder = gtk_builder_new_from_resource(glade_layouts_path); + layouts_window *window = malloc(sizeof(layouts_window)); + window->Window = yon_gtk_builder_get_widget(builder,"Window"); + window->AcceptButton = yon_gtk_builder_get_widget(builder,"AcceptButton"); + window->CancelButton = yon_gtk_builder_get_widget(builder,"CancelButton"); + window->MainTree = yon_gtk_builder_get_widget(builder,"LayoutsTree"); + window->list = GTK_LIST_STORE(gtk_builder_get_object(builder,"liststore1")); + int size,laysize; + GtkTreeIter iter; + config_str rtn = yon_config_load(get_layouts_command,&size); + for (int i=0; ilist,&iter); + gtk_list_store_set(window->list,&iter,0,layout[0],1,layout[1],-1); + } + gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(window->MainTree)),GTK_SELECTION_MULTIPLE); + + dictionary *dict = NULL; + yon_dictionary_add_or_create_if_exists_with_data(dict,"widgets",widgets); + yon_dictionary_add_or_create_if_exists_with_data(dict,"window",window); + + g_signal_connect(G_OBJECT(window->CancelButton),"clicked",G_CALLBACK(on_close_subwindow),NULL); + g_signal_connect(G_OBJECT(window->AcceptButton),"clicked",G_CALLBACK(on_layouts_accept),dict); +} + +void on_layouts_remove(GtkWidget *self, main_window *widgets){ + GtkTreeModel *model = GTK_TREE_MODEL(widgets->layoutsList); + GtkTreeIter iter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widgets->LayoutsTree)),&model,&iter)){ + gtk_list_store_remove(widgets->layoutsList,&iter); + } +} + +void on_move_up(GtkWidget *self, main_window *widgets){ + GtkTreeModel *model = GTK_TREE_MODEL(widgets->layoutsList); + GtkTreeIter iter,*previter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widgets->LayoutsTree)),&model,&iter)){ + previter = gtk_tree_iter_copy(&iter); + if (gtk_tree_model_iter_previous(model,previter)) + gtk_list_store_move_before(widgets->layoutsList,&iter,previter); + } +} + +void on_move_down(GtkWidget *self, main_window *widgets){ + GtkTreeModel *model = GTK_TREE_MODEL(widgets->layoutsList); + GtkTreeIter iter,*nextiter; + if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(widgets->LayoutsTree)),&model,&iter)){ + nextiter = gtk_tree_iter_copy(&iter); + if (gtk_tree_model_iter_next(model,nextiter)) + gtk_list_store_move_after(widgets->layoutsList,&iter,nextiter); + } + +} + + + +// standard functions + +void config_init(){ + main_config.always_open_documentation=0; + main_config.win_height=0; + main_config.win_width=0; + main_config.win_pos_x=0; + main_config.win_pos_y=0; + main_config.socket_id=-1; + main_config.save_socket_id=-1; + main_config.load_socket_id=-1; + main_config.lock_help=0; + main_config.lock_help=0; + main_config.lock_load_global=0; + main_config.lock_save_global=0; + main_config.lock_save_local=0; +} + +main_window *setup_window(){ + /* Widgets getting | Получение виджетов */ + main_window *widgets = malloc(sizeof(main_window)); + GtkBuilder *builder = gtk_builder_new_from_resource(glade_path); + widgets->Window = yon_gtk_builder_get_widget(builder,"MainWindow"); + widgets->HatLabel = yon_gtk_builder_get_widget(builder,"headerTopic"); + widgets->PlugBox = yon_gtk_builder_get_widget(builder,"plugBox"); + + widgets->HeadOverlay = yon_gtk_builder_get_widget(builder,"HeadOverlay"); + widgets->HeadImage = yon_gtk_builder_get_widget(builder,"HeadBackgroundImage"); + widgets->HeadBox = yon_gtk_builder_get_widget(builder,"HeaderBox"); + widgets->HeadTitleLabel = yon_gtk_builder_get_widget(builder,"HeaderTitleLabel"); + widgets->HeadInfoLabel = yon_gtk_builder_get_widget(builder,"HeaderInfoLabel"); + + widgets->StatusBox = yon_gtk_builder_get_widget(builder,"mainStatusBox"); + widgets->StatusIcon = yon_gtk_builder_get_widget(builder,"mainStatusIcon"); + widgets->StatusLabel = yon_gtk_builder_get_widget(builder,"mainStatusLabel"); + + widgets->SaveLabel = yon_gtk_builder_get_widget(builder,"headerSaveConfigLabel"); + widgets->SaveMenuItem = yon_gtk_builder_get_widget(builder,"SaveGlobalLocalConfigurationMenuItem"); + widgets->SaveGlobalMenuItem = yon_gtk_builder_get_widget(builder,"SaveGlobalConfigurationMenuItem"); + widgets->SaveLocalMenuItem = yon_gtk_builder_get_widget(builder,"SaveLocalConfigurationMenuItem"); + widgets->RightBox = yon_gtk_builder_get_widget(builder,"HeaderRightBox"); + + widgets->LoadLabel = yon_gtk_builder_get_widget(builder,"headerLoadConfigLabel"); + widgets->LoadGlobalMenuItem = yon_gtk_builder_get_widget(builder,"LoadGlobalConfigurationMenuItem"); + widgets->LoadLocalMenuItem = yon_gtk_builder_get_widget(builder,"LoadLocalConfigurationMenuItem"); + widgets->LeftBox = yon_gtk_builder_get_widget(builder,"HeaderLeftBox"); + + widgets->NumLockCombo = yon_gtk_builder_get_widget(builder,"NumlockCombo"); + widgets->ModelCombo = yon_gtk_builder_get_widget(builder,"ModelCombo"); + widgets->keyboard = yon_gtk_builder_get_widget(builder,"keyboard"); + widgets->keytable = yon_gtk_builder_get_widget(builder,"keytable"); + widgets->grp_toggle = yon_gtk_builder_get_widget(builder,"grp_toggle"); + widgets->OptionsEntry = yon_gtk_builder_get_widget(builder,"OptionsEntry"); + widgets->OptionsButton = yon_gtk_builder_get_widget(builder,"OptionsButton"); + widgets->LayoutsTree = yon_gtk_builder_get_widget(builder,"LayoutsTree"); + widgets->MoveUpButton = yon_gtk_builder_get_widget(builder,"MoveUpButton"); + widgets->MoveDownButton = yon_gtk_builder_get_widget(builder,"MoveDownButton"); + widgets->AddButton = yon_gtk_builder_get_widget(builder,"AddButton"); + widgets->RemoveButton = yon_gtk_builder_get_widget(builder,"RemoveButton"); + widgets->layoutsList = GTK_LIST_STORE(gtk_builder_get_object(builder,"liststore1")); + widgets->modelsList = GTK_LIST_STORE(gtk_builder_get_object(builder,"liststore2")); + + widgets->DocumentationMenuItem = yon_ubl_menu_item_documentation_new(DOCUMENTATION_LABEL); + widgets->AboutMenuItem = yon_ubl_menu_item_about_new(ABOUT_LABEL); + + gtk_window_set_title(GTK_WINDOW(widgets->Window),TITLE_LABEL); + + GtkWidget *menu = yon_gtk_builder_get_widget(builder,"menu2"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu),widgets->DocumentationMenuItem); + gtk_menu_shell_append(GTK_MENU_SHELL(menu),widgets->AboutMenuItem); + + if (main_config.lock_load_global == 1){ + gtk_widget_set_sensitive(widgets->LoadGlobalMenuItem,0); + } + if (main_config.lock_save_global == 1){ + gtk_widget_set_sensitive(widgets->SaveGlobalMenuItem,0); + gtk_widget_set_sensitive(widgets->SaveMenuItem,0); + } + if (main_config.lock_save_local == 1){ + gtk_widget_set_sensitive(widgets->SaveLocalMenuItem,0); + gtk_widget_set_sensitive(widgets->SaveMenuItem,0); + } + + int size; + GtkTreeIter iter; + config_str models = yon_config_load(get_models_command,&size); + for (int i=0;imodelsList,&iter); + gtk_list_store_set(widgets->modelsList,&iter,0,models[i],1,models[i+1],-1); + } + + /* Widget registration for config monitoring | Регистрация виджетов для мониторинга конфига */ + // yon_window_config_add_custom_parameter(widgets->HeadInfoLabel,"head-text","label",YON_TYPE_STRING); + + /* Signal connection | Присоединение сигналов */ + g_signal_connect(G_OBJECT(widgets->DocumentationMenuItem),"activate",G_CALLBACK(on_open_documentation_confirmation),WIKI_LINK); + g_signal_connect(G_OBJECT(widgets->AboutMenuItem),"activate",G_CALLBACK(on_about),NULL); + + g_signal_connect(G_OBJECT(widgets->AddButton),"clicked",G_CALLBACK(on_layouts_add),widgets); + g_signal_connect(G_OBJECT(widgets->RemoveButton),"clicked",G_CALLBACK(on_layouts_remove),widgets); + g_signal_connect(G_OBJECT(widgets->ModelCombo),"changed",G_CALLBACK(on_model_changed),widgets); + g_signal_connect(G_OBJECT(widgets->MoveDownButton),"clicked",G_CALLBACK(on_move_down),widgets); + g_signal_connect(G_OBJECT(widgets->MoveUpButton),"clicked",G_CALLBACK(on_move_up),widgets); + g_signal_connect(G_OBJECT(widgets->OptionsButton),"clicked",G_CALLBACK(on_options_open),widgets); + g_signal_connect(G_OBJECT(widgets->NumLockCombo),"changed",G_CALLBACK(on_num_lock_changed),NULL); + + + gtk_widget_show(widgets->Window); + return widgets; +} + +int main(int argc, char *argv[]){ + local=setlocale(LC_ALL, ""); + textdomain (LocaleName); + config_init(); + int option_index=0; + int show_help=0; + int debug_mode=0; + { + struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'V'}, + {"lock-help", 0,0, 1}, + {"lock-save", 0,0, 2}, + {"lock-save-local", 0,0, 3}, + {"lock-save-global", 0,0, 4}, + {"lock-load-global", 0,0, 5}, + {"socket-id", 1, 0, 's'}, + {"socket-ext-id", 1,0, 'e'}, + {"socket-trd-id", 1,0, 't'}, + {"debug", 0,0, 'd'}, + { NULL, 0, NULL, 0 } + }; + for (int i=0;iHeadOverlay,widgets->HeadBox,widgets->HeadImage,banner_path); + + yon_ubl_status_box_setup(widgets->StatusIcon,widgets->StatusBox,widgets->StatusLabel); + if (getuid()!=0) + yon_ubl_status_box_render(ROOT_WARNING_LABEL,BACKGROUND_IMAGE_FAIL_TYPE); + else + yon_ubl_status_box_render(TITLE_LABEL,BACKGROUND_IMAGE_SUCCESS_TYPE); + yon_ubl_setup_sockets(widgets->PlugBox,widgets->LeftBox,widgets->RightBox,main_config.socket_id,main_config.load_socket_id,main_config.save_socket_id); + yon_window_config_setup(GTK_WINDOW(widgets->Window)); + yon_window_config_load(config_path); + GtkCssProvider *css=gtk_css_provider_new(); + gtk_css_provider_load_from_resource(css,CssPath); + gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), + GTK_STYLE_PROVIDER(css), + -1); + gtk_main(); +} \ No newline at end of file diff --git a/source/ubl-settings-keyboard.h b/source/ubl-settings-keyboard.h new file mode 100644 index 0000000..29c2975 --- /dev/null +++ b/source/ubl-settings-keyboard.h @@ -0,0 +1,136 @@ +#include +#include +#include "ubl-utils.h" +#include +#include +#include +#include +#include +#include +#include +#include "../compile/ubl-cmake.h" +#ifdef WEBKIT_FOUND + #include +#endif +#include "ubl-strings.h" + +#define WIKI_LINK "https://wiki.ublinux.ru/ru/Программное_обеспечение/Программы_и_утилиты/Все/ubl-settings-keyboard" + +#define _(String) gettext(String) + +#define glade_path "/com/ublinux/ui/ubl-settings-keyboard.glade" +#define glade_layouts_path "/com/ublinux/ui/ubl-settings-keyboard-layouts.glade" +#define glade_options_path "/com/ublinux/ui/ubl-settings-keyboard-options.glade" +#define banner_path "/com/ublinux/images/ubl-settings-keyboard-banner.png" +#define CssPath "/com/ublinux/css/ubl-settings-keyboard.css" +#define config_path yon_char_unite(yon_ubl_user_get_home_directory(),"/.config/",LocaleName,"/",LocaleName,".conf",NULL) + +#define hostname_parameter "HOSTNAME" +#define model_parameter "XkbModel" +#define keyboard_layout_parameter "XkbLayout" +#define console_font_parameter "CONSOLE_FONT" +#define num_lock_boot_parameter "NUMLOCK" +#define language_parameter "LANG" + +#define get_options_command "grep \"grp:.*toggle\" /usr/share/X11/xkb/rules/base.lst|sed -e 's/^ *//g' -e 's/\t//g' -e 's/toggle */toggle;/g'" +#define get_models_command "sed '/<\\/modelList>/q' /usr/share/X11/xkb/rules/base.xml | grep -E '^ {8,8}|^ {8,8}'|sed -e 's/ *//g' -e 's,,,g' -e 's/ *//g' -e 's,,,g'" +#define get_layouts_command "grep '' /usr/share/ubl-settings-keyboard/csv/layouts.csv" + +#define LocalePath "/usr/share/locale" +#define LocaleName "ubl-settings-keyboard" +typedef char* string; +string version_application; + +char *local; + +typedef struct { + int always_open_documentation; + int win_pos_x; + int win_pos_y; + int win_width; + int win_height; + + int socket_id; + int load_socket_id; + int save_socket_id; + + int lock_help; + int lock_save_local; + int lock_save_global; + int lock_load_global; +} config; + +typedef struct { + //Standard + GtkWidget *Window; + GtkWidget *HatLabel; + GtkWidget *PlugBox; + + GtkWidget *HeadOverlay; + GtkWidget *HeadImage; + GtkWidget *HeadBox; + GtkWidget *HeadTitleLabel; + GtkWidget *HeadInfoLabel; + + GtkWidget *StatusBox; + GtkWidget *StatusIcon; + GtkWidget *StatusLabel; + + GtkWidget *SaveLabel; + GtkWidget *SaveMenuItem; + GtkWidget *SaveGlobalMenuItem; + GtkWidget *SaveLocalMenuItem; + GtkWidget *RightBox; + + GtkWidget *LoadLabel; + GtkWidget *LoadGlobalMenuItem; + GtkWidget *LoadLocalMenuItem; + GtkWidget *LeftBox; + + GtkWidget *DocumentationMenuItem; + GtkWidget *AboutMenuItem; + // Custom + GtkWidget *NumLockCombo; + GtkWidget *ModelCombo; + GtkWidget *keyboard; + GtkWidget *keytable; + GtkWidget *grp_toggle; + GtkWidget *OptionsEntry; + GtkWidget *OptionsButton; + GtkWidget *LayoutsTree; + GtkWidget *MoveUpButton; + GtkWidget *MoveDownButton; + GtkWidget *AddButton; + GtkWidget *RemoveButton; + GtkListStore *layoutsList; + GtkListStore *modelsList; +} main_window; + + +typedef struct { + GtkWidget *Window; + + GtkWidget *HatText; + GtkWidget *HeaderText; + GtkWidget *InfoText; + GtkWidget *AlwaysOpenCheck; + + GtkWidget *CloseButton; + GtkWidget *AcceptButton; +} documentation_confirmation_window; + +typedef struct { + GtkWidget *Window; + GtkWidget *MainTree; + GtkWidget *CancelButton; + GtkWidget *AcceptButton; + GtkListStore *list; +} layouts_window; + +typedef struct { + GtkWidget *Window; + GtkWidget *CancelButton; + GtkWidget *AcceptButton; +} options_window; + +main_window *setup_window(); \ No newline at end of file diff --git a/source/ubl-strings.h b/source/ubl-strings.h new file mode 100644 index 0000000..5be35fc --- /dev/null +++ b/source/ubl-strings.h @@ -0,0 +1,38 @@ +#define VERSION_LABEL yon_char_unite(_("Version:")," ",version_application,"\n",NULL) +#define HELP_LABEL yon_char_unite(_("ubl-settings-keyboard version:")," ", version_application,"\n",TITLE_LABEL,"\n",_("Usage:"), " ubl-settings-keyboard ",_("[OPTIONS]"),"\n",_("Options:"),"\n\t--help, -h\t\t\t",_("Show this help"),"\n\t--version, -V\t\t\t",_("Show package version"),"\n\t--lock-help\t\t\t",_("Lock this help menu"),"\n\t--lock-save\t\t\t",_("Lock configuration saving"),"\n\t--lock-save-local\t\t",_("Lock local configration saving"),"\n\t--lock-save-global\t\t",_("Lock global configration saving"),"\n\t--lock-load-global\t\t",_("Lock global configration loading"),"\n",NULL) + +#define TITLE_LABEL _("Keyboard") +#define TITLE_INFO_LABEL _("Keyboard configuration") + +#define SUCCESS_LABEL _("Operation succeeded") +#define ROOT_WARNING_LABEL _("Warning! Application was launched without root - root-dependent actions are locked") + +#define ABOUT_LABEL _("About") +#define DOCUMENTATION_LABEL _("Documentation") + +#define SAVE_LOCAL_LABEL _("Save to local configuration") +#define SAVE_GLOBAL_LABEL _("Save to global configuration") +#define SAVE_CONFIGURATION_LABEL _("Save configuration") +#define SAVE_LABEL _("Save") + +#define LOAD_LOCAL_LABEL _("Load local configuration") +#define LOAD_GLOBAL_LABEL _("Load global configuration") +#define LOAD_LABEL _("Load") + +#define CANCEL_LABEL _("Cancel") + +#define HELP_TITLE_LABEL _("Would you like to read documentation in the Web?") +#define HELP_INFO_LABEL _("You will be redirected to documentation website where documentation is\ntranslated and supported by community.") +#define HELP_ALWAYS_OPEN_LABEL _("Always redirect to online documentation") +#define OPEN_HELP_LABEL _("Open documentation") +#define PROJECT_HOME_LABEL _("Project Home Page") +#define NOTHING_CHOSEN_LABEL _("Nothing were chosen") + + +#define GLOBAL_LOAD_SUCCESS_LABEL _("Global configuration loading succseeded.") +#define LOCAL_LOAD_SUCCESS_LABEL _("Local configuration loading succseeded.") +#define LOAD_FAILED_LABEL _("Config loading failed") + +#define GLOBAL_LOCAL_SAVE_SUCCESS_LABEL _("Local and global configuration saving succseeded.") +#define GLOBAL_SAVE_SUCCESS_LABEL _("Global configuration saving succseeded.") +#define LOCAL_SAVE_SUCCESS_LABEL _("Local configuration saving succseeded.") \ No newline at end of file diff --git a/source/ubl-utils.c b/source/ubl-utils.c new file mode 100644 index 0000000..c5a6551 --- /dev/null +++ b/source/ubl-utils.c @@ -0,0 +1,2041 @@ +#include "ubl-utils.h" + +// dictionary functions + +/**yon_dictionary_new(): + * [EN] + * Creates and returns empty dictionary + * [RU] + * Создаёт и возвращает пустой словарь. + */ +dictionary *yon_dictionary_new() +{ + dictionary *dict = malloc(sizeof(dictionary)); + dict->data = NULL; + dict->key = NULL; + dict->next = NULL; + dict->prev = NULL; + dict->first = dict; + dict->data_type = DICTIONARY_OTHER_TYPE; + return dict; +} + +/**yon_dictionary_copy(dictionary *dict) + * [EN] + * + * [RU] + * Создаёт и возвращает копию элемента словаря [dict] +*/ +dictionary *yon_dictinoary_copy(dictionary *dict){ + dictionary *dct = yon_dictionary_new_with_data(dict->key,dict->data); + dct->data_type= dict->data_type; + return dct; +} + +/**yon_dictionary_copy_deep(dictionary *dict) + * [EN] + * + * [RU] + * Создаёт полную копию словаря [dict] и возвращает первый элемент +*/ +dictionary *yon_dictionary_copy_deep(dictionary *dict){ + dictionary *dct = NULL; + dictionary *newone=NULL; + for_dictionaries(dct,dict){ + yon_dictionary_add_or_create_if_exists_with_data(newone,dct->key,dct->data); + newone->data_type=dct->data_type; + } + return newone->first; +} + +/**int yon_dictionary_set_data(dictionary *dict, void *data) + * [EN] + * + * [RU] + * Установить элементу словаря [dict] значение [data] +*/ +int yon_dictionary_set_data(dictionary *dict, void *data){ + dict->data=data; +} + +/**int yon_dictionary_set_key(dictionary *dict, char *key) + * [EN] + * + * [RU] + * Изменяет ключ элемента словаря [dict] на [key] +*/ +int yon_dictionary_set_key(dictionary *dict, char *key){ + dict->key=key; + return 1; +} + +/** int yon_dictionary_set(dictionary *dict, char *key, void *data) + * [EN] + * + * [RU] +* Устанавливает значение ключа элемента словаря [dict] на [key] и его данные на [data] +*/ +int yon_dictionary_set(dictionary *dict, char *key, void *data){ + dict->key=key; + dict->data=data; + return 1; +} + +/**int yon_dictionary_empty(dictionary *dict) + * [EN] + * + * [RU] + * Очищает элемент словаря [dict] от данных +*/ +int yon_dictionary_empty(dictionary *dict){ + dict->data=NULL; + dict->data_type=DICTIONARY_OTHER_TYPE; + return 1; +} + +/**yon_dictionary_switch_to_last(dictionary **dict) + * [EN] + * + * [RU] + * Переключает словарь [dict] на последний элемент. +*/ +void yon_dictionary_switch_to_last(dictionary **dict) +{ + dictionary *dct=NULL, *dact=*dict; + for_dictionaries(dct,dact); +} + +/**yon_dictionary_create_conneced(dictionary *targetdict) + * [EN] + * + * [RU] + * Создаёт новый элемент словаря [targetdict] +*/ +dictionary *yon_dictionary_append(dictionary *targetdict) +{ + targetdict = yon_dictionary_get_last(targetdict); + targetdict->next = yon_dictionary_new(); + targetdict->next->prev = targetdict; + targetdict->next->first = targetdict->first; + targetdict->next->data_type = DICTIONARY_OTHER_TYPE; + return targetdict->next; +} + +/**yon_dictionary_get_last(dictionary *dict) + * [EN] + * + * [RU] + * Возвращает последний элемент словаря [dict]. + * В отличае от yon_dictionary_switch_to_last() + * словарь [dict] остаётся на прежнем элементе. +*/ +dictionary *yon_dictionary_get_last(dictionary *dict) +{ + if (dict->next){ + dictionary *dct = NULL; + for_dictionaries(dct,dict); + return dct; + } else return dict; +} + +/**yon_dictionary_switch_places(dictionary *dict, int aim) + * [EN] + * + * [RU] + * Меняет элемент словаря [dict] местами с другим элементом. + * если [aim]<0 элемент меняется местами с левым элементом; + * если [aim]>0 элемент меняется местами с правым элементом; +*/ +dictionary *yon_dictionary_swap(dictionary *dict, int aim) +{ + if (aim < 0) + { + if (dict->prev) + { + if (dict->prev->prev) + { + dictionary *next = dict->next, *prev = dict->prev, *preprev = prev->prev; + if (next) + { + preprev->next = dict; + dict->prev = preprev; + dict->next = prev; + prev->prev = dict; + prev->next = next; + next->prev = prev; + } + else + { + preprev->next = dict; + dict->prev = preprev; + dict->next = prev; + prev->prev = dict; + prev->next = NULL; + } + return prev; + } + else + { + dictionary *next = dict->next, *prev = dict->prev; + if (next) + { + yon_dictionary_make_first(dict); + dict->prev = NULL; + dict->next = prev; + prev->prev = dict; + prev->next = next; + next->prev = prev; + } + else + { + dict->prev = NULL; + dict->next = prev; + prev->prev = dict; + prev->next = NULL; + } + return prev; + } + } + } + else if (aim > 0) + { + if (dict->next) + { + if (dict->next->next) + { + dictionary *next = dict->next, *prev = dict->prev, *afnext = next->next; + if (prev) + { + prev->next = next; + next->prev = prev; + next->next = dict; + dict->prev = next; + dict->next = afnext; + afnext->prev = dict; + } + else + { + yon_dictionary_make_first(next); + next->prev = NULL; + next->next = dict; + dict->prev = next; + dict->next = afnext; + afnext->prev = dict; + } + return next; + } + else + { + dictionary *next = dict->next, *prev = dict->prev; + if (prev) + { + prev->next = next; + next->prev = prev; + next->next = dict; + dict->prev = next; + dict->next = NULL; + } + else + { + next->prev = NULL; + next->next = dict; + dict->prev = next; + dict->next = NULL; + } + } + } + } +} + +/**yon_dictionary_make_first(dictionary *dict) + * [EN] + * + * [RU] + * Устанавливает указатель первого элемента словаря [dict] + * на текущий элемент. Не использовать. +*/ +void yon_dictionary_make_first(dictionary *dict) +{ + for (dictionary *dct = dict->first; dct != NULL; dct = dct->next) + { + dct->first = dict; + } +} + +/**yon_dictionary_make_nth(dictionary *dict, int nth) + * [EN] + * + * [RU] + * Перемещает элемент словаря [dict] на позицию [nth]. +*/ +void yon_dictionary_make_nth(dictionary *dict, int nth) +{ + dictionary *dct = dict->first; + for (int i = 0; i < nth; i++) + { + if (dct == NULL) + return; + else + dct = dct->next; + } + yon_dictionary_rip(dict); + dictionary *prev = dct->prev; + prev->next = dict; + dict->prev = prev; + dict->next = dct; + dct->prev = dict; +} + +/**yon_dictionary_create_with_data(char *key, void *data) + * [EN] + * + * [RU] + * Создаёт новый словарь с ключом [key] и указателем на данные [data] +*/ +dictionary *yon_dictionary_new_with_data(char *key, void *data) +{ + dictionary *dct = yon_dictionary_new(); + dct->key = yon_char_new(key); + dct->data = data; + dct->data_type = DICTIONARY_OTHER_TYPE; + return dct; +} + +/** void *yon_dictionary_free_all(dictionary *dictionary,void *data_manipulation) + * [EN] + * Frees whole [dictionary] and activates [data_manipulation] function if not NULL with [dictionary]->data argument for each dictionary. + * [RU] + * Освобождает память для всех элементов словаря [dictionary] и активирует функцию [data_manipulation], если она была передана, с аргументом [dictionary]->data на каждый элемент словаря. +*/ +void *yon_dictionary_free_all(dictionary *dictionary_to_free,void (*data_manipulation)(void*)){ + dictionary *dict=NULL; + for_dictionaries(dict,dictionary_to_free){ + if(data_manipulation) + data_manipulation(dict->data); + if(dict->prev) + free(dict->prev); + } + free(dict); + return NULL; +} + +/**yon_dictionary_create_with_data_connected(dictionary *dict, char *key, void *data) + * [EN] + * + * [RU] + * Создаёт новый элемент словаря, присоединяемый в конец словаря [dict] + * с ключом [key] и указателем на данные [data] +*/ +dictionary *yon_dictionary_append_with_data(dictionary *dict, char *key, void *data) +{ + dictionary *dct = yon_dictionary_append(dict); + dct->key = yon_char_new(key); + dct->data = data; + dct->data_type = DICTIONARY_OTHER_TYPE; + return dct; +} + +/**yon_dictionary_connect(dictionary *old, dictionary *toconnect) + * [EN] + * + * [RU] + * Присоединяет словарь [toconnect] в конец словаря [old]. +*/ +dictionary *yon_dictionary_connect(dictionary *old, dictionary *toconnect) +{ + dictionary *dict = yon_dictionary_get_last(old); + dict->next = toconnect; + toconnect->prev = dict; + toconnect->first = dict->first; + return toconnect; +} + +/**yon_dictionary_get(dictionary **dict, char *key) + * [EN] + * + * [RU] + * Возвращает элемент словаря [dict] с ключом [key]. + * Если такого элемента не было обнаружено, возвращается NULL +*/ +dictionary *yon_dictionary_get(dictionary **dict, char *key) +{ + dictionary *dct = *dict; + for (dictionary *pointer = dct->first; pointer != NULL; pointer = pointer->next) + { + if (strcmp(pointer->key, key) == 0) + { + *dict = pointer; + return pointer; + } + } + return NULL; +} + +/**yon_dictionary_rip(dictionary *dict) + * [EN] + * + * [RU] + * Вырезает элемент из словаря и возвращает вырезанный элемент. +*/ +dictionary *yon_dictionary_rip(dictionary *dict) +{ + if (!dict->next&&!dict->prev) return NULL; + else if (!dict->next) + { + dictionary *prev = dict->prev; + if (prev) + { + prev->next = NULL; + return prev; + } + else + return dict; + } + else if (!dict->prev) + { + dictionary *next = dict->next; + if (next) + { + yon_dictionary_make_first(next); + next->prev = NULL; + return next; + } + else + return dict; + } + else + { + dictionary *next = dict->next, *prev = dict->prev; + next->prev = prev; + prev->next = next; + return next; + } +} + +/**yon_dictionary_get_nth(dictionary *dict, int place) + * [EN] + * + * [RU] + * Возвращает [place]-й элемент словаря [dict] +*/ +dictionary *yon_dictionary_get_nth(dictionary *dict, int place) +{ + if (dict){ + dict = dict->first; + int i = 0; + for (i = 0; i < place; i++) + if (dict->next) + dict = dict->next; + else + break; + if (i == place) + return dict; + else + return NULL; + } else return NULL; +} + +// char functions + +int yon_char_find_last(char *source, char find){ + int size = strlen(source); + int i=size; + for (;source[i]!=find&&i>0;i--); + return i; +} + +/**[EN] + * + * creates new char string by combining two char strings. + */ +char *yon_char_append(char *source, char *append) +{ + if (source && append) + { + int size = strlen(source) + strlen(append) + 1; + char *final = malloc(size); + memset(final, 0, size); + if (strstr(source, "%%")) + sprintf(final, source, append); + else + sprintf(final, "%s%s", source, append); + return final; + } + else + return NULL; +} + +/**[EN] + * + * creates new char string by copying another char. + */ +char *yon_char_new(char *chr) +{ + if (chr){ + char *newchar = malloc(strlen(chr) + 1); + memset(newchar, 0, strlen(chr) + 1); + memcpy(newchar, chr, strlen(chr)); + return newchar; + } else + return NULL; +} + +/**yon_char_unite(char *source, ...) + * [En] + * + * [RU] + * Объединяет строку [source] со всеми строками, написанными в [...] +*/ +char *yon_char_unite(char *source, ...){ + va_list arglist; + char *new_char=NULL; + char *unite_char=NULL; + new_char=yon_char_new(source); + va_start(arglist,source); + unite_char = va_arg(arglist,char*); + while(unite_char){ + new_char = yon_char_append(new_char,unite_char); + unite_char = va_arg(arglist,char*); + } + va_end(arglist); + return new_char; +} + +/**yon_cut(char *source, int size, int startpos) + * [EN] + * cuts source string by size length from startpos position. + */ +char *yon_cut(char *source, int size, int startpos) +{ + char *cut = NULL; + cut = malloc(size + 1); + memset(cut, 0, size + 1); + memcpy(cut, source + startpos, size); + return cut; +} + +/**yon_char_divide(char *source, int dividepos) + * [EN] + * divides source string in dividepos position, + * returning left part of divided string and + * inserting right part to source string. + */ +char *yon_char_divide(char *source, int dividepos) +{ + char *cut = malloc(dividepos + 1); + memset(cut, 0, dividepos + 1); + memcpy(cut, source, dividepos); + char *left = malloc(strlen(source) - strlen(cut)); + memset(left, 0, strlen(source) - strlen(cut)); + memcpy(left, source + dividepos + 1, (strlen(source) - dividepos)); + memset(source, 0, strlen(source)); + memcpy(source, left, strlen(left)); + return cut; +} + +/**yon_char_find_count(char *source, char *find) + * [EN] + * + * [RU] + * Считает количество символов [find] в строке [source] +*/ +int yon_char_find_count(char *source, char *find){ + char *working_string=yon_char_new(source); + int i=0; + int size=0; + int pos=0; + config_str rtn = yon_char_parse(working_string,&size,"\n"); + for (int j=0;j= 10; i++) + { + convert_check = convert_check / 10; + } + char *ch = g_malloc0(i * sizeof(char) + 1); + sprintf(ch, "%d", int_to_convert); + return ch; +} + +/**yon_char_replace(char *source, char *find, char*replace) + * [EN] + * + * [RU] + * Заменяет в строке [source] все вхождения строки [find] на [replace] +*/ +char *yon_char_replace(char *source, char *find, char*replace){ + if (!strstr(replace,find)){ + + + char *final=NULL; + char *temp=NULL; + if(!strstr(replace,find)){ + while ((final=strstr(source,find))){ + temp=malloc(strlen(source)-strlen(final)); + memset(temp,0,strlen(source)-strlen(final)+strlen(replace)); + memcpy(temp,source,strlen(source)-strlen(final)); + temp=yon_char_append(temp,replace); + source=yon_char_append(temp,final+1); + } + + } + } + return source; +} + +/**yon_char_parse(char *parameters, int *size, char *divider) + * [EN] + * Parses string [parameters], divided by [divider], + * then returns parsed string array and sets [size] to + * size of returned array +*/ +char **yon_char_parse(char *parameters, int *size, char *divider){ + char **string=NULL; + int i=1; + string=malloc(sizeof(char*)); + char *paramline=yon_char_new(parameters); + char *param; + while ((param=yon_char_divide_search(paramline,divider,1))){ + string=realloc(string,sizeof(char*)*i); + string[i-1]=yon_char_new(param); + i++; + if (strcmp(param,paramline)==0) break; + } + string=realloc(string,sizeof(char*)*i); + string[i-1]=yon_char_new(paramline); + i++; + // printf("%d\n",i); + *size=i-1; + return string; + +} + +/**yon_char_parsed_rip(char **char_string, int *size, int item_to_delete) + * [EN] + * + * [RU] + * Удаляет элемент [item_to_delete] из массива строк [char_string], размера [size] + * Возвращает получившийся массив, в [size] загружается размер нового массива. +*/ +char **yon_char_parsed_rip(char **char_string, int *size, int item_to_delete){ + char **new_char_parsed=NULL; + new_char_parsed=malloc(sizeof(char*)*((*size)-1)); + int flag = 0; + for (int i=0;i < (*size);i++){ + if (i==item_to_delete) { + flag = 1; + } + if (flag == 0) { + new_char_parsed[i]=yon_char_new(char_string[i]); + } + else if (flag == 1 && i!=item_to_delete) { + new_char_parsed[i-1]=yon_char_new(char_string[i]); + } + } + (*size)=(*size)-1; + return new_char_parsed; +} + +/**yon_char_parsed_check_exist(char **parameters, int size, char *param) + * [EN] + * Checks if [parameters] string array of length [size] + * has [param] element; + * [RU] + * Проверяет есть ли в массиве строк [parameters], размера [size] + * элемент [param] +*/ +int yon_char_parsed_check_exist(char **parameters, int size, char *param){ + + for (int i=0;id_name); + file = fopen(path, "r"); + if (strlen(de->d_name) > 9) + { + char *extension = strstr(path, "."); + if (extension != NULL) + { + if (strcmp(extension, ".desktop") == 0) + { + apps tempapp; + GKeyFile *gfile = g_key_file_new(); + GError *err = NULL; + g_key_file_load_from_file(gfile, path, G_KEY_FILE_KEEP_TRANSLATIONS, NULL); + char *Type = g_key_file_get_string(gfile, "Desktop Entry", "Type", &err); + if (err) + { + printf("%s\n", err->message); + } + if (strcmp(Type, "Application") == 0) + tempapp.Type = 1; + else if (strcmp(Type, "pyApplication") == 0) + tempapp.Type = 2; + else + continue; + tempapp.Name = g_key_file_get_locale_string(gfile, "Desktop Entry", "Name", setlocale(LC_ALL, NULL), NULL); + if (tempapp.Name == NULL) + continue; + tempapp.Categories = g_key_file_get_string(gfile, "Desktop Entry", "Categories", NULL); + if (tempapp.Categories == NULL) + continue; + tempapp.Exec = g_key_file_get_string(gfile, "Desktop Entry", "Exec", NULL); + if (tempapp.Exec == NULL) + continue; + tempapp.Icon = g_key_file_get_string(gfile, "Desktop Entry", "Icon", NULL); + if (tempapp.Icon == NULL) + continue; + tempapp.Pluggable = g_key_file_get_boolean(gfile, "Desktop Entry", "Pluggable", NULL); + if (!tempapp.Pluggable) + tempapp.Pluggable = g_key_file_get_boolean(gfile, "Desktop Entry", "X-XfcePluggable", NULL); + if (tempapp.Pluggable) + tempapp.DualPluggable = g_key_file_get_boolean(gfile, "Desktop Entry", "X-UBLPluggable", NULL); + if (g_key_file_get_boolean(gfile, "Desktop Entry", "X-UBL-SettingsManager-Hidden", NULL) == 0) + if (size == 0) + { + applist = (apps *)malloc(size + 1 * sizeof(apps)); + applist[0].Name = yon_char_new(tempapp.Name); + applist[0].Categories = yon_char_new(tempapp.Categories); + applist[0].Exec = yon_char_new(tempapp.Exec); + applist[0].Icon = yon_char_new(tempapp.Icon); + applist[0].Type = tempapp.Type; + applist[0].Pluggable = tempapp.Pluggable; + applist[0].DualPluggable = tempapp.DualPluggable; + size++; + } + else + { + applist = (apps *)realloc(applist, (size + 1) * sizeof(apps)); + applist[size].Name = yon_char_new(tempapp.Name); + applist[size].Categories = yon_char_new(tempapp.Categories); + applist[size].Exec = yon_char_new(tempapp.Exec); + applist[size].Icon = yon_char_new(tempapp.Icon); + applist[size].Pluggable = tempapp.Pluggable; + applist[size].DualPluggable = tempapp.DualPluggable; + applist[size].Type = tempapp.Type; + size++; + } + } + } + } + } + } + *sizef = size; + return applist; +}; + +void yon_apps_sort(apps *applist, int size) +{ + apps tmp; + if (size > 2) + { + for (int i = 1; i < size; i++) + { + for (int j = 1; j < size; j++) + { + if (strcmp(applist[j].Name, applist[j - 1].Name) < 0) + { + tmp = applist[j]; + applist[j] = applist[j - 1]; + applist[j - 1] = tmp; + }; + } + }; + } +}; + +apps *yon_apps_get_by_name(apps *applist, char *name, int size) +{ + for (int i = 0; i < size; i++) + { + if (strcmp(applist[i].Name, name) == 0) + return &applist[i]; + } + return NULL; +}; + +//config functions + +typedef struct yon_config_parameter +{ + char *key; + void *data; + struct yon_config_parameter *next; + struct yon_config_parameter *prev; + struct yon_config_parameter *first; + DICT_TYPE data_type; + int flag1; + char *section; +} yon_config_parameter; + +yon_config_parameter *yon_config_parameter_new_with_data(char *key, void *data){ + yon_config_parameter *param = yon_remalloc(NULL,sizeof(yon_config_parameter)); + param->data=data; + param->data_type=DICTIONARY_CHAR_TYPE; + param->first=param; + param->flag1=0; + param->key=yon_char_new(key); + param->next=NULL; + param->prev=NULL; + param->section=NULL; + return param; +} + +yon_config_parameter *yon_config_parameter_append_with_data(yon_config_parameter *dict, char *key, void *data){ + yon_config_parameter *param = yon_config_parameter_new_with_data(key,data); + param->first=dict->first; + (param->prev)=(yon_config_parameter*)yon_dictionary_get_last((dictionary*)dict); + dict->next=param; + return param; +} + + +static yon_config_parameter *__yon__config__strings = NULL; +#define check_config if(__yon__config__strings&&__yon__config__strings->data_type==DICTIONARY_CHAR_TYPE) +#define for_config dictionary temp = NULL; for_dictionary(temp,(dictionary*)__yon__config__strings) +#define yon_config_parameter_add_or_create_if_exists_with_data(dict,key,data) {if (!dict) dict=yon_config_parameter_new_with_data(key,data); \ + else dict=yon_config_parameter_append_with_data(dict,key,data);} + +/**yon_config_load_register(char *command) + * [EN] + * + * [RU] + * Выполняет команду [command]. + * Полученные данные парсятся и регистрируются в конфиг. +*/ +int yon_config_load_register(YON_CONFIG_TYPE config_type,char *section,char *parameter, ...){ + if (__yon__config__strings){ + __yon__config__strings = yon_dictionary_free_all((dictionary*)__yon__config__strings,NULL); + } + va_list args; + va_start(args,parameter); + char *arg; + dictionary *sections = NULL; + { + if (sections&&yon_dictionary_get(§ions,section)) sections->data=(void*)yon_char_unite(yon_dictionary_get_data(sections,char*)," ",parameter,NULL); + else yon_dictionary_add_or_create_if_exists_with_data(sections,section,parameter); + } + while (arg=va_arg(args,char*)){ + char *key = va_arg(args,char*); + if (sections&&yon_dictionary_get(§ions,arg)) sections->data=(void*)yon_char_unite(yon_dictionary_get_data(sections,char*)," ",key,NULL); + else yon_dictionary_add_or_create_if_exists_with_data(sections,arg,key); + } + char *command=NULL; + dictionary *dict; + for_dictionaries(dict,sections){ + command = yon_char_unite(ubconfig_load_command,config_type==YON_CONFIG_GLOBAL ? " global get " : " system get ", dict->key," ", yon_dictionary_get_data(dict,char*),NULL); + FILE *output = popen(command, "r"); + char **output_strings = NULL; + output_strings = malloc(sizeof(char*)); + int i = 0; + char str[4096]; + memset(str, 0, 4096); + while (fgets(str, 4096, output)) + { + if (strcmp(str, "") != 0&& strcmp(str,"(null)\n")!=0) + { + char *key = yon_char_divide_search(str,"=",-1); + char *final_str=yon_char_divide_search(str,"\n",-1); + yon_config_parameter_add_or_create_if_exists_with_data(__yon__config__strings,key,yon_char_new(final_str)); + __yon__config__strings->data_type=DICTIONARY_CHAR_TYPE; + __yon__config__strings->section=dict->key; + } + } + } + check_config + return 1; + else return 0; +} + +/**yon_config_remove_by_key(char *key) + * [EN] + * + * [RU] + * Удаляет параметр конфига по ключу [key] +*/ +int yon_config_remove_by_key(char *key){ + check_config{ + dictionary *dict = yon_dictionary_get((dictionary**)&__yon__config__strings,key); + if (dict){ + ((yon_config_parameter*)dict)->flag1=-1; + return 1; + }else return 0; + } + return 0; +} + +/**yon_config_remove_by_data(void *data) + * [EN] + * + * [RU] + * Производит поиск по конфигу на наличие параметра со значением [data] и удаляет найденное значение из конфига. +*/ +int yon_config_remove_by_data(void *data){ + check_config{ + dictionary *dict = NULL; + for_dictionaries(dict,(dictionary*)__yon__config__strings){ + if (dict->data==data){ + yon_dictionary_rip(dict); + return 1; + } + } + return 0; + } + return 0; +} + +/**yon_config_remove_element(char *key, char *deleted) + * [EN] + * + * [RU] + * Удаляет элемент [deleted] из массива параметров с ключом [key] +*/ +int yon_config_remove_element(char *key, char *deleted){ + check_config{ + yon_config_parameter *dict = (yon_config_parameter*)yon_dictionary_get((dictionary**)&__yon__config__strings,key); + char *data = (char*)dict->data; + char *found = strstr(data,deleted); + int size=strlen(data)-strlen(found)+1; + char *new_data = malloc(size); + memset(new_data,0,size); + if (strlen(found)!=strlen(deleted)){ + memcpy(new_data,data,size-1); + new_data = yon_char_append(new_data,found+strlen(deleted)+1); + } else { + memcpy(new_data,data,size-2); + new_data = yon_char_append(new_data,found+strlen(deleted)); + } + dict->data=(void*)(new_data); + dict->flag1=1; + return 1; + } else return 0; +} + +/**yon_config_get_by_key(char *key) + * [EN] + * + * [RU] + * Возвращает значение параметра конфига с ключом [key] +*/ +void *yon_config_get_by_key(char *key){ + check_config{ + dictionary *dict = NULL; + for_dictionaries(dict, (dictionary*)__yon__config__strings){ + if (strcmp(dict->key,key)==0){ + return dict->data; + } + } + } + return NULL; +} + +/**yon_config_get_key_by_data(char *data) + * [EN] + * + * [RU] + * Возвращает ключ параметра конфига со значением [data]. + * Если параметр с таким значением не найден, возвращается NULL +*/ +char *yon_config_get_key_by_data(char *data){ + check_config{ + dictionary *dict = NULL; + for_dictionaries(dict, (dictionary*)__yon__config__strings){ + if (strcmp(((char*)dict->data),data)==0){ + return dict->key; + } + } + } + return NULL; +} + +/**yon_config_set(char *key, void *data) + * [EN] + * + * [RU] + * Производит поиск по конфигу и заменяет значение параметра с ключом [key] на новое значение [data]; +*/ +int yon_config_set(char *key, void *data){ + check_config{ + yon_config_parameter *dict = (yon_config_parameter*)yon_dictionary_get((dictionary**)&__yon__config__strings,key); + dict->data=data; + dict->flag1=1; + return 1; + } else return 0; +} + + +/**yon_config_append(char *key, void *data) + * [EN] + * + * [RU] + * Производит поиск по конфигу и дополняет значение параметра с ключом [key] значением [data]; +*/ +int yon_config_append(char *key, char *data){ + check_config{ + yon_config_parameter *dict = (yon_config_parameter*)yon_dictionary_get((dictionary**)&__yon__config__strings,key); + if (strcmp(((char*)dict->data),"")!=0) + dict->data=(void*)(yon_char_unite((char*)dict->data," ",data,NULL)); + else dict->data=(void*)data; + dict->flag1=1; + return 1; + } else return 0; +} + + +/**yon_config_clean() + * [EN] + * Erase all parameters from config; + * [RU] + * Удаляет все параметры из конфига; +*/ +int yon_config_clean(){ + check_config{ + __yon__config__strings = (yon_config_parameter*)yon_dictionary_free_all((dictionary*)__yon__config__strings, NULL); + return 1; + } + else return 0; +} + +/**yon_config_register(char *key, void *data) + * [EN] + * + * [RU] + * Регистрирует новый параметр конфига. + * [key] - ключ параметра; + * [data] - значение параметра; +*/ +void yon_config_register(char *key, char *config_section, void *data){ + if (!__yon__config__strings||!yon_dictionary_get((dictionary**)&__yon__config__strings,key)){ + yon_config_parameter_add_or_create_if_exists_with_data(__yon__config__strings,key,data); + } + else if (yon_dictionary_get((dictionary**)&__yon__config__strings,key)) __yon__config__strings->data=data; + __yon__config__strings->data_type=DICTIONARY_CHAR_TYPE; + __yon__config__strings->flag1=1; + __yon__config__strings->section=yon_char_new(config_section); +} + +/**yon_config_load(char *command, int *str_len) + * [EN] + * + * [RU] + * Выполняет команду [command] и возвращает распаршеный результат выполнения команды. + * В [str_len] возвращается длина возвращаемого массива +*/ +config_str yon_config_load(char *command, int *str_len){ + FILE *output = popen(command, "r"); + char **output_strings = NULL; + output_strings = malloc(sizeof(char)); + int i = 0; + char str[4096]; + memset(str, 0, 4096); + while (fgets(str, 4096, output)) + { + if (strcmp(str, "") != 0) + { + output_strings = realloc(output_strings, sizeof(char *) * (i + 1)); + output_strings[i] = NULL; + output_strings[i] = yon_char_new(str); + memset(str, 0, 4096); + i++; + } + } + if (i>0){ + *str_len = i; + return output_strings; + } else{ + *str_len=-1; + return NULL; + } +} + +/**int yon_config_save_registered(char *path, char *section) + * [EN] + * Saves config with [command] + * [RU] + * Выполняет команду [command], добавляя в конец все записи конфига в таком виде: + * [ПАРАМЕТР1]="[значения1]" [ПАРАМЕТР2]="[значения2]" +*/ +int yon_config_save_registered(char *path, char *section){ + check_config{ + dictionary *dct; + dictionary *sections_add=NULL; + dictionary *sections_remove=NULL; + for_dictionaries(dct,(dictionary*)__yon__config__strings){ + if (dct->data&&strcmp(yon_dictionary_get_data(dct,char*),"")!=0){ + if (((yon_config_parameter*)dct)->flag1==1){ + ((yon_config_parameter*)dct)->flag1=0; + if (sections_add&&yon_dictionary_get(§ions_add,((yon_config_parameter*)dct)->section)) sections_add->data=(void*)yon_char_unite(yon_dictionary_get_data(sections_add,char*)," ",dct->key,"=",yon_dictionary_get_data(dct,char*),NULL); + else yon_dictionary_add_or_create_if_exists_with_data(sections_add,((yon_config_parameter*)dct)->section,yon_char_unite (ubconfig_save_command,path ? yon_char_append(" --target ",path):"", " set ", ((yon_config_parameter*)dct)->section, " ",dct->key,"=",yon_dictionary_get_data(dct,char*),NULL)); + } else if (((yon_config_parameter*)dct)->flag1==-1){ + ((yon_config_parameter*)dct)->flag1=0; + if (sections_remove&&yon_dictionary_get(§ions_remove,((yon_config_parameter*)dct)->section)) sections_remove->data=(void*)yon_char_unite(yon_dictionary_get_data(sections_remove,char*)," ",dct->key,NULL); + else yon_dictionary_add_or_create_if_exists_with_data(sections_remove,((yon_config_parameter*)dct)->section,yon_char_unite (ubconfig_save_command,path ? yon_char_append(" --target ",path):"", " remove ", ((yon_config_parameter*)dct)->section, " ",dct->key,NULL)); + } + } + } + if (sections_add) + for_dictionaries(dct,sections_add){ + char *command = yon_dictionary_get_data(dct,char*); + yon_launch(command); + } + if (sections_remove) + for_dictionaries(dct,sections_remove){ + char *command = yon_dictionary_get_data(dct,char*); + yon_launch(command); + } + + + // char *command = yon_char_unite(ubconfig_save_command,path ? yon_char_append(" --target ",path):"", " set ", section, " ", yon_dictionary_get_data(dct,char*),NULL); + // char *remove_command = yon_char_unite(ubconfig_save_command, path ? yon_char_append(" --target ",path):"", " remove "," ", yon_dictionary_get_data(dct,char*), section,NULL); + // dictionary *dict = NULL; + // int any_add = 0; + // int any_remove = 0; + // for_dictionaries(dict,(dictionary*)__yon__config__strings){ + // char *data = yon_dictionary_get_data(dict,char*); + // if (((yon_config_parameter*)dict)->flag1==1&&strcmp(data,"")!=0){ + // command = yon_char_unite(command, " ", dict->key,"=\"", yon_dictionary_get_data(dict,char*),"\"", NULL); + // any_add=1; + // } + // if (strcmp(data,"")==0){ + // remove_command = yon_char_unite(remove_command, " ", dict->key, NULL); + // any_remove=1; + // } + // } + // if (any_add) yon_launch(command); + // if (any_remove) yon_launch(remove_command); + return 1; + } else return 1; +} + +/**yon_config_get_all(int *size) + * [EN] + * + * [RU] + * Возвращает массив со всеми параметрами конфига, оканчивающаяся NULL + * [size] - указатель, в который выгружается длина массива +*/ +config_str yon_config_get_all(int *size){ + check_config{ + *size = 1; + config_str conf = NULL; + dictionary *dict = NULL; + for_dictionaries(dict,(dictionary*)__yon__config__strings){ + conf = yon_remalloc(conf,sizeof(char*)*(*size)); + conf[(*size)-1] = yon_char_unite(dict->key,"=",(char*)dict->data,NULL); + (*size)++; + } + conf = yon_remalloc(conf,sizeof(char*)*(*size)); + conf[*size-1] = NULL; + return conf; + } else return NULL; +} + +/**char *yon_config_get_parameter(config parameters, int size, char *param) + * [EN] + * Gets parameter [param] from parameter list [parameters] of size [size]; + * or NULL if nothing were found + * [RU] + * Возвращает параметр [param] из массива строк [parameters] размером [size] + * или NULL если такой не был найден +*/ +char *yon_config_get_parameter(config_str parameters, int size, char *param) +{ + if (param[0]==' ') + yon_char_divide_search(param," ",-1); + param=yon_char_divide_search(yon_char_new(param)," ",-1); + + char *str = NULL; + for (int j = 0; j < size; j++) + { + char *name = yon_char_divide_search(yon_char_new(parameters[j]), "=", 1); + if (name) + { + if (strcmp(name, param) == 0) + { + str = yon_char_divide_search(yon_char_new(parameters[j]), "\n", 1); + if (strcmp(str, "") != 0 && strcmp(str, "(null)") != 0) + return str; + else + return NULL; + } + } + } + return NULL; +} + + + +// terminal-using functions + +/**yon_launch_app_with_arguments(char *name, char *args) + * [EN] + * Execute [command] in separate thread; + * [RU] + * Выполнить команду [command] в отдельном потоке; +*/ +int yon_launch_app_with_arguments(char *name, char *args) +{ + char *path = yon_char_unite("/usr/bin/", name, " ", args,NULL); + pthread_t thread_id; + char *command = NULL; + command = path; + pthread_create(&thread_id, NULL, (void *)yon_launch, command); +}; + +/**yon_launch(char *command) + * [EN] + * Execute command [command] + * [RU] + * Выполнить команду [command] +*/ +void yon_launch(char *command) +{ + system(command); +} + +// Gtk functions + + +#ifdef __GTK_H__ + + +static render_data render; + +#ifdef VTE_TERMINAL + +static void child_ready(VteTerminal *terminal, GPid pid, GError *error, gpointer user_data) +{ + if (!terminal) return; + if (pid == -1) printf("Error\n\n\n"); + else vte_terminal_feed_child(VTE_TERMINAL(terminal),(char*)user_data,strlen((char*)user_data)); +} + +/** + * void yon_terminal_integrated_launch(GtkWidget *place_to_show, void *endwork_function, void* endwork_function_argument) + * [EN] + * launches terminal with specific [command], + * terminal is shown in [place_to_show] container, + * after terminal done its work [endwork_function] is called with [endwork_function_argument] argument. + * [RU] + * Запускает терминал с командой [command], + * терминал добавляется в контейнер [place_to_show] виджета, + * после завершения работы терминала вызывается функция [endwork_function] с аргументом [endwork_function_argument]. +*/ +void yon_terminal_integrated_launch(GtkWidget *place_to_show, char* command, void *endwork_function, void* endwork_function_argument){ + char **commands=new_arr(char*,2); + gchar **envp = g_get_environ(); + commands[0]=(gchar *)g_strdup(g_environ_getenv(envp, "SHELL")); + commands[1]=NULL; + char **env=new_arr(char*,2); + env[0]=""; + env[1]=NULL; + GtkWidget *terminal = vte_terminal_new(); + vte_terminal_set_size(VTE_TERMINAL(terminal),10,15); + VtePty *pty = vte_pty_new_sync(VTE_PTY_DEFAULT,NULL,NULL); + vte_terminal_set_pty(VTE_TERMINAL(terminal),pty); + gtk_container_add(GTK_CONTAINER(place_to_show),terminal); + char *install_command=yon_char_unite("tput cup 0 0 && tput ed; ",command," ; sleep 5;exit 0","\n",NULL); + printf("%s\n",install_command); + if(endwork_function) + g_signal_connect(G_OBJECT(terminal), "child-exited", G_CALLBACK(endwork_function), endwork_function_argument); + vte_terminal_spawn_async(VTE_TERMINAL(terminal), + VTE_PTY_DEFAULT, + NULL, + commands, + NULL, + 0, + NULL, NULL, + NULL, + -1, + NULL, + child_ready, + install_command); + vte_pty_spawn_async(pty, + NULL, + commands, + NULL, + 0, + NULL, NULL, + NULL, + -1, + NULL, + NULL, + NULL); + vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), -1); + vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), TRUE); + vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE); + gtk_widget_show_all(terminal); + } + +/**yon_terminal_integrated_start(GtkWidget *terminal, char* command, void *endwork_function, void* endwork_function_argument) + * [EN] + * launches terminal with specific [command], + * terminal is shown in [place_to_show] container, + * after terminal done its work [endwork_function] is called with [endwork_function_argument] argument. + * [RU] + * Запускает терминал с командой [command], + * терминал добавляется в контейнер [place_to_show] виджета, + * после завершения работы терминала вызывается функция [endwork_function] с аргументом [endwork_function_argument]. +*/ +void yon_terminal_integrated_start(GtkWidget *terminal, char* command, void *endwork_function, void* endwork_function_argument){ + char **commands=new_arr(char*,2); + gchar **envp = g_get_environ(); + commands[0]=(gchar *)g_strdup(g_environ_getenv(envp, "SHELL")); + commands[1]=NULL; + char **env=new_arr(char*,2); + env[0]=""; + env[1]=NULL; + vte_terminal_set_size(VTE_TERMINAL(terminal),10,15); + VtePty *pty = vte_pty_new_sync(VTE_PTY_DEFAULT,NULL,NULL); + vte_terminal_set_pty(VTE_TERMINAL(terminal),pty); + char *install_command=yon_char_unite("tput cup 0 0 && tput ed; ",command," ; sleep 5;exit 0","\n",NULL); + if(endwork_function) + g_signal_connect(G_OBJECT(terminal), "child-exited", G_CALLBACK(endwork_function), endwork_function_argument); + vte_terminal_spawn_async(VTE_TERMINAL(terminal), + VTE_PTY_DEFAULT, + NULL, + commands, + NULL, + 0, + NULL, NULL, + NULL, + -1, + NULL, + child_ready, + install_command); + vte_pty_spawn_async(pty, + NULL, + commands, + NULL, + 0, + NULL, NULL, + NULL, + -1, + NULL, + NULL, + NULL); + vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), 100); + vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), TRUE); + vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE); + gtk_widget_show_all(terminal); + } +#endif + + // Window config functions + + #define check_window_config_setup if(__yon_window_config_target_window) + + typedef struct { + char *parameter_name; + enum YON_TYPE containing_type; + GtkWidget *track_widget; + char *property_name; + } __yon_listener_parameter; + + typedef struct { + char *parameter_name; + char *section; + enum YON_TYPE containing_type; + void *property; + } __yon_custom_parameter; + + struct { + int x; + int y; + int width; + int height; + int fullscreen; + dictionary *custom_listeners; + dictionary *custom_parameters; + dictionary *deleted_parameters; + } __yon_main_window_config; + + static GtkWindow *__yon_window_config_target_window = NULL; + static GKeyFile *__yon_window_config_file = NULL; + static char *__yon_window_config_path = NULL; + + void yon_window_config_save(){ + g_key_file_set_integer(__yon_window_config_file,"window","WindowPosX",__yon_main_window_config.x); + g_key_file_set_integer(__yon_window_config_file,"window","WindowPosY",__yon_main_window_config.y); + g_key_file_set_integer(__yon_window_config_file,"window","WindowWidth",__yon_main_window_config.width); + g_key_file_set_integer(__yon_window_config_file,"window","WindowHeight",__yon_main_window_config.height); + g_key_file_set_integer(__yon_window_config_file,"window","fullscreen",__yon_main_window_config.fullscreen); + dictionary *dict=NULL; + if (__yon_main_window_config.custom_listeners) + for_dictionaries(dict,__yon_main_window_config.custom_listeners){ + __yon_listener_parameter *param = yon_dictionary_get_data(dict,__yon_listener_parameter*); + GValue *val = g_malloc0(sizeof(GValue)); + g_object_get_property(G_OBJECT(param->track_widget),param->property_name,val); + switch(param->containing_type){ + case YON_TYPE_STRING: + g_key_file_set_string(__yon_window_config_file,"window",param->parameter_name, g_value_get_string(val)); + break; + case YON_TYPE_INT: + g_key_file_set_integer(__yon_window_config_file,"window",param->parameter_name, g_value_get_int(val)); + break; + case YON_TYPE_BOOLEAN: + g_key_file_set_boolean(__yon_window_config_file,"window",param->parameter_name, g_value_get_boolean(val)); + break; + case YON_TYPE_OTHER:printf("\033[0;31mCannot save %s property with %s key\033[0m\n",param->property_name,param->parameter_name);break; + } + } + if (__yon_main_window_config.custom_parameters) + for_dictionaries(dict,__yon_main_window_config.custom_parameters){ + __yon_custom_parameter *param = yon_dictionary_get_data(dict,__yon_custom_parameter*); + switch (param->containing_type){ + case YON_TYPE_STRING: + g_key_file_set_string(__yon_window_config_file,param->section,param->parameter_name, (char*)param->property); + break; + case YON_TYPE_INT: + g_key_file_set_integer(__yon_window_config_file,param->section,param->parameter_name, *(int*)param->property); + break; + case YON_TYPE_BOOLEAN: + g_key_file_set_boolean(__yon_window_config_file,param->section,param->parameter_name, *(gboolean*)param->property); + break; + default: + break; + } + } + if (__yon_main_window_config.deleted_parameters) + for_dictionaries(dict,__yon_main_window_config.deleted_parameters){ + __yon_custom_parameter *param = yon_dictionary_get_data(dict,__yon_custom_parameter*); + g_key_file_remove_key(__yon_window_config_file,param->section,param->parameter_name,NULL); + } + g_key_file_save_to_file(__yon_window_config_file,__yon_window_config_path,NULL); + } + + void yon_get_is_fullscreen(){ + gtk_window_is_maximized(__yon_window_config_target_window); + __yon_main_window_config.fullscreen = gtk_window_is_maximized(__yon_window_config_target_window); + if (!__yon_main_window_config.fullscreen) gtk_window_get_position(__yon_window_config_target_window,&__yon_main_window_config.x,&__yon_main_window_config.y); + } + + /**yon_on_configured_window_destroy(GtkWidget* self,GdkEvent* event) + * [EN] + * + * [RU] + * Сохраняет настройки основного окна. Вызывается когда основное окно уничтожается. + */ + void yon_on_configured_window_destroy(GtkWidget* self,GdkEvent* event){ + check_window_config_setup{ + yon_get_is_fullscreen(); + yon_window_config_save(); + } + gtk_main_quit(); + } + + void __yon_window_config_on_resize(){ + int max=0; + max=gtk_window_is_maximized(__yon_window_config_target_window); + if(max==0){ + gtk_window_get_size(__yon_window_config_target_window,&__yon_main_window_config.width,&__yon_main_window_config.height); + gtk_window_get_position(__yon_window_config_target_window,&__yon_main_window_config.x,&__yon_main_window_config.y); + } + } + + /**yon_window_config_setup(GtkWindow *window) + * [EN] + * + * [RU] + * Устанавливает указатель на окно для отслеживания его положения и размера + */ + void yon_window_config_setup(GtkWindow *window){ + __yon_window_config_target_window = window; + g_signal_connect(G_OBJECT(window),"delete-event",G_CALLBACK(yon_on_configured_window_destroy),NULL); + g_signal_connect(G_OBJECT(window),"check-resize"/*"configure-event"*/,G_CALLBACK(__yon_window_config_on_resize),NULL); + } + + void _yon_maximize(void *data){ + g_usleep(G_USEC_PER_SEC/10); + if(__yon_main_window_config.fullscreen ==1) gtk_window_maximize(__yon_window_config_target_window); + } + + /**yon_window_config_load(char *path) + * [EN] + * + * [RU] + * Загружает конфиг окна и инициализирует отслеживание его параметров + */ + int yon_window_config_load(char *path){ + __yon_window_config_file = g_key_file_new(); + __yon_window_config_path=yon_char_new(path); + if (!g_key_file_load_from_file(__yon_window_config_file,__yon_window_config_path,G_KEY_FILE_NONE,NULL)){ + struct stat st; + int size; + config_str conf = yon_char_parse(yon_char_new(__yon_window_config_path),&size,"/"); + char *path = yon_char_unite(conf[0],"/",conf[1],"/",conf[2],"/",conf[3],"/",conf[4],"/",NULL); + if (stat(path, &st) == -1) { + mkdir(path, 0777); + } + FILE *fp; + fp=fopen(__yon_window_config_path,"w"); + fclose(fp); + g_key_file_load_from_file(__yon_window_config_file,__yon_window_config_path,G_KEY_FILE_NONE,NULL); + } + __yon_main_window_config.x = g_key_file_get_integer(__yon_window_config_file,"window","WindowPosX",NULL); + __yon_main_window_config.y = g_key_file_get_integer(__yon_window_config_file,"window","WindowPosY",NULL); + __yon_main_window_config.width = g_key_file_get_integer(__yon_window_config_file,"window","WindowWidth",NULL); + __yon_main_window_config.height = g_key_file_get_integer(__yon_window_config_file,"window","WindowHeight",NULL); + __yon_main_window_config.fullscreen = g_key_file_get_integer(__yon_window_config_file,"window","fullscreen",NULL); + dictionary *dict=NULL; + if (__yon_main_window_config.custom_listeners) + for_dictionaries(dict,__yon_main_window_config.custom_listeners){ + __yon_listener_parameter *param = yon_dictionary_get_data(dict,__yon_listener_parameter*); + GValue *val = g_malloc0(sizeof(GValue)); + g_object_get_property(G_OBJECT(param->track_widget),param->property_name,val); + switch(param->containing_type){ + case YON_TYPE_STRING: + g_value_set_string(val,g_key_file_get_string(__yon_window_config_file,"window",param->parameter_name, NULL)); + break; + case YON_TYPE_INT: + g_value_set_int(val,g_key_file_get_integer(__yon_window_config_file,"window",param->parameter_name, NULL)); + break; + case YON_TYPE_BOOLEAN: + gboolean res = g_key_file_get_boolean(__yon_window_config_file,"window",param->parameter_name, NULL); + g_value_set_boolean(val,res); + break; + default:printf("\033[0;31mCannot load %s property with %s key\033[0m\n",param->property_name,param->parameter_name);break; + } + g_object_set_property(G_OBJECT(param->track_widget),param->property_name,val); + } + if (__yon_main_window_config.width==0) __yon_main_window_config.width=800; + if (__yon_main_window_config.height==0) __yon_main_window_config.height=600; + gtk_window_resize(__yon_window_config_target_window,__yon_main_window_config.width,__yon_main_window_config.height); + gtk_window_move(__yon_window_config_target_window,__yon_main_window_config.x,__yon_main_window_config.y); + pthread_t tid; + pthread_create(&tid,NULL,(void *)_yon_maximize,NULL); + return 1; + } + + void yon_window_config_apply(){ + dictionary *dict=NULL; + gtk_window_move(__yon_window_config_target_window,__yon_main_window_config.x,__yon_main_window_config.y); + gtk_window_resize(__yon_window_config_target_window,__yon_main_window_config.width,__yon_main_window_config.height); + } + + config_str yon_window_config_get_section(char *section, gsize *size){ + config_str key = g_key_file_get_keys(__yon_window_config_file,section,size,NULL); + return key; + } + + /**yon_window_config_add_custom_parameter(GtkWidget *widget, char *param_name, char *widget_property) + * [EN] + * + * [RU] + * Добавляет параметр виджета [widget] по названию [widget_property] для отслеживания и сохраняет его в конфиг под ключом [param_name]. + */ + void yon_window_config_add_listener(GtkWidget *widget, char *param_name, char *widget_property, enum YON_TYPE val_type){ + __yon_listener_parameter *param = NULL; + param = yon_remalloc(param,sizeof(__yon_listener_parameter)); + param->parameter_name = yon_char_new(param_name); + param->track_widget = widget; + param->property_name = yon_char_new(widget_property); + param->containing_type = val_type; + yon_dictionary_add_or_create_if_exists_with_data(__yon_main_window_config.custom_listeners,param->parameter_name,param); + } + + void yon_window_config_add_custom_parameter(char *param_name, char *section, void *tracked_value, enum YON_TYPE val_type){ + __yon_custom_parameter *param = NULL; + param = yon_remalloc(param,sizeof(__yon_custom_parameter)); + param->parameter_name = yon_char_new(param_name); + param->section=section; + param->property = tracked_value; + param->containing_type = val_type; + yon_dictionary_add_or_create_if_exists_with_data(__yon_main_window_config.custom_parameters,param->parameter_name,param); + } + + void yon_window_config_erase_custom_parameter(char *param_name, char *section){ + __yon_custom_parameter *param = NULL; + param = yon_remalloc(param,sizeof(__yon_custom_parameter)); + param->parameter_name=param_name; + param->section=section; + yon_dictionary_add_or_create_if_exists_with_data(__yon_main_window_config.deleted_parameters,param->parameter_name,param); + } + +GtkWidget *yon_ubl_menu_item_about_new(char *buttonname){ + GtkWidget *menu_item = gtk_menu_item_new(); + gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),"menuitembottom"); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0); + GtkWidget *label = gtk_label_new(buttonname); + GtkWidget *image = gtk_image_new_from_icon_name("dialog-information-symbolic",GTK_ICON_SIZE_BUTTON); + gtk_label_set_xalign(GTK_LABEL(label),0.0); + gtk_box_pack_start(GTK_BOX(box),image,0,0,5); + gtk_box_pack_start(GTK_BOX(box),label,0,0,5); + gtk_container_add(GTK_CONTAINER(menu_item),box); + gtk_widget_show_all(menu_item); + return menu_item; +} + +GtkWidget *yon_ubl_menu_item_documentation_new(char *buttonname){ + GtkWidget *menu_item = gtk_menu_item_new(); + gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),"menuitemtop"); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0); + GtkWidget *label = gtk_label_new(buttonname); + GtkWidget *image = gtk_image_new_from_icon_name("dialog-question-symbolic",GTK_ICON_SIZE_BUTTON); + gtk_label_set_xalign(GTK_LABEL(label),0.0); + gtk_box_pack_start(GTK_BOX(box),image,0,0,5); + gtk_box_pack_start(GTK_BOX(box),label,0,0,5); + gtk_container_add(GTK_CONTAINER(menu_item),box); + gtk_widget_show_all(menu_item); + return menu_item; +} + + +// other Gtk functions + +/**yon_gtk_combo_box_text_fill(GtkWidget *combo, config_str parameters,int size) + * [EN] + * + * [RU] + * Добавляет в Комбобокс [combo] все строки из массива строк [parameters] размера [size] +*/ +int yon_gtk_combo_box_text_fill(GtkWidget *combo, config_str parameters,int size){ + if (combo&¶meters){ + for (int i=0;i=0 ? 1 : 0); +} + +void yon_gtk_widget_set_sensitive_from_toggle_combo_box_inversed(GtkComboBox *toggle, GtkWidget *target){ + gtk_widget_set_sensitive(target,!gtk_combo_box_get_active(toggle)>=0 ? 0 : 1); +} + +void _yon_ubl_header_setup(GtkWidget *Overlay, GtkWidget *Head, GtkWidget *Image, char *image_path) +{ + gtk_overlay_add_overlay(GTK_OVERLAY(Overlay), Head); + gtk_image_set_from_file(GTK_IMAGE(Image), image_path); +} + +void _yon_ubl_header_setup_resource(GtkWidget *Overlay, GtkWidget *Head, GtkWidget *Image, char *image_path) +{ + gtk_overlay_add_overlay(GTK_OVERLAY(Overlay), Head); + gtk_image_set_from_resource(GTK_IMAGE(Image), image_path); +} + +int yon_ubl_status_box_setup(GtkWidget *icon, GtkWidget *box, GtkWidget *label) +{ + if(icon&&box&&label){ + render.icon=icon; + render.box=box; + render.label=label; + return 1; + } else return 0; +} + +void _yon_ubl_status_box_render(char *text, BACKGROUND_IMAGE_TYPE type) +{ + render_data data = render; + GtkIconTheme *ictheme = gtk_icon_theme_get_default(); + GError *err = NULL; + if (err) + { + printf("%s\n", err->message); + g_error_free(err); + } + if (type == BACKGROUND_IMAGE_SUCCESS_TYPE||! type) + { + gtk_style_context_remove_class(gtk_widget_get_style_context(data.box), "boxInfoMessError"); + gtk_style_context_add_class(gtk_widget_get_style_context(data.box), "boxInfoMessOK"); + gtk_image_set_from_pixbuf(GTK_IMAGE(data.icon), gtk_icon_theme_load_icon_for_scale(ictheme, "com.ublinux.ubl-settings-video.checked", 25, 1, GTK_ICON_LOOKUP_FORCE_SIZE, &err)); + } + else if (type == BACKGROUND_IMAGE_FAIL_TYPE) + { + gtk_style_context_remove_class(gtk_widget_get_style_context(data.box), "boxInfoMessOK"); + gtk_style_context_add_class(gtk_widget_get_style_context(data.box), "boxInfoMessError"); + gtk_image_set_from_pixbuf(GTK_IMAGE(data.icon), gtk_icon_theme_load_icon_for_scale(ictheme, "com.ublinux.ubl-settings-video.warning", 25, 1, GTK_ICON_LOOKUP_FORCE_SIZE, &err)); + } + if (text) + gtk_label_set_text(GTK_LABEL(data.label), text); +} + +void yon_ubl_status_box_render(char *text, BACKGROUND_IMAGE_TYPE type){ + _yon_ubl_status_box_render(text,type); +} + +/**yon_ubl_setup_sockets(GtkWidget *main_window, GtkWidget *left_window, GtkWidget *right_window, int socket_main_id, int socket_left_id, int socket_right_id) + * [EN] + * Set up plugs for using with GtkSockets insine ubl-settings-manager. + * [main_window] is container widget, which holds main application functionality. + * [left_window] is container widget, which holds widgets, have to be shown at left part of ubl-settings-manager header. + * [right_window] is container widget, which holds widgets, have to be shown at right part of ubl-settings-manager header. + * [socket_main_id] is id of socket for [main_window]. + * [socket_left_id] is id of socket for [left_window]. + * [socket_right_id] is id of socket for [right_window]. + * [RU] + * Настраивает плаги для работы с сокетами в утилите ubl-settings-manager. + * [main_window] - контейнер основного интерфейса приложения. + * [left_window] - контейнер для виджетов которые должны отображаться в левой части шапки ubl-settings-manager. + * [right_window] - контейнер для виджетов которые должны отображаться в правой части шапки ubl-settings-manager. + * [socket_main_id] - id сокета для [main_window]. + * [socket_left_id] - id сокета для [left_window]. + * [socket_right_id] - id сокета для [right_window]. +*/ +void yon_ubl_setup_sockets(GtkWidget *main_window, GtkWidget *left_window, GtkWidget *right_window, int socket_main_id, int socket_left_id, int socket_right_id){ + if (main_window&&socket_main_id>-1){ + gtk_widget_hide(gtk_widget_get_toplevel(main_window)); + GtkWidget *plug_main=gtk_plug_new(socket_main_id); + GtkWidget *plug_left=NULL; + GtkWidget *plug_right=NULL; + GtkWidget *box=NULL; + g_signal_connect(G_OBJECT(plug_main), "destroy", G_CALLBACK(gtk_main_quit),NULL); + if (socket_left_id>-1&&left_window){ + plug_left=gtk_plug_new(socket_left_id); + g_object_ref(left_window); + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(left_window)),left_window); + gtk_container_add(GTK_CONTAINER(plug_left),left_window); + gtk_style_context_add_class(gtk_widget_get_style_context(plug_left),"primary-toolbar"); + gtk_style_context_add_class(gtk_widget_get_style_context(left_window),"button"); + gtk_style_context_add_class(gtk_widget_get_style_context(left_window),"opacited"); + gtk_style_context_add_class(gtk_widget_get_style_context(left_window),"color"); + gtk_style_context_add_class(gtk_widget_get_style_context(plug_left),"noborder"); + gtk_widget_show(plug_left); + } + else if (left_window){ + if (box==NULL){ + box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5); + gtk_box_pack_start(GTK_BOX(main_window),box,0,0,5); + gtk_box_reorder_child(GTK_BOX(main_window),box,0); + gtk_widget_show(box); + } + gtk_style_context_add_class(gtk_widget_get_style_context(left_window),"inherited"); + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(left_window)),left_window); + gtk_box_pack_end(GTK_BOX(box),left_window,0,0,5); + } + if (socket_right_id>-1&&right_window){ + plug_right=gtk_plug_new(socket_right_id); + g_object_ref(right_window); + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(right_window)),right_window); + gtk_container_add(GTK_CONTAINER(plug_right),right_window); + gtk_style_context_add_class(gtk_widget_get_style_context(plug_right),"primary-toolbar"); + gtk_style_context_add_class(gtk_widget_get_style_context(right_window),"button"); + gtk_style_context_add_class(gtk_widget_get_style_context(right_window),"opacited"); + gtk_style_context_add_class(gtk_widget_get_style_context(right_window),"color"); + gtk_style_context_add_class(gtk_widget_get_style_context(plug_right),"noborder"); + gtk_widget_show(plug_right); + } + else if (right_window){ + if (box==NULL){ + box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5); + gtk_box_pack_start(GTK_BOX(main_window),box,0,0,5); + gtk_box_reorder_child(GTK_BOX(main_window),box,0); + gtk_widget_show(box); + } + gtk_style_context_add_class(gtk_widget_get_style_context(right_window),"inherited"); + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(right_window)),right_window); + gtk_box_pack_start(GTK_BOX(box),right_window,0,0,5); + } + g_object_ref(main_window); + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(main_window)),main_window); + gtk_container_add(GTK_CONTAINER(plug_main),main_window); + gtk_widget_show(plug_main); + } +} + +#ifdef WEBKIT_FOUND + +/**yon_ubl_browser_window_open(char *link, char *browser_window_name) + * [EN] + * Launches integrated browser window, named [browser_window_name] at header with [link]. + * [RU] + * Открывает встроенный браузер с именем [browser_window_name] и показываемой страницей по ссылке [link] +*/ +void yon_ubl_browser_window_open(char *link, char *browser_window_name){ + GtkWidget *browser=gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget *web_place=gtk_box_new(GTK_ORIENTATION_VERTICAL,0); + GtkWidget *header=gtk_header_bar_new(); + GtkWidget *header_label=gtk_label_new(browser_window_name); + GtkWidget *WebView=webkit_web_view_new(); + gtk_container_add(GTK_CONTAINER(browser),web_place); + gtk_window_set_titlebar(GTK_WINDOW(browser),header); + gtk_window_set_title(GTK_WINDOW(browser),browser_window_name); + gtk_widget_set_size_request(browser,800,600); + gtk_header_bar_set_custom_title(GTK_HEADER_BAR(header),header_label); + gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header),1); + webkit_web_view_load_uri(WEBKIT_WEB_VIEW(WebView),link); + gtk_box_pack_start(GTK_BOX(web_place),WebView,1,1,0); + gtk_widget_show_all(browser); +} +#else + +/**yon_ubl_browser_window_open(char *link, char *browser_window_name) + * [EN] + * Launches browser with [link]. + * [browser_window_name] is't used. It's needed for compatibility with webkit version of that function. + * [RU] + * Открывает браузер со страницей по ссылке [link] + * [browser_window_name] не используется. Нужна для совместимости с webkit версией этой функции. +*/ +void yon_ubl_browser_window_open(char *link, char *browser_window_name){ + char *user=getenv("SUDO_USER"); + if (!user) + user=getlogin(); + char *command=yon_char_unite("sudo -u ",user," xdg-open ", link,NULL); + yon_launch_app(command); +} +#endif + +#endif \ No newline at end of file diff --git a/source/ubl-utils.h b/source/ubl-utils.h new file mode 100644 index 0000000..fba6c98 --- /dev/null +++ b/source/ubl-utils.h @@ -0,0 +1,378 @@ +#ifndef UBL_UTILS +#define UBL_UTILS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../compile/ubl-cmake.h" +#ifdef WEBKIT_FOUND + #include +#endif +#define DesktopPath "/usr/share/applications/" + +#define for_dictionaries(obj, obj1) for (obj = obj1->first; obj != NULL; obj = obj->next) + +#define new(type) malloc(sizeof(type)) +#define new_arr(type,size) malloc(sizeof(type)*size) + +#define get_home_dir_command yon_char_unite("getent passwd \"",yon_ubl_root_user_get(),"\" | cut -d: -f6",NULL) + + + +typedef enum +{ + #ifdef __GTK_H__ + DICTIONARY_GTK_WIDGETS_TYPE, + #endif + DICTIONARY_OTHER_TYPE=0, + DICTIONARY_CHAR_TYPE, + DICTIONARY_INT_TYPE, + DICTIONARY_BOOL_TYPE, + +} DICT_TYPE; + +typedef struct dictionary +{ + char *key; + void *data; + struct dictionary *next; + struct dictionary *prev; + struct dictionary *first; + DICT_TYPE data_type; +} dictionary; + + + + +typedef struct apps +{ + char *Name; + int Type; + char *Categories; + char *Exec; + char *Icon; + int Pluggable; + int DualPluggable; +} apps; + +typedef char** config_str; + +#define config(key) yon_config_get_by_key(key) + +#define yon_remalloc(pointer, size) (!pointer) ? malloc(size) : realloc(pointer, size) +// dictionary functions + +/**yon_dictionary_get_data(dictionary, type) + * [EN] + * Gets data from dictionary. + * [dictionary] is dictionary, from which data should be extracted; + * [type] is type of data, [dictionary] contains. + * [RU] + * Возвращает данные из словаря. + * [dictionary] - словарь из которого достаются данные. + * [type] - тип данных, хранящихся в словаре [dictionary]. +*/ +#define yon_dictionary_get_data(dictionary, type) ((type)dictionary->data) + +/**yon_dictionary_add_or_create_if_exists_with_data(dict,key,data) + * [EN] + * + * [RU] + * Добавляет элемент словаря в конец словаря [dict] c ключом [key] и данными [data]. + * Если словарь не существует, создаёт его +*/ +#define yon_dictionary_add_or_create_if_exists_with_data(dict,key,data) {if (!dict) dict=yon_dictionary_new_with_data(key,data); \ + else dict=yon_dictionary_append_with_data(dict,key,data);} + +dictionary *yon_dictionary_new(); + +dictionary *yon_dictionary_append(dictionary *targetdict); + +dictionary *yon_dictionary_get_last(dictionary *dict); + +dictionary *yon_dictionary_swap(dictionary *dict, int aim); + +void yon_dictionary_make_first(dictionary *dict); + +void yon_dictionary_make_nth(dictionary *dict, int nth); + +dictionary *yon_dictionary_new_with_data(char *key, void *data); + +dictionary *yon_dictionary_append_with_data(dictionary *dict, char *key, void *data); + +dictionary *yon_dictionary_connect(dictionary *old, dictionary *toconnect); + +dictionary *yon_dictionary_get(dictionary **dict, char *key); + +dictionary *yon_dictionary_rip(dictionary *dict); + +dictionary *yon_dictionary_get_nth(dictionary *dict, int place); + +void *yon_dictionary_free_all(dictionary *dictionary,void (data_manipulation)(void*)); + +// char functions + +int yon_char_find_last(char *source, char find); + +char *yon_char_append(char *source, char *append); + +char *yon_char_new(char *chr); + +char *yon_char_unite(char *source, ...); + +char *yon_cut(char *source, int size, int startpos); + +char *yon_char_divide(char *source, int dividepos); + +char *yon_char_divide_search(char *source, char *dividepos, int delete_divider); + +char *yon_char_from_int(int int_to_convert); + +char *yon_char_replace(char *source, char *find, char*replace); + +char **yon_char_parse(char *parameters, int *size, char *divider); + +char **yon_char_parsed_rip(char **char_string, int *size, int item_to_delete); + +int yon_char_parsed_check_exist(char **parameters, int size, char *param); + +int yon_char_find_count(char *source, char *find); + +int yon_char_parsed_includes_char_parsed (config_str source, config_str to_check, int source_size, int check_size); + +config_str yon_char_parsed_new (int *size, ...); + +void yon_char_parsed_copy(config_str *source, config_str *to_copy); + +config_str yon_char_parsed_append(config_str parsed, int *size, char *string); + +int yon_ubl_check_root(); + +char *yon_ubl_root_user_get(); + +char *yon_ubl_user_get_home_directory(); + +// parsing functions + +config_str philos_list_user(int* size); + +apps *yon_apps_scan_and_parse_desktops(int *sizef); + +void yon_apps_sort(apps *applist, int size); + +apps *yon_apps_get_by_name(apps *applist, char *name, int size); + +//config functions + +#define ubconfig_save_command "ubconfig" +#define ubconfig_load_command "ubconfig --source" + +typedef enum { + YON_CONFIG_LOCAL=0, + YON_CONFIG_GLOBAL, + YON_CONFIG_BOTH +} YON_CONFIG_TYPE; + +config_str yon_config_load(char *command, int *str_len); + +int yon_config_save_registered(char *path, char *section); + +char *yon_config_get_parameter(config_str parameters, int size, char *param); + +int yon_config_load_register(YON_CONFIG_TYPE config_type,char *section,char *parameter, ...); + +int yon_config_remove_by_key(char *key); + +int yon_config_remove_by_data(void *data); + +int yon_config_remove_element(char *key, char *deleted); + +void *yon_config_get_by_key(char *key); + +char *yon_config_get_key_by_data(char *data); + +int yon_config_set(char *key, void *data); + +int yon_config_clean(); + +void yon_config_register(char *key, char* config_section, void *data); + +config_str yon_config_get_all(); + +// terminal-using functions + +int yon_launch_app_with_arguments(char *name, char *args); + +void yon_launch(char *command); + +// Gtk functions + +#ifdef __GTK_H__ +#ifdef VTE_TERMINAL +void yon_terminal_integrated_launch(GtkWidget *place_to_show, char* command, void *endwork_function, void* endwork_function_argument); + +void yon_terminal_integrated_start(GtkWidget *terminal, char* command, void *endwork_function, void* endwork_function_argument); + +#endif + +enum YON_TYPE{ + YON_TYPE_STRING, + YON_TYPE_INT, + YON_TYPE_BOOLEAN, + YON_TYPE_OTHER +}; + +GtkWidget *yon_ubl_menu_item_about_new(char *buttonname); +GtkWidget *yon_ubl_menu_item_documentation_new(char *buttonname); + +/**yon_gtk_builder_get_widget(builder, widget_name) + * [EN] + * Returns GtkWidget from GtkBuilder *[builder]. + * [builder] is GtkBuilder*; + * [widget_name] is id of widget; +*/ +#define yon_gtk_builder_get_widget(builder, widget_name) GTK_WIDGET(gtk_builder_get_object(builder, widget_name)) + +typedef struct +{ + GtkWidget *Icon; + GtkWidget *Label; + GtkWidget *IconView; + GtkListStore *List; +} expander_icon_view; + +void yon_window_config_setup(GtkWindow *window); + +int yon_window_config_load(char *path); + +config_str yon_window_config_get_section(char *section, gsize *size); + +void yon_window_config_add_listener(GtkWidget *widget, char *param_name, char *widget_property, enum YON_TYPE val_type); + +void yon_window_config_add_custom_parameter(char *param_name, char *section, void *tracked_value, enum YON_TYPE val_type); + +void yon_window_config_erase_custom_parameter(char *param_name, char *section); + +int yon_gtk_combo_box_fill(GtkWidget *combo, char **parameters,int size); + +int yon_gtk_combo_box_text_find(GtkWidget *combo_box, char *text_to_find); + +int yon_gtk_icon_view_hide_empty(dictionary *icon_view_segment); + +int yon_dictionary_gtk_pack_start_multiple_widgets(GtkBox *destination, gboolean expand, gboolean fill, int padding, ...); + +int yon_dictionary_gtk_pack_end_multiple_widgets(GtkBox *destination, gboolean expand, gboolean fill, int padding, ...); + + +void yon_gtk_widget_set_sensitive_from_toggle_button(GtkToggleButton *toggle, GtkWidget *target); +void yon_gtk_widget_set_sensitive_from_toggle_button_inversed(GtkToggleButton *toggle, GtkWidget *target); +void yon_gtk_widget_set_sensitive_from_combo_box(GtkComboBox *toggle, GtkWidget *target); +void yon_gtk_widget_set_sensitive_from_combo_box_inversed(GtkComboBox *toggle, GtkWidget *target); + +typedef enum +{ + BACKGROUND_IMAGE_SUCCESS_TYPE, + BACKGROUND_IMAGE_FAIL_TYPE +} BACKGROUND_IMAGE_TYPE; + +typedef struct { + BACKGROUND_IMAGE_TYPE type; + GtkWidget *icon; + GtkWidget *box; + GtkWidget *label; + char* text_to_render; +} render_data; + + +/**yon_ubl_status_box_setup(render,icon,box,label) + * [EN] + * Sets up [render] structure of type render_data. + * [icon] is GtkImage widget of status box for showing status icons; + * [box] is GtkBox widget of status box for showing status color; + * [label] is GtkLabel widget of status box for showing status text; + * [RU] + * Настраивает структуру [render] типа render_data. + * [icon] - виджет типа GtkIcon в котором будут отображаться статусные иконки; + * [box] - виджет типа GtkBox в котором будет отображаться цвет статуса; + * [label] - виджет типа GtkLabel в котором будет отображаться текст статусного сообщения; +*/ +int yon_ubl_status_box_setup(GtkWidget *icon, GtkWidget *box, GtkWidget *label); + +/**yon_ubl_status_box_render(render,text,type) + * [EN] + * Renders message in status box; + * [render] is render_data structure of status box; + * [text] is text to be shown in status box; + * [type] if type of message. Can be BACKGROUND_IMAGE_FAIL_TYPE or BACKGROUND_IMAGE_SUCCESS_TYPE + * [RU] + * Отображает сообщение в статусном окне. + * [render] - структура типа render_data для нужного статусного окна; + * [text] - текст, отображаемый в статусном окне; + * [type] - тип сообщения. Может быть: + * BACKGROUND_IMAGE_FAIL_TYPE (красный фон,иконка - восклицательный знак) + * или + * BACKGROUND_IMAGE_SUCCESS_TYPE (Жёлтный фон, иконка - галка) +*/ +void yon_ubl_status_box_render(char *text, BACKGROUND_IMAGE_TYPE type); + +#ifdef __cplusplus + +/**yon_ubl_header_setup(overlay, head, image, imag_path) + * [EN] + * Sets up header of app. + * [overlay] is overlay for app header; + * [head] is box of header, which connects to [overlay] + * [image] is header background image; + * [imag_path] is path of image, shown in [image] + * [RU] + * Настраивает заголовок приложения. + * [overlay] - оверлей заголовка приложения; + * [head] - шапка заголовка, присоединяемая к [overlay] + * [image] - виджет картинки для заднего фона; + * [imag_path] - путь до картинки, загружаемой в [image] +*/ +#define yon_ubl_header_setup(overlay, head, image, imag_path) _yon_ubl_header_setup(GTK_WIDGET(overlay.gobj()), GTK_WIDGET(head.gobj()), GTK_WIDGET(image.gobj()), (char *)imag_path) +#else + +/**yon_ubl_header_setup(overlay, head, image, imag_path) + * [EN] + * Sets up header of app. + * [overlay] is overlay for app header; + * [head] is box of header, which connects to [overlay] + * [image] is header background image; + * [imag_path] is path of image, shown in [image] + * [RU] + * Настраивает заголовок приложения. + * [overlay] - оверлей заголовка приложения; + * [head] - шапка заголовка, присоединяемая к [overlay] + * [image] - виджет картинки для заднего фона; + * [imag_path] - путь до картинки, загружаемой в [image] +*/ +#define yon_ubl_header_setup(overlay, head, image, imag_path) _yon_ubl_header_setup(GTK_WIDGET(overlay), GTK_WIDGET(head), GTK_WIDGET(image), (char *)imag_path) +#define yon_ubl_header_setup_resource(overlay, head, image, imag_path) _yon_ubl_header_setup_resource(GTK_WIDGET(overlay), GTK_WIDGET(head), GTK_WIDGET(image), (char *)imag_path) +#endif + +void _yon_ubl_header_setup(GtkWidget *Overlay, GtkWidget *Head, GtkWidget *Image, char *image_path); + +void _yon_ubl_header_setup_resource(GtkWidget *Overlay, GtkWidget *Head, GtkWidget *Image, char *image_path); + +void yon_ubl_setup_sockets(GtkWidget *main_window, GtkWidget *left_window, GtkWidget *right_window, int socket_main_id, int socket_left_id, int socket_right_id); +#ifdef WEBKIT_FOUND + +void yon_ubl_browser_window_open(char *link, char *browser_window_name); +#else +void yon_ubl_browser_window_open(char *link, char *browser_window_name); +#endif +#endif +#endif \ No newline at end of file diff --git a/ubl-settings-keyboard b/ubl-settings-keyboard new file mode 100755 index 0000000000000000000000000000000000000000..84e08fff468b8f7833b74fe4284d755c1162a1f1 GIT binary patch literal 262488 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 z + + + + + True + False + emblem-ok-symbolic + + + True + False + process-stop-symbolic + + + + + + + + + + + 450 + 550 + True + False + dialog + + + False + 3 + 3 + 3 + 3 + vertical + 5 + + + False + end + + + Cancel + True + True + True + image2 + + + True + True + 0 + + + + + Accept + True + True + True + image1 + + + True + True + 1 + + + + + False + False + 0 + + + + + True + True + in + + + True + True + liststore1 + False + + + column + + + + 1 + + + + + + + + + True + True + 1 + + + + + + + True + False + True + + + True + False + 5 + 5 + 5 + 5 + 2 + Keyboard + + + + + + + + True + False + 5 + 5 + 5 + 5 + 6 + 6 + 32 + com.ublinux.ubl-settings-keyboard + + + + + + + diff --git a/ubl-settings-keyboard-options.glade b/ubl-settings-keyboard-options.glade new file mode 100644 index 0000000..d9d8518 --- /dev/null +++ b/ubl-settings-keyboard-options.glade @@ -0,0 +1,145 @@ + + + + + + + 450 + 550 + True + False + dialog + + + False + 3 + 3 + 3 + 3 + vertical + 5 + + + False + end + + + Cancel + True + True + True + image2 + + + True + True + 0 + + + + + Accept + True + True + True + image1 + + + True + True + 1 + + + + + False + False + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + True + + + True + False + 5 + 5 + 5 + 5 + 2 + Keyboard + + + + + + + + True + False + 5 + 5 + 5 + 5 + 6 + 6 + 32 + com.ublinux.ubl-settings-keyboard + + + + + + + + True + False + emblem-ok-symbolic + + + True + False + process-stop-symbolic + + diff --git a/ubl-settings-keyboard.css b/ubl-settings-keyboard.css new file mode 100644 index 0000000..88e8c57 --- /dev/null +++ b/ubl-settings-keyboard.css @@ -0,0 +1,114 @@ + +.thin { + margin:0px; + padding:0px; +} +.noborder { + border:none; +} +.nobackground { +background:transparent; +} +.nobackground:active { +background:transparent; +} +.textHead{ + text-shadow: 2px 2px @theme_bg_color; + color: @theme_text_color; +} + +.inherited>* { + border:none; + background:inherit; +} +.workingbg { + background:@theme_base_color; +} +.menuitembottom{ + margin-top:0px; + margin-bottom:3px; + border-color:inherit; + border-left-width:inherit; + border-right-width:inherit; + } + .menuitemmiddle{ + margin-top:0px; + margin-bottom:0px; + border-color:inherit; + border-left-width:inherit; + border-right-width:inherit; + } + + .menuitemtop{ + margin-bottom:0px; + border-color:inherit; + border-top-width:inherit; + border-left-width:inherit; + border-right-width:inherit; + } + .menuitemtop>*{ + margin:2px 2px 0 2px; + padding: 3px 10px 3px 5px; + /* padding: 5px 0px 3px 5px; */ + border:transparent; + } + .menuitemmiddle>*{ + margin:0 2px 0 2px; + padding: 3px 10px 3px 5px; + /* padding: 3px 0px 3px 5px; */ + border:transparent; + } + .menuitembottom>*{ + margin:0 2px 2px 2px; + padding: 3px 10px 3px 5px; + /* padding: 3px 0px 5px 5px; */ + } + .menuitemtop:hover { + background:@theme_bg_color; + border-color:inherit; + border-top-width:inherit; + border-left-width:inherit; + border-right-width:inherit; + } + .menuitemmiddle:hover { + background:@theme_bg_color; + border-color:inherit; + border-left-width:inherit; + border-right-width:inherit; + } + .menuitembottom:hover { + background:@theme_bg_color; + border-color:inherit; + border-bottom-width:0px; + border-left-width:inherit; + border-right-width:inherit; + + } + .menuitemtop:hover>* { + margin:2px 2px 0 2px; + padding: 3px 10px 3px 5px; + /* padding: 5px 0 3px 5px; */ + background:@theme_selected_bg_color; + border-radius:2px; + } + .menuitemmiddle:hover>* { + margin:0 2px 0px 2px; + padding: 3px 10px 3px 5px; + /* padding: 3px 0px 3px 5px; */ + background:@theme_selected_bg_color; + border-radius:2px; + } + .menuitembottom:hover>* { + margin:0 2px 2px 2px; + padding: 3px 10px 3px 5px; + /* padding: 3px 0px 5px 5px; */ + background:@theme_selected_bg_color; + border-radius:2px; + } + .boxInfoMessError{ + background-color: #ea9999; +} + +.boxInfoMessOK{ + background-color: #f3f0ac; +} \ No newline at end of file diff --git a/ubl-settings-keyboard.desktop b/ubl-settings-keyboard.desktop new file mode 100644 index 0000000..a1c10e7 --- /dev/null +++ b/ubl-settings-keyboard.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Keyboard configuration +Name[ru]=TEMPLATE +GenericName=ubl-settings-keyboard +GenericName[ru]=TEMPLATE +Comment=Keyboard configuration +Comment[ru]=Приложение для TEMPLATE +Type=Application +Exec=pkexec ubl-settings-keyboard +Icon=com.ublinux.ubl-settings-keyboard +Terminal=false +X-XfcePluggable=true +X-UBLPluggable=true +Categories=XFCE;GTK;Settings;DesktopSettings;X-XFCE-SettingsDialog;X-XFCE-SystemSettings;X-UBL-SettingsManager;X-UBL-Personal-Settings; diff --git a/ubl-settings-keyboard.glade b/ubl-settings-keyboard.glade new file mode 100644 index 0000000..ca3c67e --- /dev/null +++ b/ubl-settings-keyboard.glade @@ -0,0 +1,1229 @@ + + + + + + + + + + False + False + True + center + com.ublinux.ubl-settings-keyboard + dialog + True + ubl-settings-keyboard + 1.1 + Copyright © 2022 - 2023, UBSoft LLC + Keyboard + https://wiki.ublinux.ru/ru/Программное_обеспечение/Программы_и_утилиты/Все/ubl-settings-keyboard + Project Home Page + Это приложение распространяется без каких-либо гарантий. +Подробнее в <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, версии 2 или позднее</a>. + UBGroup + UBGroup + com.ublinux.ubl-settings-keyboard + True + gpl-2-0 + + + True + False + vertical + 2 + + + False + end + + + False + False + 1 + + + + + + + True + False + True + + + True + False + 5 + 5 + 5 + 5 + 2 + Keyboard + + + + + + + + + + True + False + center + + + 90 + True + False + 5 + 5 + 5 + 5 + 6 + 6 + 69 + com.ublinux.ubl-settings-keyboard + + + False + True + 0 + + + + + True + False + + + True + False + + + True + False + center + vertical + + + 255 + True + False + end + Keyboard + 0 + + + + + + + + True + True + 0 + + + + + 255 + True + False + start + Keyboard configuration + 0 + + + + + + + + True + True + 1 + + + + + False + True + 0 + + + + + True + True + 0 + + + + + True + True + 1 + + + + + + True + False + user-trash-symbolic + + + True + False + value-increase-symbolic + + + True + False + document-edit-symbolic + + + True + False + process-stop-symbolic + + + True + False + emblem-ok-symbolic + + + False + False + 450 + dialog-question-symbolic + + + True + False + 5 + 5 + 5 + 5 + vertical + 10 + + + True + False + + + True + False + start + 20 + 20 + dialog-question-symbolic + 6 + + + False + True + 0 + + + + + True + False + vertical + + + True + False + start + 10 + 5 + Would you like to read documentation in the Web? + True + 0 + + + + + + + False + True + 0 + + + + + True + False + start + start + 10 + 10 + You will be redirected to documentation website where documentation is +translated and supported by community. + True + 0 + + + + False + True + 1 + + + + + Always redirect to online documentation + True + True + False + end + True + + + + False + True + end + 2 + + + + + + True + True + 1 + + + + + + True + True + 0 + + + + + True + False + 30 + True + + + Cancel + True + True + True + image8 + + + + True + True + 0 + + + + + Open documentation + True + True + True + image9 + + + + True + True + 1 + + + + + False + True + 1 + + + + + + + True + False + True + + + True + False + Keyboard + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + True + False + False + + + True + False + Load global configuration + + + + + + True + False + Load local configuration + + + + + + True + False + False + False + + + True + False + False + + + True + False + Save configuration + + + + + + True + False + Save to global configuration + + + + + + True + False + Save to local configuration + + + + + + True + False + + + True + False + + + 800 + 600 + False + 800 + 600 + com.ublinux.ubl-settings-keyboard + + + True + False + vertical + + + True + False + vertical + + + True + False + + + True + False + 5 + 5 + 5 + 5 + 5 + 5 + 25 + + + False + True + 0 + + + + + True + False + start + 5 + 5 + 5 + 5 + 6 + 6 + True + + + + + + + False + True + 1 + + + + + False + True + 0 + + + + + True + False + vertical + + + 81 + True + False + + + True + False + start + + + -1 + + + + + False + True + 0 + + + + + False + True + 1 + + + + + True + False + 5 + 5 + 5 + 5 + 5 + 5 + True + True + vertical + 5 + + + True + False + 0.019999999552965164 + in + + + True + False + 5 + 5 + 5 + + + True + False + 5 + + + True + False + Num Lock on boot: + + + False + True + 0 + + + + + True + False + 0 + + Default + On + Off + + + + True + True + 1 + + + + + + + + + True + False + Console + + + + + False + True + 0 + + + + + True + False + 0.019999999552965164 + in + + + True + False + 5 + 5 + 5 + + + True + False + vertical + 6 + + + True + False + 5 + + + True + False + Keyboard Model: + 0 + + + False + True + 0 + + + + + True + False + liststore2 + 0 + + + + 0 + + + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + 5 + + + True + False + vertical + 5 + + + True + True + in + + + True + True + liststore1 + False + + + + + + column + + + + 0 + + + + + + + + + True + True + 0 + + + + + True + True + 0 + + + + + True + False + vertical + 5 + + + True + True + True + + + True + True + False + True + menu4 + up + + + + + + + + + + False + True + 0 + + + + + True + True + True + + + True + True + False + True + menu5 + + + + + + + + + + False + True + 1 + + + + + True + True + True + image3 + + + + False + True + 2 + + + + + True + True + True + image1 + + + + False + True + 4 + + + + + False + True + 1 + + + + + True + True + end + 2 + + + + + True + False + Keyboard layouts: + 0 + + + False + True + end + 4 + + + + + True + False + 5 + + + True + False + KEYBOARD: + 0 + + + False + True + 0 + + + + + True + True + + + True + True + 1 + + + + + False + True + 4 + + + + + True + False + 5 + + + True + False + Keyboard options: + 0 + + + False + True + 0 + + + + + True + True + + + True + True + 1 + + + + + True + True + True + image4 + + + + False + True + 2 + + + + + False + True + 7 + + + + + + + + + True + False + Keyboard + + + + + True + True + 3 + + + + + False + True + 2 + + + + + True + True + 0 + + + + + + + True + False + True + + + True + False + 5 + 5 + 5 + 5 + 2 + Keyboard + + + + + + + + True + False + 5 + 5 + 5 + 5 + 6 + 6 + 32 + com.ublinux.ubl-settings-keyboard + + + + + True + False + + + True + True + False + True + menu3 + + + True + False + + + True + False + Save + + + False + True + 0 + + + + + True + False + pan-down-symbolic + + + False + True + 1 + + + + + + + False + True + 0 + + + + + True + True + True + False + True + True + menu2 + none + + + + + + + False + True + 1 + + + + + end + 1 + + + + + True + False + + + True + True + False + True + menu1 + + + True + False + + + True + False + Load + + + False + True + 0 + + + + + True + False + pan-down-symbolic + + + False + True + 1 + + + + + + + False + True + 0 + + + + + 2 + + + + + + + diff --git a/ubl-settings-keyboard.pot b/ubl-settings-keyboard.pot new file mode 100644 index 0000000..6273a6d --- /dev/null +++ b/ubl-settings-keyboard.pot @@ -0,0 +1,171 @@ +# Language translations for ubl-settings-keyboard package. +# Copyright (C) 2022, UBTech LLC +# This file is distributed under the same license as the ubl-settings-keyboard package. +# UBLinux Team , 2022 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: ubl-settings-keyboard 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-05-22 16:12+0600\n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: source/ubl-strings.h:1 +msgid "Version:" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "ubl-settings-keyboard version:" +msgstr "" + + +#: source/ubl-strings.h:2 +msgid "Usage:" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "[OPTIONS]" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Options:" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Show this help" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Show package version" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Lock this help menu" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Lock configuration saving" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Lock local configration saving" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Lock global configration saving" +msgstr "" + +#: source/ubl-strings.h:2 +msgid "Lock global configration loading" +msgstr "" + +#: source/ubl-strings.h:4 +msgid "Keyboard" +msgstr "" + +#: source/ubl-strings.h:5 +msgid "Keyboard configuration" +msgstr "" + +#: source/ubl-strings.h:7 +msgid "Operation succeeded" +msgstr "" + +#: source/ubl-strings.h:8 +msgid "" +"Warning! Application was launched without root - root-dependent actions are " +"locked" +msgstr "" + +#: source/ubl-strings.h:10 +msgid "About" +msgstr "" + +#: source/ubl-strings.h:11 +msgid "Documentation" +msgstr "" + +#: source/ubl-strings.h:12 +msgid "Save to local configuration" +msgstr "" + +#: source/ubl-strings.h:13 +msgid "Save to global configuration" +msgstr "" + +#: source/ubl-strings.h:14 +msgid "Save configuration" +msgstr "" + +#: source/ubl-strings.h:15 +msgid "Save" +msgstr "" + +#: source/ubl-strings.h:16 +msgid "Load local configuration" +msgstr "" + +#: source/ubl-strings.h:17 +msgid "Load global configuration" +msgstr "" + +#: source/ubl-strings.h:18 +msgid "Load" +msgstr "" + +#: source/ubl-strings.h:20 +msgid "Cancel" +msgstr "" + +#: source/ubl-strings.h:22 +msgid "Would you like to read documentation in the Web?" +msgstr "" + +#: source/ubl-strings.h:23 +msgid "" +"You will be redirected to documentation website where documentation is\n" +"translated and supported by community." +msgstr "" + +#: source/ubl-strings.h:24 +msgid "Always redirect to online documentation" +msgstr "" + +#: source/ubl-strings.h:25 +msgid "Open documentation" +msgstr "" + +#: source/ubl-strings.h:26 +msgid "Project Home Page" +msgstr "" + +#: source/ubl-strings.h:27 +msgid "Nothing were chosen" +msgstr "" + +#: source/ubl-strings.h:30 +msgid "Global configuration loading succseeded." +msgstr "" + +#: source/ubl-strings.h:31 +msgid "Local configuration loading succseeded." +msgstr "" + +#: source/ubl-strings.h:33 +msgid "Local and global configuration saving succseeded." +msgstr "" + +#: source/ubl-strings.h:34 +msgid "Global configuration saving succseeded." +msgstr "" + +#: source/ubl-strings.h:35 +msgid "Local configuration saving succseeded." +msgstr "" diff --git a/ubl-settings-keyboard_ru.po b/ubl-settings-keyboard_ru.po new file mode 100644 index 0000000..7b2a798 --- /dev/null +++ b/ubl-settings-keyboard_ru.po @@ -0,0 +1,177 @@ +# Russian translations for ubl-settings-keyboard package. +# Copyright (C) 2022, UBTech LLC +# This file is distributed under the same license as the ubl-settings-keyboard package. +# UBLinux Team , 2022 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: ubl-settings-keyboard 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-05-22 16:12+0600\n" +"PO-Revision-Date: 2023-01-01 00:00+0600\n" +"Last-Translator: UBLinux Team \n" +"Language-Team: Russian - UBLinux Team \n" +"Language: Russian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: source/ubl-strings.h:1 +msgid "Version:" +msgstr "Версия:" + +#: source/ubl-strings.h:2 +msgid "ubl-settings-keyboard version:" +msgstr "Версия ubl-settings-keyboard: " + +#: source/ubl-strings.h:2 +msgid "TEMPLATE settings" +msgstr "Настройки TEMPLATE" + +#: source/ubl-strings.h:2 +msgid "Usage:" +msgstr "Использование:" + +#: source/ubl-strings.h:2 +msgid "[OPTIONS]" +msgstr "[АРГУМЕНТЫ]" + +#: source/ubl-strings.h:2 +msgid "Options:" +msgstr "Аргументы:" + +#: source/ubl-strings.h:2 +msgid "Show this help" +msgstr "Показать параметры справки" + +#: source/ubl-strings.h:2 +msgid "Show package version" +msgstr "Показать текущую версию" + +#: source/ubl-strings.h:2 +msgid "Lock this help menu" +msgstr "Блокировка вызова справки" + +#: source/ubl-strings.h:2 +#, fuzzy +msgid "Lock configuration saving" +msgstr "Блокировка сохранения локальной и глобальной конфигурации" + +#: source/ubl-strings.h:2 +msgid "Lock local configration saving" +msgstr "Блокировка сохранения локальной конфигурации" + +#: source/ubl-strings.h:2 +msgid "Lock global configration saving" +msgstr "Блокировка сохранения глобальной конфигурации" + +#: source/ubl-strings.h:2 +msgid "Lock global configration loading" +msgstr "Блокировка загрузки глобальной конфигурации" + +#: source/ubl-strings.h:4 +msgid "Keyboard" +msgstr "Клавиатура" + +#: source/ubl-strings.h:5 +msgid "Keyboard configuration" +msgstr "Настройки Клавиатуры" + +#: source/ubl-strings.h:7 +msgid "Operation succeeded" +msgstr "Операция завершена" + +#: source/ubl-strings.h:8 +msgid "" +"Warning! Application was launched without root - root-dependent actions are " +"locked" +msgstr "Внимание! Приложение было запущено без прав суперпользователя - действия, требующие их наличия заблокированы" + +#: source/ubl-strings.h:10 +msgid "About" +msgstr "О программе" + +#: source/ubl-strings.h:11 +msgid "Documentation" +msgstr "Справка" + +#: source/ubl-strings.h:12 +msgid "Save to local configuration" +msgstr "Сохранить в локальную конфигурацию" + +#: source/ubl-strings.h:13 +msgid "Save to global configuration" +msgstr "Сохранить в глобальную конфигурацию" + +#: source/ubl-strings.h:14 +msgid "Save configuration" +msgstr "Сохранить конфигурацию" + +#: source/ubl-strings.h:15 +msgid "Save" +msgstr "Сохранить" + +#: source/ubl-strings.h:16 +msgid "Load local configuration" +msgstr "Загрузить локальную конфигуруцию" + +#: source/ubl-strings.h:17 +msgid "Load global configuration" +msgstr "Загрузить глобальную конфигурацию" + +#: source/ubl-strings.h:18 +msgid "Load" +msgstr "Загрузить" + +#: source/ubl-strings.h:20 +msgid "Cancel" +msgstr "Отмена" + +#: source/ubl-strings.h:22 +msgid "Would you like to read documentation in the Web?" +msgstr "Вы хотите прочитать справку в Сети?" + +#: source/ubl-strings.h:23 +msgid "" +"You will be redirected to documentation website where documentation is\n" +"translated and supported by community." +msgstr "" +"Вы будете перенаправлены на сайт с документацией, где страницы помощи\n" +"переводятся и поддерживаются сообществом." + +#: source/ubl-strings.h:24 +msgid "Always redirect to online documentation" +msgstr "Всегда перенаправлять" + +#: source/ubl-strings.h:25 +msgid "Open documentation" +msgstr "Прочитать справку" + +#: source/ubl-strings.h:26 +msgid "Project Home Page" +msgstr "Домашняя страница проекта" + +#: source/ubl-strings.h:27 +msgid "Nothing were chosen" +msgstr "Ничего не было выбрано" + +#: source/ubl-strings.h:30 +msgid "Global configuration loading succseeded." +msgstr "Успешно загружена глобальная конфигурация" + +#: source/ubl-strings.h:31 +msgid "Local configuration loading succseeded." +msgstr "Успешно загружена локальная конфигурация" + +#: source/ubl-strings.h:33 +msgid "Local and global configuration saving succseeded." +msgstr "Успешно записаны локальная и глобальная конфигурация" + +#: source/ubl-strings.h:34 +msgid "Global configuration saving succseeded." +msgstr "Успешно записана глобальная конфигурация" + +#: source/ubl-strings.h:35 +msgid "Local configuration saving succseeded." +msgstr "Успешно записана локальная конфигурация"