diff options
-rw-r--r-- | gtk_win.c | 19 | ||||
-rw-r--r-- | gtk_win.h | 124 | ||||
-rw-r--r-- | window_main.glade | 114 |
3 files changed, 182 insertions, 75 deletions
diff --git a/gtk_win.c b/gtk_win.c index 7b6ca57f5c18..3f4dbfc0ecae 100644 --- a/gtk_win.c +++ b/gtk_win.c @@ -221,8 +221,8 @@ void on_modify_button_clicked(GtkButton* button) { gtk_widget_grab_focus(GTK_WIDGET(gtk_builder_get_object(app.builder, "modify_symbol_entry"))); } -void on_modify_entry_activate(GtkEntry* entry, gpointer dialog) { - gtk_widget_hide(GTK_WIDGET(dialog)); +void on_modify_entry_activate(GtkEntry* entry) { + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(app.builder, "portfolio_modify_dialog"))); GtkEntry* symbol_entry = GTK_ENTRY(gtk_builder_get_object(app.builder, "modify_symbol_entry")); GtkEntry* amount_entry = GTK_ENTRY(gtk_builder_get_object(app.builder, "modify_amount_entry")); GtkEntry* spent_entry = GTK_ENTRY(gtk_builder_get_object(app.builder, "modify_spent_entry")); @@ -255,12 +255,13 @@ void on_modify_entry_activate(GtkEntry* entry, gpointer dialog) { void on_portfolio_modify_dialog_response(GtkDialog* dialog, gint response_id) { if (response_id == GTK_RESPONSE_CANCEL) gtk_widget_hide(GTK_WIDGET(dialog)); - else on_modify_entry_activate(NULL, NULL); // GTK_RESPONSE_OK + else on_modify_entry_activate(NULL); // GTK_RESPONSE_OK } -void on_password_entry_activate(GtkEntry* entry, gpointer dialog) { - gtk_widget_hide(GTK_WIDGET(dialog)); - const gchar* password = gtk_entry_get_text(entry); +void on_password_entry_activate(GtkEntry* entry) { + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(app.builder, "get_password_dialog"))); + const gchar* password = gtk_entry_get_text(GTK_ENTRY(gtk_builder_get_object(app.builder, + "password_entry"))); if (password == NULL || strcmp(password, "") == 0) // Return if NULL or empty entry text return; @@ -276,15 +277,15 @@ void on_password_entry_activate(GtkEntry* entry, gpointer dialog) { // Copy password to app strcpy(app.password, modified_pw); - // Load portfolio + // Reload portfolio on_load_button_clicked(NULL); } } -void on_get_password_dialog_response(GtkDialog* dialog, gint response_id, gpointer entry) { +void on_get_password_dialog_response(GtkDialog* dialog, gint response_id) { if (response_id == GTK_RESPONSE_CANCEL) gtk_widget_hide(GTK_WIDGET(dialog)); - else on_password_entry_activate(entry, dialog); // GTK_REPONSE_OK + else on_password_entry_activate(NULL); // GTK_REPONSE_OK } void on_check_window_destroy(void) { diff --git a/gtk_win.h b/gtk_win.h index 24cc6cf4455d..590ab0699ea4 100644 --- a/gtk_win.h +++ b/gtk_win.h @@ -17,46 +17,143 @@ typedef struct app_data { } App_Data; /** - * Opens GTK+ Window and prints portfolio data to it. Currently cannot handle encrypted portfolios. + * Initializes gtk, loads glade file, connects signals, shows the check window, and enters the + * main gtk loop. */ void window_main(void); +/** + * Precondition: app.portfolio_string is a String containing a JSON array of portfolio data + * + * If the JSON array is length 0, the function will do nothing. + * + * Otherwise, app.portfolio_data will be created from app.portfolio_string and the check list store + * will be cleared and appended with this data. + */ void check_list_create_from_string(void); +/** + * Precondition: check_list_create_from_string has already been called and api data has been + * stored in app.portfolio_data + * + * Api data from app.portfolio_data will be stored in the check list store + */ void check_list_add_api_data(void); -/** SIGNALS **/ +/********************* SIGNALS *********************/ +/** + * SIGNAL FOR LOAD BUTTON CLICK + * + * Loads the portfolio file, decrypts if necessary, collects api data, and adds all the data to + * the check list store. + * @param button UNUSED -- MAY BE NULL + */ void on_load_button_clicked(GtkButton* button); +/** + * SIGNAL FOR LOAD BUTTON CLICK + * + * Shows either the encrypt or decrypt dialog depending on the button's label. + * @param button a GtkButton with either label "Encrypt" or "Decrypt" + */ void on_lock_button_clicked(GtkButton* button); +/** + * SIGNAL FOR SET PASSWORD DIALOG RESPONSE + * + * If response is GTK_RESPONSE_CANCEL (if click cancel or press escape), hide the dialog. + * Otherwise, calls on_set_password_entry_activate. + * @param dialog + * @param response_id response of button activated -- either GTK_RESPONSE_CANCEL or GTK_RESPONSE_OK + */ void on_set_password_dialog_response(GtkDialog* dialog, gint response_id); +/** + * SIGNAL FOR SET PASSWORD ENTRY ACTIVATE + * + * Activated by keypress ENTER. + * + * If the length of the entered password is not between 6 and 30 characters or the two entered + * passwords are not the same, the password will not be set. + * @param entry UNUSED -- MAY BE NULL + */ void on_set_password_entry_activate(GtkEntry* entry); +/** + * SIGNAL FOR DECRYPT DIALOG RESPONSE + * + * If response is GTK_RESPONSE_CANCEL (if click cancel or press escape), hide the dialog. + * Otherwise, calls on_decrypt_password_entry_activate. + * @param dialog + * @param response_id response of button activated -- either GTK_RESPONSE_CANCEL or GTK_RESPONSE_OK + */ void on_decrypt_dialog_response(GtkDialog* dialog, gint response_id); +/** + * SIGNAL FOR DECRYPT PASSWORD ENTRY ACTIVATE + * + * If the entered password matches app.password, app.password will be cleared. + * @param entry UNUSED -- MAY BE NULL + */ void on_decrypt_password_entry_activate(GtkEntry* entry); +/** + * SIGNAL FOR ADD, REMOVE, AND SET BUTTON CLICK + * + * Opens portfolio_modify_dialog based on which button was clicked. + * @param button the button clicked + */ void on_modify_button_clicked(GtkButton* button); -void on_modify_entry_activate(GtkEntry* entry, gpointer dialog); +/** + * SIGNAL FOR MODIFY ENTRY ACTIVATE + * + * Modifies app.portfolio_string according to the values entered in portfolio_modify_dialog + * @param entry UNUSED -- MAY BE NULL + */ +void on_modify_entry_activate(GtkEntry* entry); +/** + * SIGNAL FOR PORTFOLIO MODIFY DIALOG RESPONSE + * + * If response is GTK_RESPONSE_CANCEL (if click cancel or press escape), hide the dialog. + * Otherwise, calls on_modify_entry_activate. + * @param dialog + * @param response_id response of button activated -- either GTK_RESPONSE_CANCEL or GTK_RESPONSE_OK + */ void on_portfolio_modify_dialog_response(GtkDialog* dialog, gint response_id); -void on_password_entry_activate(GtkEntry* entry, gpointer dialog); +/** + * SIGNAL FOR PASSWORD ENTRY ACTIVATE + * + * If the entered password is correct, copy the password to app.password and load the portfolio + * @param entry UNUSED -- MAY BE NULL + */ +void on_password_entry_activate(GtkEntry* entry); -void on_get_password_dialog_response(GtkDialog* dialog, gint response_id, gpointer entry); +/** + * SIGNAL FOR GET PASSWORD DIALOG RESPONSE + * + * If response is GTK_RESPONSE_CANCEL (if click cancel or press escape), hide the dialog. + * Otherwise, calls on_password_entry_activate. + * @param dialog + * @param response_id response of button activated -- either GTK_RESPONSE_CANCEL or GTK_RESPONSE_OK + */ +void on_get_password_dialog_response(GtkDialog* dialog, gint response_id); /** - * Signal handler for destroying main window. Exits the program. + * SIGNAL FOR CHECK WINDOW DESTROY + * + * Encrypts and writes the portfolio to file if necessary. Unrefs gtk builder and exits main gtk + * loop. Destroys all memory in app. */ void on_check_window_destroy(void); /** - * Signal handler for clicking column labels. Sorts the ListStore struct according to which - * column was clicked. + * SIGNAL FOR COLUMN CLICKED + * + * Sorts the ListStore struct according to which column was clicked. * @param column clicked column * @param list_store portfolio data list */ @@ -66,7 +163,7 @@ void on_column_clicked(GtkTreeViewColumn* column, GtkListStore* list_store); /** * Formats text in Info structs for printing to window - * @param portfolio_data + * @param portfolio_data Info_Array* with valid Info data in it. */ void format_cells(Info_Array* portfolio_data); @@ -77,8 +174,17 @@ void format_cells(Info_Array* portfolio_data); */ void list_store_sort(GtkListStore* list_store, Col_Index idx); +/** + * Destroys app.portfolio_data and recreates it from app.portfolio_string with api data. Then + * recreates the check list. + */ void list_store_update(void); +/** + * Shows a generic message dialog. + * @param message the message to show + * @param success if true, will show a success dialog. otherwise it will show an error dialog. + */ void show_generic_message_dialog(const char* message, gboolean success); #endif
\ No newline at end of file diff --git a/window_main.glade b/window_main.glade index a877bc127e13..1c71fddca254 100644 --- a/window_main.glade +++ b/window_main.glade @@ -447,6 +447,58 @@ https://github.com/aokellermann/ </object> </child> </object> + <object class="GtkMessageDialog" id="decrypt_dialog"> + <property name="can_focus">False</property> + <property name="modal">True</property> + <property name="destroy_with_parent">True</property> + <property name="type_hint">dialog</property> + <property name="skip_taskbar_hint">True</property> + <property name="urgency_hint">True</property> + <property name="transient_for">check_window</property> + <property name="message_type">question</property> + <property name="buttons">ok-cancel</property> + <property name="text" translatable="yes">Enter your password:</property> + <signal name="close" handler="gtk_widget_hide" swapped="no"/> + <signal name="destroy-event" handler="gtk_widget_hide_on_delete" swapped="no"/> + <signal name="response" handler="on_decrypt_dialog_response" swapped="no"/> + <child> + <placeholder/> + </child> + <child internal-child="vbox"> + <object class="GtkBox"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkButtonBox"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="decrypt_password_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">●</property> + <property name="max_width_chars">31</property> + <property name="input_purpose">password</property> + <signal name="activate" handler="on_decrypt_password_entry_activate" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + </object> <object class="GtkMessageDialog" id="generic_check_window_error_dialog"> <property name="can_focus">False</property> <property name="type_hint">dialog</property> @@ -520,7 +572,7 @@ https://github.com/aokellermann/ <property name="text" translatable="yes">Enter your password:</property> <signal name="close" handler="gtk_widget_hide" swapped="no"/> <signal name="delete-event" handler="gtk_widget_hide_on_delete" swapped="no"/> - <signal name="response" handler="on_get_password_dialog_response" object="password_entry" swapped="no"/> + <signal name="response" handler="on_get_password_dialog_response" swapped="no"/> <child> <placeholder/> </child> @@ -549,7 +601,7 @@ https://github.com/aokellermann/ <property name="invisible_char">●</property> <property name="max_width_chars">31</property> <property name="input_purpose">password</property> - <signal name="activate" handler="on_password_entry_activate" object="get_password_dialog" swapped="no"/> + <signal name="activate" handler="on_password_entry_activate" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -599,7 +651,7 @@ https://github.com/aokellermann/ <property name="caps_lock_warning">False</property> <property name="placeholder_text" translatable="yes">Symbol</property> <property name="input_purpose">alpha</property> - <signal name="activate" handler="on_modify_entry_activate" object="portfolio_modify_dialog" swapped="no"/> + <signal name="activate" handler="on_modify_entry_activate" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -614,7 +666,7 @@ https://github.com/aokellermann/ <property name="max_width_chars">16</property> <property name="placeholder_text" translatable="yes">Quantity</property> <property name="input_purpose">digits</property> - <signal name="activate" handler="on_modify_entry_activate" object="portfolio_modify_dialog" swapped="no"/> + <signal name="activate" handler="on_modify_entry_activate" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -629,7 +681,7 @@ https://github.com/aokellermann/ <property name="max_width_chars">16</property> <property name="placeholder_text" translatable="yes">Price per share</property> <property name="input_purpose">digits</property> - <signal name="activate" handler="on_modify_entry_activate" object="portfolio_modify_dialog" swapped="no"/> + <signal name="activate" handler="on_modify_entry_activate" swapped="no"/> </object> <packing> <property name="expand">False</property> @@ -709,56 +761,4 @@ https://github.com/aokellermann/ </object> </child> </object> - <object class="GtkMessageDialog" id="decrypt_dialog"> - <property name="can_focus">False</property> - <property name="modal">True</property> - <property name="destroy_with_parent">True</property> - <property name="type_hint">dialog</property> - <property name="skip_taskbar_hint">True</property> - <property name="urgency_hint">True</property> - <property name="transient_for">check_window</property> - <property name="message_type">question</property> - <property name="buttons">ok-cancel</property> - <property name="text" translatable="yes">Enter your password:</property> - <signal name="close" handler="gtk_widget_hide" swapped="no"/> - <signal name="destroy-event" handler="gtk_widget_hide_on_delete" swapped="no"/> - <signal name="response" handler="on_decrypt_dialog_response" swapped="no"/> - <child> - <placeholder/> - </child> - <child internal-child="vbox"> - <object class="GtkBox"> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">2</property> - <child internal-child="action_area"> - <object class="GtkButtonBox"> - <property name="can_focus">False</property> - <property name="layout_style">end</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="decrypt_password_entry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="visibility">False</property> - <property name="invisible_char">●</property> - <property name="max_width_chars">31</property> - <property name="input_purpose">password</property> - <signal name="activate" handler="on_decrypt_password_entry_activate" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - </child> - </object> </interface> |