diff --git a/gresource.xml b/gresource.xml
index db00251..5aab596 100644
--- a/gresource.xml
+++ b/gresource.xml
@@ -12,6 +12,7 @@
libublsettingsui-gtk3-service-control.glade
libublsettingsui-gtk3-app-chooser.glade
libublsettingsui-gtk3-password.glade
+ libublsettingsui-gtk3-users-window.glade
libublsettingsui-gtk3.css
diff --git a/libublsettingsui-gtk3-users-window.glade b/libublsettingsui-gtk3-users-window.glade
new file mode 100644
index 0000000..8698736
--- /dev/null
+++ b/libublsettingsui-gtk3-users-window.glade
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
diff --git a/libublsettingsui-gtk3.pot b/libublsettingsui-gtk3.pot
index c507f7f..f87abcf 100644
--- a/libublsettingsui-gtk3.pot
+++ b/libublsettingsui-gtk3.pot
@@ -391,4 +391,7 @@ msgstr ""
#: source/libublsettingsui-gtk3.h:493
msgid "The configuration file contains incorrect parameters."
+msgstr ""
+
+msgid "Empty important field!"
msgstr ""
\ No newline at end of file
diff --git a/libublsettingsui-gtk3_ru.po b/libublsettingsui-gtk3_ru.po
index d56a7a5..d84a9a9 100644
--- a/libublsettingsui-gtk3_ru.po
+++ b/libublsettingsui-gtk3_ru.po
@@ -397,4 +397,7 @@ msgid "Access to file denied"
msgstr "Отказано в доступе к файлу"
msgid "The configuration file contains incorrect parameters."
-msgstr "Файл конфигурации содержит некорректные параметры"
\ No newline at end of file
+msgstr "Файл конфигурации содержит некорректные параметры"
+
+msgid "Empty important field!"
+msgstr "Пустое важное поле!"
\ No newline at end of file
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 190acd1..92729b9 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -48,6 +48,7 @@ set(DEPENDFILES
../libublsettingsui-gtk3-service-control.glade
../libublsettingsui-gtk3-app-chooser.glade
../libublsettingsui-gtk3-password.glade
+ ../libublsettingsui-gtk3-users-window.glade
../gresource.xml
../libublsettingsui-gtk3-banner.png
../libublsettingsui-gtk3.css
@@ -89,6 +90,7 @@ add_library(${PROJECT_NAME} SHARED
libublsettingsui-gtk3-app-chooser.c
libublsettingsui-gtk3-standard-callbacks.c
libublsettingsui-gtk3-password.c
+ libublsettingsui-gtk3-users-window.c
libublsettingsui-gtk3.h
${CMAKE_CURRENT_BINARY_DIR}/${GRESOURCE_C})
diff --git a/source/libublsettingsui-gtk3-users-window.c b/source/libublsettingsui-gtk3-users-window.c
new file mode 100644
index 0000000..134537c
--- /dev/null
+++ b/source/libublsettingsui-gtk3-users-window.c
@@ -0,0 +1,132 @@
+#include "libublsettingsui-gtk3.h"
+
+typedef struct {
+ GtkWidget *Window;
+ GtkWidget *StatusBox;
+ GtkWidget *UsersTree;
+ GtkListStore *list;
+ GtkWidget *CancelButton;
+ GtkWidget *AcceptButton;
+ GtkCellRenderer *StatusCell;
+ GtkTreeViewColumn *GroupColumn;
+ unsigned int selection_size;
+ config_str selection;
+} yon_user_window;
+
+gboolean on_user_window_closed(GtkWidget *, yon_user_window *){
+ gtk_main_quit();
+ return 0;
+}
+
+void on_group_clicked(GtkCellRenderer *, char *path, yon_user_window *window){
+ GtkTreeIter iter;
+ gboolean status;
+ gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(window->list),&iter,path);
+ gtk_tree_model_get(GTK_TREE_MODEL(window->list),&iter,0,&status,-1);
+ gtk_list_store_set(window->list,&iter,0,!status,-1);
+ if (gtk_cell_renderer_toggle_get_radio(GTK_CELL_RENDERER_TOGGLE(window->StatusCell))){
+ GtkTreeIter *prev = gtk_tree_iter_copy(&iter);
+ for (int valid = gtk_tree_model_iter_previous(GTK_TREE_MODEL(window->list),prev); valid; valid = gtk_tree_model_iter_previous(GTK_TREE_MODEL(window->list),prev)){
+ gtk_list_store_set(window->list,prev,0,0,-1);
+ }
+ gtk_tree_iter_free(prev);
+
+ GtkTreeIter *next = gtk_tree_iter_copy(&iter);
+ for (int valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(window->list),next); valid; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(window->list),next)){
+ gtk_list_store_set(window->list,next,0,0,-1);
+ }
+ gtk_tree_iter_free(next);
+ }
+}
+
+void on_users_window_accept(GtkWidget *, yon_user_window *window){
+ GtkTreeModel *model;
+ GList *list = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(window->UsersTree)),&model);
+ GList *liter;
+ for (liter=list;liter;liter=liter->next){
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter(model,&iter,(GtkTreePath*)liter->data);
+ int selected;
+ char *target;
+ int id;
+ gtk_tree_model_get(model,&iter,0,&selected,1,&target,2,&id,-1);
+ if (selected){
+ char *id_string = yon_char_from_int(id);
+ yon_char_parsed_add_or_create_if_exists(window->selection,&window->selection_size,target); //FIXME: IMPLEMENT USER AND GROUP SYSTEM AND SWITCH TARGET TO UID/GID
+ free(id_string);
+ }
+ }
+ on_subwindow_close(window->Window);
+}
+
+yon_user_window *yon_user_window_new(enum YON_USER_WINDOW_MODE_TYPE mode){
+ yon_user_window *window = malloc(sizeof(yon_user_window));
+ memset(window,0,sizeof(yon_user_window));
+ GtkBuilder *builder = gtk_builder_new_from_resource(ui_glade_path_userwindow);
+ window->Window=yon_gtk_builder_get_widget(builder,"Window");
+ window->StatusBox=yon_gtk_builder_get_widget(builder,"StatusBox");
+ window->UsersTree=yon_gtk_builder_get_widget(builder,"UsersTree");
+ window->StatusCell = GTK_CELL_RENDERER(gtk_builder_get_object(builder,"StatusCell"));
+ window->GroupColumn = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder,"GroupColumn"));
+ window->CancelButton=yon_gtk_builder_get_widget(builder,"CancelButton");
+ window->AcceptButton=yon_gtk_builder_get_widget(builder,"AcceptButton");
+ window->list = gtk_list_store_new(3,G_TYPE_BOOLEAN,G_TYPE_STRING,G_TYPE_INT);
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(window->list),2,GTK_SORT_ASCENDING);
+
+ yon_gtk_window_setup(GTK_WINDOW(window->Window),NULL,NULL,NULL,"GroupWindow");
+
+ g_signal_connect(G_OBJECT(window->Window),"destroy",G_CALLBACK(on_user_window_closed),window);
+ g_signal_connect(G_OBJECT(window->CancelButton),"clicked",G_CALLBACK(on_subwindow_close),NULL);
+ g_signal_connect(G_OBJECT(window->AcceptButton),"clicked",G_CALLBACK(on_users_window_accept),window);
+ g_signal_connect(G_OBJECT(window->StatusCell),"toggled",G_CALLBACK(on_group_clicked),window);
+ GtkTreeIter iter;
+ switch (mode){
+ case YON_USER_WINDOW_USERS_MULTIPLE:
+ gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(window->StatusCell),0);
+ [[fallthrough]];
+ case YON_USER_WINDOW_USERS:{
+ int size;
+ config_str system_param = yon_file_open("/etc/passwd",&size);
+ for (int i=0;i2&&!yon_char_is_empty(parsed[2])){
+ gtk_list_store_append(window->list,&iter);
+ gtk_list_store_set(window->list,&iter,0,0,1,parsed[0],2,atoi(parsed[2]),-1);
+ }
+ }
+ } break;
+
+ case YON_USER_WINDOW_GROUPS_MULTIPLE:
+ gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(window->StatusCell),0);
+ [[fallthrough]];
+ case YON_USER_WINDOW_GROUPS:{
+ int size;
+ config_str system_param = yon_file_open("/etc/group",&size);
+ for (int i=0;i2&&!yon_char_is_empty(parsed[2])){
+ gtk_list_store_append(window->list,&iter);
+ gtk_list_store_set(window->list,&iter,0,0,1,parsed[0],2,atoi(parsed[2]),-1);
+ }
+ }
+ } break;
+ }
+ gtk_tree_view_set_model(GTK_TREE_VIEW(window->UsersTree),GTK_TREE_MODEL(window->list));
+
+
+ g_signal_connect(G_OBJECT(window->CancelButton),"clicked",G_CALLBACK(on_subwindow_close),NULL);
+return window;
+}
+
+config_str yon_users_window_select(enum YON_USER_WINDOW_MODE_TYPE mode, unsigned int *size){
+ (*size) = 0;
+ yon_user_window *window = yon_user_window_new(mode);
+ gtk_widget_show(window->Window);
+ gtk_main();
+ (*size) = window->selection_size;
+ config_str ret = window->selection;
+ free(window);
+ return ret;
+}
diff --git a/source/libublsettingsui-gtk3.h b/source/libublsettingsui-gtk3.h
index 8e3b3d0..c40ebec 100644
--- a/source/libublsettingsui-gtk3.h
+++ b/source/libublsettingsui-gtk3.h
@@ -26,7 +26,7 @@
#define ui_glade_path_window "/com/ublinux/ui/libublsettingsui-gtk3-window.glade"
-
+#define ui_glade_path_userwindow "/com/ublinux/ui/libublsettingsui-gtk3-users-window.glade"
/**Путь до файла подтверждения открытия документации утилит ubl-settings-**/
#define ui_glade_path_documentation "/com/ublinux/ui/libublsettingsui-gtk3-documentation.glade"
@@ -365,6 +365,15 @@ void yon_window_remove_exit_config_check(template_main_window *widgets);
void yon_window_set_exit_config_check(template_main_window *widgets, GCallback data_callback_function);
+enum YON_USER_WINDOW_MODE_TYPE {
+ YON_USER_WINDOW_USERS,
+ YON_USER_WINDOW_USERS_MULTIPLE,
+ YON_USER_WINDOW_GROUPS,
+ YON_USER_WINDOW_GROUPS_MULTIPLE
+};
+
+config_str yon_users_window_select(enum YON_USER_WINDOW_MODE_TYPE mode, unsigned int *size);
+
typedef struct {
GtkWidget *Window;
GtkWidget *HeaderTopic;