Untitled
public
Jan 10, 2025
Never
45
1 #include <iostream> 2 #include <string> 3 #include <map> 4 #include <sstream> 5 #include <sys/socket.h> 6 #include <arpa/inet.h> 7 #include <unistd.h> 8 #include <gtk/gtk.h> 9 10 #define PORT 8080 11 12 int clientSocket; 13 bool isConnected = false; 14 15 int selectedDay = 1; 16 int selectedMonth = 0; 17 int selectedYear = 2024; 18 19 // Będziemy pamiętać o wydarzeniach lokalnie, 20 // by móc je łatwo zaznaczać w kalendarzu. 21 std::map<std::string, std::string> localCalendar; 22 23 // Referencja do GtkCalendar i do etykiety informacyjnej 24 GtkWidget *calendarWidget = nullptr; 25 GtkWidget *infoLabel = nullptr; 26 27 // Pomocnicza funkcja do zaznaczania dni w kalendarzu 28 // w których istnieją wydarzenia. 29 void updateCalendarMarks() { 30 // Czyścimy dotychczasowe zaznaczenia 31 gtk_calendar_clear_marks(GTK_CALENDAR(calendarWidget)); 32 33 34 // Dla każdego wpisu w localCalendar parsujemy datę i zaznaczamy w kalendarzu 35 for (auto &pair : localCalendar) { 36 // format daty: YYYY-MM-DD 37 std::string dateStr = pair.first; 38 // event: pair.second 39 40 int year, month, day; 41 if (sscanf(dateStr.c_str(), "%d-%d-%d", &year, &month, &day) == 3) { 42 43 g_print("Year: %d, Month: %d, Day: %d\n", year, month + 1, day); 44 45 46 47 // Uwaga: w GtkCalendar miesiące liczone są od 0, 48 // a lata musimy podawać normalnie (np. 2025). 49 // Dni również są 1-based, więc day jest OK. 50 // Zaznaczamy dzień 51 // Jeżeli chcemy ograniczyć się tylko do bieżącego widoku miesiąca, 52 // to można sprawdzić, czy (year,month) == (aktualnyRok, aktualnyMiesiac), 53 // ale tutaj zaznaczmy wszystkie. 54 55 56 gtk_calendar_mark_day(GTK_CALENDAR(calendarWidget), day); 57 } 58 59 } 60 } 61 62 // Funkcja wywoływana przy zmianie dnia w kalendarzu (kliknięcie) 63 extern "C" void on_calendar_day_selected(GtkCalendar *calendar, gpointer user_data) { 64 // Pobieramy aktualnie wybraną datę 65 guint year, month, day; 66 gtk_calendar_get_date(calendar, &year, &month, &day); 67 // month jest 0-based 68 69 gtk_calendar_get_date(calendar, (guint*)&selectedYear, (guint*)&selectedMonth, (guint*)&selectedDay); 70 selectedMonth += 1; 71 72 73 char dateBuffer[11]; 74 snprintf(dateBuffer, sizeof(dateBuffer), "%04u-%02u-%02u", year, month+1, day); 75 std::string selectedDate = dateBuffer; 76 77 auto it = localCalendar.find(selectedDate); 78 if (it != localCalendar.end()) { 79 // Mamy wydarzenie 80 std::string msg = "Wydarzenie: " + it->second; 81 gtk_label_set_text(GTK_LABEL(infoLabel), msg.c_str()); 82 } else { 83 gtk_label_set_text(GTK_LABEL(infoLabel), "Brak wydarzenia w tym dniu."); 84 } 85 } 86 87 // Funkcja obsługująca przycisk "Connect to Server" 88 extern "C" void on_connect_button_clicked(GtkWidget *widget, gpointer data) { 89 if (isConnected) { 90 gtk_label_set_text(GTK_LABEL(data), "Already connected!"); 91 return; 92 } 93 94 clientSocket = socket(AF_INET, SOCK_STREAM, 0); 95 if (clientSocket < 0) { 96 gtk_label_set_text(GTK_LABEL(data), "Socket creation failed!"); 97 return; 98 } 99 100 sockaddr_in serverAddress; 101 serverAddress.sin_family = AF_INET; 102 serverAddress.sin_port = htons(PORT); 103 inet_pton(AF_INET, "127.0.0.1", &serverAddress.sin_addr); 104 105 if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) { 106 gtk_label_set_text(GTK_LABEL(data), "Connection failed!"); 107 close(clientSocket); 108 return; 109 } 110 111 gtk_label_set_text(GTK_LABEL(data), "Connected to server!"); 112 isConnected = true; 113 } 114 115 // Funkcja obsługująca przycisk "Add Event" 116 extern "C" void on_add_event_button_clicked(GtkWidget *widget, gpointer data) { 117 GtkWidget **widgets = (GtkWidget **)data; 118 GtkWidget *eventEntry = widgets[0]; 119 GtkWidget *dateEntry = widgets[1]; 120 GtkWidget *statusLabel = widgets[2]; 121 122 if (!isConnected) { 123 gtk_label_set_text(GTK_LABEL(statusLabel), "Connect to server first!"); 124 return; 125 } 126 127 const char *eventText = gtk_entry_get_text(GTK_ENTRY(eventEntry)); 128 const char *dateText = gtk_entry_get_text(GTK_ENTRY(dateEntry)); 129 130 if (strlen(eventText) == 0 || strlen(dateText) == 0) { 131 gtk_label_set_text(GTK_LABEL(statusLabel), "Enter both date and event!"); 132 return; 133 } 134 135 // Komunikat do serwera 136 std::string fullEventText = "ADD " + std::string(dateText) + " " + std::string(eventText); 137 send(clientSocket, fullEventText.c_str(), fullEventText.size(), 0); 138 139 // Odczyt odpowiedzi 140 char buffer[1024] = {0}; 141 int bytesRead = read(clientSocket, buffer, sizeof(buffer)); 142 if (bytesRead > 0) { 143 gtk_label_set_text(GTK_LABEL(statusLabel), buffer); 144 } else { 145 gtk_label_set_text(GTK_LABEL(statusLabel), "Failed to add event!"); 146 } 147 148 // Dodajemy do lokalnej struktury i odświeżamy kalendarz 149 localCalendar[dateText] = eventText; 150 updateCalendarMarks(); 151 152 // Czyścimy pola 153 gtk_entry_set_text(GTK_ENTRY(eventEntry), ""); 154 gtk_entry_set_text(GTK_ENTRY(dateEntry), ""); 155 } 156 157 // Funkcja obsługująca przycisk "View Events" 158 extern "C" void on_view_events_button_clicked(GtkWidget *widget, gpointer data) { 159 GtkWidget *statusLabel = GTK_WIDGET(data); 160 161 if (!isConnected) { 162 gtk_label_set_text(GTK_LABEL(statusLabel), "Connect to server first!"); 163 return; 164 } 165 166 const char *viewCommand = "VIEW"; 167 send(clientSocket, viewCommand, strlen(viewCommand), 0); 168 169 char buffer[1024] = {0}; 170 int bytesRead = read(clientSocket, buffer, sizeof(buffer)); 171 if (bytesRead > 0) { 172 // Wyświetlamy w statusLabel pełną listę 173 gtk_label_set_text(GTK_LABEL(statusLabel), buffer); 174 175 // Parsujemy to, co przyszło, i aktualizujemy localCalendar 176 localCalendar.clear(); 177 std::stringstream ss(buffer); 178 std::string line; 179 while (std::getline(ss, line)) { 180 // Linia ma format: YYYY-MM-DD: event 181 // Przykład: 2025-01-10: Urodziny babci 182 if (line.find(":") != std::string::npos) { 183 auto pos = line.find(":"); 184 std::string datePart = line.substr(0, pos); 185 std::string eventPart = line.substr(pos + 2); // omijamy ": " (2 znaki) 186 if (!datePart.empty()) { 187 localCalendar[datePart] = eventPart; 188 } 189 } 190 } 191 updateCalendarMarks(); 192 193 } else { 194 gtk_label_set_text(GTK_LABEL(statusLabel), "Failed to retrieve events!"); 195 } 196 } 197 198 // Funkcja obsługująca przycisk "Disconnect" 199 extern "C" void on_exit_button_clicked(GtkWidget *widget, gpointer data) { 200 if (isConnected) { 201 const char *exitCommand = "EXIT"; 202 send(clientSocket, exitCommand, strlen(exitCommand), 0); 203 close(clientSocket); 204 isConnected = false; 205 gtk_label_set_text(GTK_LABEL(data), "Disconnected."); 206 } else { 207 gtk_label_set_text(GTK_LABEL(data), "No active connection."); 208 } 209 } 210 211 // Główna funkcja programu 212 int main(int argc, char *argv[]) { 213 gtk_init(&argc, &argv); 214 215 // Główne okno 216 GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 217 gtk_window_set_title(GTK_WINDOW(window), "Calendar Client GUI"); 218 gtk_window_set_default_size(GTK_WINDOW(window), 500, 400); 219 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); 220 221 // Główny kontener pionowy 222 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); 223 gtk_container_add(GTK_CONTAINER(window), vbox); 224 225 // Etykieta statusu/informacji 226 infoLabel = gtk_label_new("Status: Disconnected"); 227 gtk_box_pack_start(GTK_BOX(vbox), infoLabel, FALSE, FALSE, 0); 228 229 // Kalendarz 230 calendarWidget = gtk_calendar_new(); 231 gtk_calendar_set_display_options( 232 GTK_CALENDAR(calendarWidget), 233 static_cast<GtkCalendarDisplayOptions>( 234 GTK_CALENDAR_SHOW_HEADING 235 | GTK_CALENDAR_SHOW_DAY_NAMES 236 | GTK_CALENDAR_SHOW_WEEK_NUMBERS 237 ) 238 ); 239 240 // Gdy użytkownik kliknie w dzień w kalendarzu 241 g_signal_connect(calendarWidget, "day-selected", 242 G_CALLBACK(on_calendar_day_selected), nullptr); 243 244 gtk_box_pack_start(GTK_BOX(vbox), calendarWidget, FALSE, FALSE, 0); 245 246 // Pola do wpisywania daty i wydarzenia 247 GtkWidget *dateEntry = gtk_entry_new(); 248 gtk_entry_set_placeholder_text(GTK_ENTRY(dateEntry), "Enter date (YYYY-MM-DD)"); 249 gtk_box_pack_start(GTK_BOX(vbox), dateEntry, FALSE, FALSE, 0); 250 251 GtkWidget *eventEntry = gtk_entry_new(); 252 gtk_entry_set_placeholder_text(GTK_ENTRY(eventEntry), "Enter event"); 253 gtk_box_pack_start(GTK_BOX(vbox), eventEntry, FALSE, FALSE, 0); 254 255 // Przyciski 256 GtkWidget *connectButton = gtk_button_new_with_label("Connect to Server"); 257 GtkWidget *addEventButton = gtk_button_new_with_label("Add Event"); 258 GtkWidget *viewEventsButton = gtk_button_new_with_label("View Events"); 259 GtkWidget *exitButton = gtk_button_new_with_label("Disconnect"); 260 261 gtk_box_pack_start(GTK_BOX(vbox), connectButton, FALSE, FALSE, 0); 262 gtk_box_pack_start(GTK_BOX(vbox), addEventButton, FALSE, FALSE, 0); 263 gtk_box_pack_start(GTK_BOX(vbox), viewEventsButton, FALSE, FALSE, 0); 264 gtk_box_pack_start(GTK_BOX(vbox), exitButton, FALSE, FALSE, 0); 265 266 // Tablica wskaźników do przekazania w callbacku (wygoda) 267 GtkWidget *widgets[3] = { eventEntry, dateEntry, infoLabel }; 268 269 // Przypinamy sygnały 270 g_signal_connect(connectButton, "clicked", G_CALLBACK(on_connect_button_clicked), infoLabel); 271 g_signal_connect(addEventButton, "clicked", G_CALLBACK(on_add_event_button_clicked), widgets); 272 g_signal_connect(viewEventsButton, "clicked", G_CALLBACK(on_view_events_button_clicked), infoLabel); 273 g_signal_connect(exitButton, "clicked", G_CALLBACK(on_exit_button_clicked), infoLabel); 274 275 // Wyświetlamy wszystko 276 gtk_widget_show_all(window); 277 gtk_main(); 278 279 return 0; 280 }