progressdialog.c (8311B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2024 the Claws Mail team and Hiroyuki Yamamoto 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <glib.h> 20 #include <glib/gi18n.h> 21 #include <gtk/gtk.h> 22 23 #include "progressdialog.h" 24 #include "gtkutils.h" 25 #include "utils.h" 26 27 enum { 28 PROGRESS_IMAGE, 29 PROGRESS_ACCOUNT, 30 PROGRESS_STATE, 31 N_PROGRESS_COLUMNS 32 }; 33 34 static gint progress_dialog_insert_account(ProgressDialog *progress, 35 gint row, 36 const gchar *account, 37 const gchar *status, 38 GdkPixbuf *image); 39 40 static void progress_dialog_hide_btn_cb(GtkWidget *widget, gpointer data); 41 static void progress_dialog_delete_event_btn_cb(GtkWidget *widget, gpointer data); 42 43 ProgressDialog *progress_dialog_create(void) 44 { 45 ProgressDialog *progress; 46 GtkWidget *dialog; 47 GtkWidget *hbox; 48 GtkWidget *vbox; 49 GtkWidget *label; 50 GtkWidget *hide_btn; 51 GtkWidget *showlog_btn; 52 GtkWidget *cancel_btn; 53 GtkWidget *progressbar; 54 GtkWidget *scrolledwin; 55 GtkWidget *treeview; 56 GtkListStore *store; 57 GtkTreeSelection *selection; 58 GtkTreeViewColumn *column; 59 GtkCellRenderer *renderer; 60 61 debug_print("Creating progress dialog...\n"); 62 progress = g_new0(ProgressDialog, 1); 63 64 dialog = gtk_dialog_new(); 65 gtk_window_set_resizable(GTK_WINDOW(dialog), TRUE); 66 gtk_widget_realize(dialog); 67 68 vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); 69 gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); 70 gtk_box_set_spacing(GTK_BOX(vbox), 8); 71 72 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); 73 gtk_box_pack_start(GTK_BOX(vbox), hbox, 74 FALSE, FALSE, 8); 75 gtk_widget_show(hbox); 76 77 label = gtk_label_new(""); 78 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 8); 79 gtk_widget_show(label); 80 81 hide_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), 82 _("_Hide"), 83 GTK_RESPONSE_NONE); 84 showlog_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), 85 _("_View log"), 86 GTK_RESPONSE_NONE); 87 cancel_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), 88 _("_Cancel"), 89 GTK_RESPONSE_NONE); 90 gtk_widget_grab_default(cancel_btn); 91 gtk_widget_grab_focus(cancel_btn); 92 93 progressbar = gtk_progress_bar_new(); 94 gtk_box_pack_start(GTK_BOX(vbox), progressbar, 95 FALSE, FALSE, 0); 96 gtk_widget_show(progressbar); 97 98 scrolledwin = gtk_scrolled_window_new(NULL, NULL); 99 gtk_widget_show(scrolledwin); 100 gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, 101 TRUE, TRUE, 0); 102 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), 103 GTK_POLICY_AUTOMATIC, 104 GTK_POLICY_AUTOMATIC); 105 106 store = gtk_list_store_new(N_PROGRESS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, 107 G_TYPE_STRING, G_TYPE_POINTER); 108 109 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); 110 g_object_unref(G_OBJECT(store)); 111 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE); 112 gtk_widget_show(treeview); 113 gtk_container_add(GTK_CONTAINER(scrolledwin), treeview); 114 gtk_widget_set_size_request(treeview, -1, 120); 115 116 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); 117 gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); 118 119 renderer = gtk_cell_renderer_pixbuf_new(); 120 g_object_set(renderer, "xalign", 0.5, NULL); 121 column = gtk_tree_view_column_new_with_attributes 122 (NULL, renderer, "pixbuf", PROGRESS_IMAGE, NULL); 123 gtk_tree_view_column_set_alignment(column, 0.5); 124 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); 125 gtk_tree_view_column_set_fixed_width(column, 20); 126 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); 127 128 renderer = gtk_cell_renderer_text_new(); 129 column = gtk_tree_view_column_new_with_attributes 130 (_("Account"), renderer, "text", PROGRESS_ACCOUNT, NULL); 131 gtk_tree_view_column_set_resizable(column, TRUE); 132 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); 133 gtk_tree_view_column_set_fixed_width(column, 160); 134 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); 135 136 renderer = gtk_cell_renderer_text_new(); 137 column = gtk_tree_view_column_new_with_attributes 138 (_("Status"), renderer, "text", PROGRESS_STATE, NULL); 139 gtk_tree_view_column_set_resizable(column, TRUE); 140 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); 141 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); 142 143 /* the WM close and hide buttons are handled internally and not published to caller */ 144 g_signal_connect(G_OBJECT(dialog), "delete_event", 145 G_CALLBACK(progress_dialog_delete_event_btn_cb), NULL); 146 g_signal_connect(G_OBJECT(hide_btn), "clicked", 147 G_CALLBACK(progress_dialog_hide_btn_cb), dialog); 148 149 progress->window = dialog; 150 progress->label = label; 151 progress->showlog_btn = showlog_btn; 152 progress->cancel_btn = cancel_btn; 153 progress->progressbar = progressbar; 154 progress->treeview = treeview; 155 progress->store = store; 156 157 return progress; 158 } 159 160 void progress_dialog_set_label(ProgressDialog *progress, gchar *str) 161 { 162 gtk_label_set_text(GTK_LABEL(progress->label), str); 163 } 164 165 void progress_dialog_get_fraction(ProgressDialog *progress) 166 { 167 gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progress->progressbar)); 168 } 169 170 void progress_dialog_set_fraction(ProgressDialog *progress, 171 gfloat percentage) 172 { 173 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->progressbar), 174 percentage); 175 } 176 177 void progress_dialog_destroy(ProgressDialog *progress) 178 { 179 if (progress) { 180 gtk_widget_destroy(progress->window); 181 g_free(progress); 182 } 183 } 184 185 /*! 186 *\return gint Row where status was set 187 */ 188 gint progress_dialog_list_set_status(ProgressDialog *progress, 189 gint row, 190 const gchar *status) 191 { 192 return progress_dialog_insert_account(progress, row, NULL, 193 status, NULL); 194 } 195 196 /*! 197 *\return gint Row where data were set 198 */ 199 gint progress_dialog_list_set(ProgressDialog *progress, 200 gint row, 201 GdkPixbuf *image, 202 const gchar *account_name, 203 const gchar *status) 204 { 205 return progress_dialog_insert_account(progress, row, account_name, 206 status, image); 207 } 208 209 void progress_dialog_scroll_to_row(ProgressDialog *progress, gint row) 210 { 211 GtkTreeModel *model = GTK_TREE_MODEL(progress->store); 212 GtkTreeIter iter; 213 GtkTreePath *path; 214 215 if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) 216 return; 217 218 path = gtk_tree_model_get_path(model, &iter); 219 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(progress->treeview), 220 path, NULL, FALSE, 0.0, 0.0); 221 gtk_tree_path_free(path); 222 } 223 224 static gint progress_dialog_insert_account(ProgressDialog *progress, 225 gint row, 226 const gchar *account, 227 const gchar *status, 228 GdkPixbuf *image) 229 { 230 GtkTreeIter iter; 231 GtkListStore *store = progress->store; 232 gint result = -1; 233 234 if (account == NULL && status == NULL && image == NULL) 235 return -1; 236 237 /* see if row exists, if not append */ 238 if (row < 0 || !gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), 239 &iter, NULL, row)) { 240 result = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), 241 NULL); 242 gtk_list_store_append(store, &iter); 243 } else 244 result = row; 245 246 /* 247 * XXX: uhm, when does the iter invalidate? sure not while 248 * just setting a row's column i hope? 249 */ 250 251 if (account) 252 gtk_list_store_set(store, &iter, 253 PROGRESS_ACCOUNT, account, 254 -1); 255 if (status) 256 gtk_list_store_set(store, &iter, 257 PROGRESS_STATE, status, 258 -1); 259 if (image) 260 gtk_list_store_set(store, &iter, 261 PROGRESS_IMAGE, image, 262 -1); 263 264 return result; 265 } 266 267 static void progress_dialog_hide_btn_cb(GtkWidget *widget, gpointer data) 268 { 269 gtk_widget_hide(GTK_WIDGET(data)); 270 } 271 272 static void progress_dialog_delete_event_btn_cb(GtkWidget *widget, gpointer data) 273 { 274 gtk_widget_hide(widget); 275 }