Enhance database management and TUI functionality: update person data in CSV, add edit and delete options in TUI, and improve mutex handling in user functions.

This commit is contained in:
2025-05-18 00:49:59 +02:00
parent 9e7fa91180
commit 1650a741b2
4 changed files with 293 additions and 24 deletions
+8 -6
View File
@@ -1,19 +1,17 @@
1,Klara,Novotna,3010,1,0,0 1,Klara,Novotna,3010,1,0,0
2,Jan,Novak,3011,1,0,0 2,Jan,Novak,3011,1,0,0
3,Petr,Horak,3012,1,0,0
4,Lucie,Kralova,3013,1747515862,416,0 4,Lucie,Kralova,3013,1747515862,416,0
5,Martin,Prochazka,3014,1,0,0
6,Anna,Urbanova,3015,1747515857,0,1 6,Anna,Urbanova,3015,1747515857,0,1
7,David,Svoboda,3016,1,0,0 7,David,Svoboda,3016,1747519032,0,1
8,Veronika,Kucerova,3017,1,0,0 8,Veronika,Kucerova,3017,1,0,0
9,Tomas,Blaha,3018,1747515450,0,1 9,Tomas,Blaha,3018,1747518718,3268,0
10,Barbora,Kratochvilova,3019,1,0,0 10,Barbora,Kratochvilova,3019,1,0,0
11,Jakub,Pospisil,3020,1747515462,0,1 11,Jakub,Pospisil,3020,1747515462,0,1
12,Eliska,Valkova,3021,1,0,0 12,Eliska,Valkova,3021,1747518666,0,1
13,Ondrej,Stepanek,3022,1747515457,0,1 13,Ondrej,Stepanek,3022,1747515457,0,1
14,Simona,Holubova,3023,1747515453,0,1 14,Simona,Holubova,3023,1747515453,0,1
15,Filip,Navratil,3024,1,0,0 15,Filip,Navratil,3024,1,0,0
16,Adela,Slavikova,3025,1,0,0 16,Adela,Slavikova,3025,1747518672,0,1
17,Radek,Polak,3026,1,0,0 17,Radek,Polak,3026,1,0,0
18,Monika,Adamcova,3027,1,0,0 18,Monika,Adamcova,3027,1,0,0
19,Jaroslav,Kolar,3028,1,0,0 19,Jaroslav,Kolar,3028,1,0,0
@@ -30,3 +28,7 @@
30,Marketa,Rezacova,3039,1,0,0 30,Marketa,Rezacova,3039,1,0,0
31,Libor,Hanak,3040,1,0,0 31,Libor,Hanak,3040,1,0,0
32,Libor,Hanak,3040,1,0,0 32,Libor,Hanak,3040,1,0,0
17267,Kamil,Novacek,2502,0,0,0
17747,Kamil,Franta,2502,0,0,0
17767,Kamil,Filip,2502,0,0,0
9158,Jindrich,Sidlo,2440,0,0,0
1 1 Klara Novotna 3010 1 0 0
2 2 Jan Novak 3011 1 0 0
3 Petr Horak 3012 1 0 0
3 4 Lucie Kralova 3013 1747515862 416 0
5 Martin Prochazka 3014 1 0 0
4 6 Anna Urbanova 3015 1747515857 0 1
5 7 David Svoboda 3016 1 1747519032 0 0 1
6 8 Veronika Kucerova 3017 1 0 0
7 9 Tomas Blaha 3018 1747515450 1747518718 0 3268 1 0
8 10 Barbora Kratochvilova 3019 1 0 0
9 11 Jakub Pospisil 3020 1747515462 0 1
10 12 Eliska Valkova 3021 1 1747518666 0 0 1
11 13 Ondrej Stepanek 3022 1747515457 0 1
12 14 Simona Holubova 3023 1747515453 0 1
13 15 Filip Navratil 3024 1 0 0
14 16 Adela Slavikova 3025 1 1747518672 0 0 1
15 17 Radek Polak 3026 1 0 0
16 18 Monika Adamcova 3027 1 0 0
17 19 Jaroslav Kolar 3028 1 0 0
28 30 Marketa Rezacova 3039 1 0 0
29 31 Libor Hanak 3040 1 0 0
30 32 Libor Hanak 3040 1 0 0
31 17267 Kamil Novacek 2502 0 0 0
32 17747 Kamil Franta 2502 0 0 0
33 17767 Kamil Filip 2502 0 0 0
34 9158 Jindrich Sidlo 2440 0 0 0
+2
View File
@@ -55,6 +55,7 @@ int main(int argc, char const **argv)
puts("Corrupted and/or empty list. Exiting...\n"); puts("Corrupted and/or empty list. Exiting...\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
pthread_mutex_unlock(&person_list.lock);
noecho(); noecho();
noraw(); noraw();
@@ -118,6 +119,7 @@ int main(int argc, char const **argv)
pthread_join(uart_thread, NULL); pthread_join(uart_thread, NULL);
free(args); free(args);
pthread_mutex_destroy(&person_list.lock);
clear(); clear();
endwin(); endwin();
+274 -11
View File
@@ -216,6 +216,10 @@ void mainMenu(list_t *person_list, char *db_filename, int terminal_x, int termin
case 1: case 1:
personSearch(person_list, terminal_x, terminal_y); personSearch(person_list, terminal_x, terminal_y);
break; break;
case 2:
editDatabaseMenu(person_list, terminal_x, terminal_y);
break;
case 3: case 3:
if (!saveListToCSV(db_filename, person_list)) if (!saveListToCSV(db_filename, person_list))
dialogWindow(3, "Unknown error while saving.", terminal_x, terminal_y); dialogWindow(3, "Unknown error while saving.", terminal_x, terminal_y);
@@ -249,7 +253,7 @@ void mainMenu(list_t *person_list, char *db_filename, int terminal_x, int termin
void personListing(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_height = 22;
int win_width = 76; int win_width = 76;
int start_y = (terminal_y - win_height) / 2; int start_y = (terminal_y - win_height) / 2;
int start_x = (terminal_x - win_width) / 2; int start_x = (terminal_x - win_width) / 2;
@@ -279,10 +283,9 @@ void personListing(list_t *person_list, int terminal_x, int terminal_y)
current = person_list->head; current = person_list->head;
int idx = 0, row = 2; int idx = 0, row = 2;
while (current && row < win_height) while (current && row < win_height -1)
{ {
if (idx >= offset)
if (idx >= offset && row < win_height - 1)
{ {
if (idx == highlight) if (idx == highlight)
wattron(personlisting, COLOR_PAIR(2)); wattron(personlisting, COLOR_PAIR(2));
@@ -299,6 +302,7 @@ void personListing(list_t *person_list, int terminal_x, int terminal_y)
current = current->next; current = current->next;
} }
wrefresh(personlisting); wrefresh(personlisting);
keyboard_input = wgetch(personlisting); keyboard_input = wgetch(personlisting);
@@ -489,10 +493,7 @@ void personInfo(list_t *_list, node_t *_person, int terminal_x, int terminal_y)
WINDOW *personinfodialog = newwin(win_height, win_width, start_y, start_x); WINDOW *personinfodialog = newwin(win_height, win_width, start_y, start_x);
int max_rows = win_height - 2; char buttons[3][20] = {"<Print to file>", "<Add Time Event>", "<Back>"};
int total_count = 0;
char buttons[3][20] = {"<Print to file...>", "<Add Time Event>", "<Back>"};
char prompts[6][32] = {"Name", "Surname", "Department", "Last time event", "Total time", "Available"}; char prompts[6][32] = {"Name", "Surname", "Department", "Last time event", "Total time", "Available"};
char keyboard_input; char keyboard_input;
@@ -500,8 +501,7 @@ void personInfo(list_t *_list, node_t *_person, int terminal_x, int terminal_y)
int field_y = 2; int field_y = 2;
int field_x = 4; int field_x = 4;
int button_y = field_y + 15;
int button_x = field_x;
while (1) while (1)
{ {
@@ -556,7 +556,10 @@ void personInfo(list_t *_list, node_t *_person, int terminal_x, int terminal_y)
{ {
if (highlight == 0) if (highlight == 0)
{ {
exportPersonInfo(_person); if (exportPersonInfo(_person))
dialogWindow(1, "Export succesfully created", terminal_x, terminal_y);
else
dialogWindow(3, "Unknown error", terminal_x, terminal_y);
} }
else if (highlight == 1) else if (highlight == 1)
{ {
@@ -686,14 +689,274 @@ int exportDialog(list_t *_list, int terminal_x, int terminal_y)
void editDatabaseMenu(list_t *_person_list, int terminal_x, int terminal_y) void editDatabaseMenu(list_t *_person_list, int terminal_x, int terminal_y)
{ {
int win_height = 10;
int win_width = 50;
int start_y = (terminal_y - win_height) / 2;
int start_x = (terminal_x - win_width) / 2;
char choices[4][30] = {"Add person to database", "Remove person from database", "Log time event", "Back"};
char keyboard_input;
int highlight = 0;
start_color();
WINDOW *mainmenu = newwin(win_height, win_width, start_y, start_x);
while (1)
{
initWindow(mainmenu, win_width, terminal_x, terminal_y, STANDARD_WIN_COLOUR, "Database Editing");
for (int i = 0; i < 6; i++)
{
if (i == highlight)
wattron(mainmenu, COLOR_PAIR(2));
else
wattron(mainmenu, COLOR_PAIR(1));
wattron(mainmenu, A_BOLD);
mvwprintw(mainmenu, 2 + i, (win_width - strlen(choices[i])) / 2, "%s", choices[i]);
wattroff(mainmenu, A_BOLD);
if (i == highlight)
wattroff(mainmenu, COLOR_PAIR(2));
else
wattroff(mainmenu, COLOR_PAIR(1));
}
wrefresh(mainmenu);
flushinp();
keyboard_input = wgetch(mainmenu);
if (keyboard_input == '\t')
{
if (highlight < 3)
highlight++;
else
highlight = 0;
}
else if (keyboard_input == '\n')
{
switch (highlight)
{
case 0:
addPersonDialog(_person_list, terminal_x, terminal_y);
break;
case 1:
deletePersonDialog(_person_list, terminal_x, terminal_y);
break;
case 2:
dialogWindow(2, "You can add time event for existing user from main menu", terminal_x, terminal_y);
break;
case 3:
if (keyboard_input == '\n')
{
wclear(mainmenu);
wrefresh(mainmenu);
touchwin(stdscr);
refresh();
delwin(mainmenu);
refresh();
return;
}
break;
}
}
}
} }
void addPersonDialog(list_t *_person_list, int terminal_x, int terminal_y) void addPersonDialog(list_t *_person_list, int terminal_x, int terminal_y)
{ {
int win_height = 14;
int win_width = 60;
int start_y = (terminal_y - win_height) / 2;
int start_x = (terminal_x - win_width) / 2;
WINDOW *addwin = newwin(win_height, win_width, start_y, start_x);
initWindow(addwin, win_width, terminal_x, terminal_y, STANDARD_WIN_COLOUR, "Add Person");
char name[32] = "";
char surname[32] = "";
char department[8] = "";
int highlight = 0;
char *fields[3] = {name, surname, department};
int field_lens[3] = {31, 31, 7};
char *prompts[3] = {"Name", "Surname", "Department"};
char *buttons[2] = {"<Add>", "<Back>"};
while (1)
{
werase(addwin);
initWindow(addwin, win_width, terminal_x, terminal_y, STANDARD_WIN_COLOUR, "Add Person");
for (int i = 0; i < 3; i++)
{
if (highlight == i)
wattron(addwin, COLOR_PAIR(2));
else
wattron(addwin, COLOR_PAIR(1));
mvwprintw(addwin, 2 + i * 2, 4, "%s: [%s]", prompts[i], fields[i][0] ? fields[i] : "______________________________");
if (highlight == i)
wattroff(addwin, COLOR_PAIR(2));
else
wattroff(addwin, COLOR_PAIR(1));
}
for (int i = 0; i < 2; i++)
{
if (highlight == 3 + i)
wattron(addwin, COLOR_PAIR(2) | A_BOLD);
else
wattron(addwin, COLOR_PAIR(1) | A_BOLD);
mvwprintw(addwin, 10, 4 + i * 16, "%s", buttons[i]);
if (highlight == 3 + i)
wattroff(addwin, COLOR_PAIR(2) | A_BOLD);
else
wattroff(addwin, COLOR_PAIR(1) | A_BOLD);
}
wrefresh(addwin);
int ch = wgetch(addwin);
if (ch == '\t')
{
highlight = (highlight + 1) % 5;
}
else if (ch == '\n')
{
if (highlight < 3)
{
echo();
curs_set(1);
mvwprintw(addwin, 2 + highlight * 2, 7 + strlen(prompts[highlight]), "%-30s", "");
wmove(addwin, 2 + highlight * 2, 7 + strlen(prompts[highlight]));
wgetnstr(addwin, fields[highlight], field_lens[highlight]);
curs_set(0);
noecho();
}
else if (highlight == 3)
{
if (strlen(name) == 0 || strlen(surname) == 0 || strlen(department) == 0)
{
dialogWindow(3, "All fields must be filled.", terminal_x, terminal_y);
continue;
}
if (addPersonToList(_person_list, name, surname, atoi(department)))
{
dialogWindow(1, "Person added successfully.", terminal_x, terminal_y);
}
else
{
dialogWindow(3, "Failed to add person.", terminal_x, terminal_y);
}
delwin(addwin);
touchwin(stdscr);
refresh();
return;
}
else if (highlight == 4)
{
delwin(addwin);
touchwin(stdscr);
refresh();
return;
}
}
else if (ch == 27 || ch == 'q')
{
delwin(addwin);
touchwin(stdscr);
refresh();
return;
}
}
} }
void deletePersonDialog(list_t *_person_list, int terminal_x, int terminal_y) void deletePersonDialog(list_t *_person_list, int terminal_x, int terminal_y)
{ {
int win_height = 8;
int win_width = 50;
int start_y = (terminal_y - win_height) / 2;
int start_x = (terminal_x - win_width) / 2;
WINDOW *delwin_dialog = newwin(win_height, win_width, start_y, start_x);
initWindow(delwin_dialog, win_width, terminal_x, terminal_y, STANDARD_WIN_COLOUR, "Delete Person");
char prompt[] = "Enter UUID of person to delete:";
char input[16] = "";
int highlight = 0;
int button_x = (win_width - 7) / 2;
int text_x = (win_width - 18) / 2;
while (1)
{
werase(delwin_dialog);
initWindow(delwin_dialog, win_width, terminal_x, terminal_y, STANDARD_WIN_COLOUR, "Delete Person");
mvwprintw(delwin_dialog, 2, (win_width - strlen(prompt)) / 2, "%s", prompt);
if (highlight == 0)
wattron(delwin_dialog, COLOR_PAIR(2));
else
wattron(delwin_dialog, COLOR_PAIR(1));
mvwprintw(delwin_dialog, 4, text_x, "[%15s]", input);
if (highlight == 0)
wattroff(delwin_dialog, COLOR_PAIR(2));
else
wattroff(delwin_dialog, COLOR_PAIR(1));
if (highlight == 1)
wattron(delwin_dialog, COLOR_PAIR(2) | A_BOLD);
else
wattron(delwin_dialog, COLOR_PAIR(1) | A_BOLD);
mvwprintw(delwin_dialog, 6, button_x, "<Delete>");
if (highlight == 1)
wattroff(delwin_dialog, COLOR_PAIR(2) | A_BOLD);
else
wattroff(delwin_dialog, COLOR_PAIR(1) | A_BOLD);
wrefresh(delwin_dialog);
int ch = wgetch(delwin_dialog);
if (ch == '\t')
{
highlight = !highlight;
}
else if (ch == '\n')
{
if (highlight == 0)
{
echo();
curs_set(1);
mvwprintw(delwin_dialog, 4, text_x + 1, "%-15s", "");
wmove(delwin_dialog, 4, text_x + 1);
wgetnstr(delwin_dialog, input, 15);
curs_set(0);
noecho();
}
else if (highlight == 1)
{
uint16_t uuid = (uint16_t)atoi(input);
node_t *for_delete = searchPersonByUUID(_person_list, uuid);
if (removePersonFromList(_person_list, &for_delete))
{
dialogWindow(1, "Person deleted successfully.", terminal_x, terminal_y);
}
else
{
dialogWindow(3, "Person not found.", terminal_x, terminal_y);
}
delwin(delwin_dialog);
touchwin(stdscr);
refresh();
return;
}
}
else if (ch == 27 || ch == 'q')
{
delwin(delwin_dialog);
touchwin(stdscr);
refresh();
return;
}
}
} }
+9 -7
View File
@@ -15,12 +15,11 @@ uint16_t generateUUID(
{ {
uint16_t uuid; uint16_t uuid;
int found; int found;
pthread_mutex_lock(&_list->lock);
do do
{ {
found = 0; found = 0;
uuid = (uint16_t)(rand() % (UINT16_MAX + 1)); uuid = (uint16_t)(rand() % (UINT16_MAX + 1));
pthread_mutex_lock(&_list->lock);
node_t *current = _list->head; node_t *current = _list->head;
while (current != NULL) while (current != NULL)
{ {
@@ -60,7 +59,8 @@ uint16_t searchUUIDByName(list_t *_list, char *_name, char *_surname, uint16_t *
{ {
uint16_t sum = 0; uint16_t sum = 0;
uint16_t *uuids = malloc(sizeof(uint16_t)); uint16_t *uuids = malloc(sizeof(uint16_t));
if (uuids == NULL) { if (uuids == NULL)
{
*_uuids_found = NULL; *_uuids_found = NULL;
return 0; return 0;
} }
@@ -127,7 +127,7 @@ int addPersonToList(
strcpy(new_node->user.name, _name); strcpy(new_node->user.name, _name);
strcpy(new_node->user.surname, _surname); strcpy(new_node->user.surname, _surname);
new_node->user.department = _department; new_node->user.department = _department;
new_node->user.last_time_event = -255; new_node->user.last_time_event = 0;
new_node->user.total = 0; new_node->user.total = 0;
new_node->user.available = FALSE; new_node->user.available = FALSE;
@@ -166,7 +166,8 @@ int loadPersonToList(list_t *_list, uint16_t _uuid, char *_name, char *_surname,
if (_list->head == NULL) if (_list->head == NULL)
{ {
_list->head = (node_t *)malloc(sizeof(node_t)); _list->head = (node_t *)malloc(sizeof(node_t));
if (_list->head == NULL) { if (_list->head == NULL)
{
pthread_mutex_unlock(&_list->lock); pthread_mutex_unlock(&_list->lock);
return 0; return 0;
} }
@@ -236,7 +237,6 @@ int loadPersonToList(list_t *_list, uint16_t _uuid, char *_name, char *_surname,
} }
current->next = new_node; current->next = new_node;
pthread_mutex_unlock(&_list->lock); pthread_mutex_unlock(&_list->lock);
return 1; return 1;
} }
@@ -254,7 +254,8 @@ int addTimeEvent(
pthread_mutex_lock(&_list->lock); pthread_mutex_lock(&_list->lock);
if (_person->user.available) if (_person->user.available)
{ {
if (current_time > _person->user.last_time_event) { if (current_time > _person->user.last_time_event)
{
_person->user.total += (current_time - _person->user.last_time_event); _person->user.total += (current_time - _person->user.last_time_event);
} }
} }
@@ -291,6 +292,7 @@ int removePersonFromList(list_t *_list, node_t **_person)
free(current->user.surname); free(current->user.surname);
free(current); free(current);
*_person = NULL; *_person = NULL;
pthread_mutex_unlock(&_list->lock);
return 1; return 1;
} }
prev = current; prev = current;