From 7bc938aa697e3cdd1b07b3e88a402e9743bf6e7b Mon Sep 17 00:00:00 2001 From: "DLABAL, Eduard" Date: Thu, 15 May 2025 23:19:35 +0200 Subject: [PATCH] Enhance user management: update CSV data, refactor UUID search function, and implement person listing and search functionalities in the TUI. --- TestList.csv | 32 +++++- include/main.h | 2 +- include/tui.h | 4 + include/users.h | 2 +- src/tui.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++ src/users.c | 58 +++++------ 6 files changed, 320 insertions(+), 31 deletions(-) diff --git a/TestList.csv b/TestList.csv index 4a0c5e2..cfc65f4 100644 --- a/TestList.csv +++ b/TestList.csv @@ -1 +1,31 @@ -1,Kamil,Novak,2504,0,0,0 \ No newline at end of file +17,Klara,Novotna,3010,1,0,1 +18,Jan,Novak,3011,1,0,1 +19,Petr,Horak,3012,1,0,1 +20,Lucie,Kralova,3013,1,0,1 +21,Martin,Prochazka,3014,1,0,1 +22,Anna,Urbanova,3015,1,0,1 +23,David,Svoboda,3016,1,0,1 +24,Veronika,Kucerova,3017,1,0,1 +25,Tomas,Blaha,3018,1,0,1 +26,Barbora,Kratochvilova,3019,1,0,1 +27,Jakub,Pospisil,3020,1,0,1 +28,Eliska,Valkova,3021,1,0,1 +29,Ondrej,Stepanek,3022,1,0,1 +30,Simona,Holubova,3023,1,0,1 +31,Filip,Navratil,3024,1,0,1 +32,Adela,Slavikova,3025,1,0,1 +33,Radek,Polak,3026,1,0,1 +34,Monika,Adamcova,3027,1,0,1 +35,Jaroslav,Kolar,3028,1,0,1 +36,Petra,Malikova,3029,1,0,1 +37,Daniel,Richter,3030,1,0,1 +38,Kristyna,Stastna,3031,1,0,1 +39,Stepan,Musil,3032,1,0,1 +40,Lenka,Jurickova,3033,1,0,1 +41,Patrik,Vanek,3034,1,0,1 +42,Karolina,Vitkova,3035,1,0,1 +43,Stanislav,Sevcik,3036,1,0,1 +44,Alena,Matouskova,3037,1,0,1 +45,Josef,Suchy,3038,1,0,1 +46,Marketa,Rezacova,3039,1,0,1 +47,Libor,Hanak,3040,1,0,1 \ No newline at end of file diff --git a/include/main.h b/include/main.h index cd334dc..ba84ae6 100644 --- a/include/main.h +++ b/include/main.h @@ -5,7 +5,7 @@ #ifndef __MAIN_H__ #define __MAIN_H__ -#define TRUE 1 +#define TRUE !0 #define FALSE 0 #define BYTE uint8_t #define MIN_X_TERMINAL_SIZE 50 diff --git a/include/tui.h b/include/tui.h index adb03e6..4556860 100644 --- a/include/tui.h +++ b/include/tui.h @@ -11,4 +11,8 @@ void uartDialog(char *uart_adress, int terminal_x, int terminal_y); void mainMenu(list_t * person_list, int terminal_x, int terminal_y); +void personListing(list_t * person_list, int terminal_x, int terminal_y); + +void personSearch(list_t * person_list, int terminal_x, int terminal_y); + #endif \ No newline at end of file diff --git a/include/users.h b/include/users.h index d8a2802..96b4d90 100644 --- a/include/users.h +++ b/include/users.h @@ -59,7 +59,7 @@ uint16_t generateUUID(list_t *_list); * @param _surname Pointer to a string containing the user's surname. * @return Pointer to the UUID of the user if found, or 0 if no match is found. */ -uint16_t *searchUUIDByName(list_t *_list, char *_name, char *_surname); +uint16_t searchUUIDByName(list_t *_list, char *_name, char *_surname, uint16_t * _uuids_found); /** * @brief Searches for a person in a linked list by their UUID. diff --git a/src/tui.c b/src/tui.c index 767cf02..e6dfe12 100644 --- a/src/tui.c +++ b/src/tui.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "main.h" #include "tui.h" @@ -173,6 +174,12 @@ void mainMenu(list_t *person_list, int terminal_x, int terminal_y) { switch (highlight) { + case 0: + personListing(person_list, terminal_x, terminal_y); + break; + + case 1: + personSearch(person_list, terminal_x, terminal_y); case 5: if (keboard_input == '\n') @@ -190,3 +197,249 @@ void mainMenu(list_t *person_list, int terminal_x, int terminal_y) } } } + +void personListing(list_t *person_list, int terminal_x, int terminal_y) +{ + int win_height = 20; + int win_width = 76; + int start_y = (terminal_y - win_height) / 2; + int start_x = (terminal_x - win_width) / 2; + + start_color(); + + WINDOW *personlisting = newwin(win_height, win_width, start_y, start_x); + wbkgd(personlisting, COLOR_PAIR(1)); + box(personlisting, 0, 0); + + wattron(personlisting, COLOR_PAIR(1)); + wattron(personlisting, A_BOLD); + mvwprintw(personlisting, 0, (win_width - strlen("Filtered list")) / 2, "%s", "Filtered list"); + wattroff(personlisting, A_BOLD); + wattroff(personlisting, COLOR_PAIR(1)); + keypad(personlisting, TRUE); + + int max_rows = win_height - 2; + int total_count = 0; + node_t *current = person_list->head; + while (current) + { + total_count++; + current = current->next; + } + + int offset = 0; + int highlight = 0; + int keboard_input; + + while (1) + { + werase(personlisting); + box(personlisting, 0, 0); + wattron(personlisting, COLOR_PAIR(1)); + wattron(personlisting, A_BOLD); + mvwprintw(personlisting, 0, (win_width - strlen("Filtered list")) / 2, "%s", "Filtered list"); + wattroff(personlisting, A_BOLD); + wattroff(personlisting, COLOR_PAIR(1)); + + wattron(personlisting, A_BOLD); + mvwprintw(personlisting, 1, 2, "UUID Surname Name Available"); + wattroff(personlisting, A_BOLD); + + current = person_list->head; + int idx = 0, row = 2; + while (current && row < win_height - 1) + { + if (current->user.uuid) + if (idx >= offset && row < win_height - 1) + { + if (idx == highlight) + wattron(personlisting, COLOR_PAIR(2)); + mvwprintw(personlisting, row, 2, "%-10hu %-20s %-20s %s", + current->user.uuid, + current->user.surname, + current->user.name, + current->user.available ? "Yes " : "No "); + if (idx == highlight) + wattroff(personlisting, COLOR_PAIR(2)); + row++; + } + idx++; + current = current->next; + } + + wrefresh(personlisting); + + keboard_input = wgetch(personlisting); + if (keboard_input == KEY_UP) + { + if (highlight > 0) + { + highlight--; + if (highlight < offset) + offset--; + } + } + else if (keboard_input == KEY_DOWN) + { + if (highlight < total_count - 1) + { + highlight++; + if (highlight >= offset + max_rows) + offset++; + } + } + else if (keboard_input == '\n') + { + int idx = 0; + node_t *selected = person_list->head; + while (selected && idx < highlight) + { + selected = selected->next; + idx++; + } + } + else if (keboard_input == 27) + { + break; + } + } + + delwin(personlisting); + touchwin(stdscr); + refresh(); +} + +void personSearch(list_t *person_list, int terminal_x, int terminal_y) +{ + int win_height = 20; + int win_width = 76; + int start_y = (terminal_y - win_height) / 2; + int start_x = (terminal_x - win_width) / 2; + + char buttons[2][10] = {"", ""}; + char prompts[2][10] = {"Name ", "Surname "}; + + start_color(); + + WINDOW *searchdialog = newwin(win_height, win_width, start_y, start_x); + wbkgd(searchdialog, COLOR_PAIR(1)); + box(searchdialog, 0, 0); + + wattron(searchdialog, COLOR_PAIR(1)); + wattron(searchdialog, A_BOLD); + mvwprintw(searchdialog, 0, (win_width - strlen("Search")) / 2, "%s", "Search"); + wattroff(searchdialog, A_BOLD); + wattroff(searchdialog, COLOR_PAIR(1)); + keypad(searchdialog, TRUE); + + char choice; + int highlight = 0; + + int field_y = 2; + int field_x = 4; + static char name[32] = ""; + static char surname[32] = ""; + char *fields[2] = {name, surname}; + int field_lens[2] = {31, 31}; + + uint16_t * uuids_found; + + while (1) + { + + for (int i = 0; i < 2; i++) + { + if (highlight == i) + wattron(searchdialog, COLOR_PAIR(2)); + else + wattron(searchdialog, COLOR_PAIR(1)); + mvwprintw(searchdialog, field_y + i * 2, field_x, "%s [%30s]", prompts[i], fields[i]); + if (highlight == i) + wattroff(searchdialog, COLOR_PAIR(2)); + else + wattroff(searchdialog, COLOR_PAIR(1)); + } + + int button_y = field_y + 7; + int button_x = field_x; + for (int i = 0; i < 2; i++) + { + if (highlight == 2 + i) + wattron(searchdialog, COLOR_PAIR(2)); + else + wattron(searchdialog, COLOR_PAIR(1)); + wattron(searchdialog, A_BOLD); + mvwprintw(searchdialog, button_y, button_x + i * 12, "%s", buttons[i]); + wattroff(searchdialog, A_BOLD); + if (highlight == 2 + i) + wattroff(searchdialog, COLOR_PAIR(2)); + else + wattroff(searchdialog, COLOR_PAIR(1)); + } + + wrefresh(searchdialog); + + choice = wgetch(searchdialog); + + if (choice == '\t') + { + if (highlight < 3) + { + highlight++; + } + else + highlight = 0; + } + else if (choice == '\n') + { + if (highlight < 2) + { + echo(); + curs_set(1); + mvwprintw(searchdialog, field_y + highlight * 2, field_x + strlen(prompts[highlight]) + 3, "%-30s", ""); + wmove(searchdialog, field_y + highlight * 2, field_x + strlen(prompts[highlight]) + 4); + wgetnstr(searchdialog, fields[highlight], field_lens[highlight]); + curs_set(0); + noecho(); + } + else if (highlight == 2) + { + uint16_t count = searchUUIDByName(person_list, name, surname, uuids_found); + list_t found_pesons; + found_pesons.head = NULL; + node_t **last_ptr = &found_pesons.head; + for (uint16_t i = 0; i < count; i++) { + node_t *cur = person_list->head; + while (cur) { + if (cur->user.uuid == uuids_found[i]) { + node_t *new_node = malloc(sizeof(node_t)); + if (new_node) { + new_node->user = cur->user; + new_node->next = NULL; + *last_ptr = new_node; + last_ptr = &new_node->next; + } + break; + } + cur = cur->next; + } + } + personListing(&found_pesons, terminal_x, terminal_y); + } + else if (highlight == 3) + { + delwin(searchdialog); + touchwin(stdscr); + refresh(); + break; + } + } + else if (choice == 27) + { // ESC + delwin(searchdialog); + touchwin(stdscr); + refresh(); + break; + } + } +} \ No newline at end of file diff --git a/src/users.c b/src/users.c index 586e83c..c738187 100644 --- a/src/users.c +++ b/src/users.c @@ -56,49 +56,51 @@ node_t *searchPersonByUUID( return NULL; } -uint16_t *searchUUIDByName( +uint16_t searchUUIDByName( list_t *_list, - char *_name, - char *_surname) + const char *_name, + const char *_surname, + uint16_t **_uuids_found) { - int sum = 0; - uint16_t *uuids = malloc(sizeof(uint16_t)); - pthread_mutex_lock(&_list->lock); - node_t *current = _list->head; - - if (_list->head == NULL) - { + if (_list == NULL || _name == NULL || _surname == NULL || _uuids_found == NULL) { return 0; } - if (uuids == NULL) - { - puts("Fatal error: free memory is not sufficient for this operation"); - exit(EXIT_FAILURE); - } + uint16_t *uuids = NULL; + size_t sum = 0; + size_t capacity = 0; + + pthread_mutex_lock(&_list->lock); + node_t *current = _list->head; while (current != NULL) { - if (strcmp(_name, current->user.name) == 0 && strcmp(_surname, current->user.surname) == 0) + if (current->user.name != NULL && current->user.surname != NULL) { - sum++; - - uuids = realloc(uuids, sum * sizeof(uint16_t)); - if (uuids == NULL) + if (strcmp(_name, current->user.name) == 0 && strcmp(_surname, current->user.surname) == 0) { - puts("Fatal error: free memory is not sufficient for this operation"); - exit(EXIT_FAILURE); + if (sum >= capacity) { + capacity = (capacity == 0) ? 1 : capacity * 2; + uint16_t *tmp = realloc(uuids, capacity * sizeof(uint16_t)); + if (tmp == NULL) + { + pthread_mutex_unlock(&_list->lock); + free(uuids); + fprintf(stderr, "Fatal error: insufficient memory for this operation\n"); + *_uuids_found = NULL; + return 0; + } + uuids = tmp; + } + uuids[sum++] = current->user.uuid; } - - uuids[sum - 1] = current->user.uuid; } + current = current->next; } pthread_mutex_unlock(&_list->lock); - if (sum == 0) - - return NULL; - return uuids; + *_uuids_found = uuids; + return (uint16_t)sum; } int addPersonToList(