remove all gtk3 conditionals
[claws.git] / src / gtk / foldersort.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2004-2018 the Claws Mail Team
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
20 #include "defs.h"
21
22 #include <glib.h>
23 #include <glib/gi18n.h>
24 #include <gdk/gdkkeysyms.h>
25
26 #include "foldersort.h"
27 #include "inc.h"
28 #include "utils.h"
29
30 enum {
31         FOLDERSORT_COL_NAME,
32         FOLDERSORT_COL_PTR,
33         N_FOLDERSORT_COLS
34 };
35
36 typedef struct _FolderSortDialog FolderSortDialog;
37
38 struct _FolderSortDialog
39 {
40         GtkWidget *window;
41         GtkWidget *moveup_btn;
42         GtkWidget *movedown_btn;
43         GtkWidget *folderlist;
44         gint rows;
45 };
46
47 static void destroy_dialog(FolderSortDialog *dialog)
48 {
49         inc_unlock();
50         gtk_widget_destroy(dialog->window);
51
52         g_free(dialog);
53 }
54
55 static void ok_clicked(GtkWidget *widget, FolderSortDialog *dialog)
56 {
57         Folder *folder;
58         GtkTreeModel *model;
59         GtkTreeIter iter;
60         int i;
61
62         model = gtk_tree_view_get_model(GTK_TREE_VIEW(dialog->folderlist));
63
64         for (i = 0; i < dialog->rows; i++) {
65                 if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, i))
66                         continue;
67
68                 gtk_tree_model_get(model, &iter, FOLDERSORT_COL_PTR, &folder, -1);
69
70                 folder_set_sort(folder, dialog->rows - i);
71         }
72
73         destroy_dialog(dialog);
74 }
75
76 static void cancel_clicked(GtkWidget *widget, FolderSortDialog *dialog)
77 {
78         destroy_dialog(dialog);
79 }
80
81 static void set_selected(FolderSortDialog *dialog)
82 {
83         GtkTreeSelection *sel;
84         GtkTreeModel *model;
85         GtkTreeIter iter;
86         GtkTreePath *path;
87         gint *indices;
88         gint selected;
89
90         /* Get row number of the selected row */
91         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->folderlist));
92         if (!gtk_tree_selection_get_selected(sel, &model, &iter))
93                 return;
94         path = gtk_tree_model_get_path(model, &iter);
95         indices = gtk_tree_path_get_indices(path);
96         selected = indices[0];
97         gtk_tree_path_free(path);
98
99         if (selected >= 0) {
100                 gtk_widget_set_sensitive(dialog->moveup_btn, selected > 0);
101                 gtk_widget_set_sensitive(dialog->movedown_btn, selected < (dialog->rows - 1));
102         } else {
103                 gtk_widget_set_sensitive(dialog->moveup_btn, FALSE);
104                 gtk_widget_set_sensitive(dialog->movedown_btn, FALSE);
105         }
106 }
107
108 static void moveup_clicked(GtkWidget *widget, FolderSortDialog *dialog)
109 {
110         GtkTreeSelection *sel;
111         GtkTreeModel *model;
112         GtkTreeIter iter, previter;
113         GtkTreePath *path;
114
115         /* Get currently selected iter */
116         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->folderlist));
117         if (!gtk_tree_selection_get_selected(sel, &model, &iter))
118                 return;
119
120         /* Now get the iter above it, if any */
121         /* GTK+2 does not have gtk_tree_model_iter_previous(), so
122          * we have to get through GtkPath */
123         path = gtk_tree_model_get_path(model, &iter);
124         if (!gtk_tree_path_prev(path)) {
125                 /* No previous path, are we already on top? */
126                 gtk_tree_path_free(path);
127                 return;
128         }
129
130         if (!gtk_tree_model_get_iter(model, &previter, path)) {
131                 /* Eh? */
132                 gtk_tree_path_free(path);
133                 return;
134         }
135
136         gtk_tree_path_free(path);
137
138         gtk_list_store_move_before(GTK_LIST_STORE(model), &iter, &previter);
139
140         set_selected(dialog);
141 }
142
143 static void movedown_clicked(GtkWidget *widget, FolderSortDialog *dialog)
144 {
145         GtkTreeSelection *sel;
146         GtkTreeModel *model;
147         GtkTreeIter iter, nextiter;
148
149         /* Get currently selected iter */
150         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->folderlist));
151         if (!gtk_tree_selection_get_selected(sel, &model, &iter))
152                 return;
153
154         /* Now get the iter above it, if any */
155         nextiter = iter;
156         if (!gtk_tree_model_iter_next(model, &nextiter)) {
157                 /* No next iter, are we already on the bottom? */
158                 return;
159         }
160
161         gtk_list_store_move_after(GTK_LIST_STORE(model), &iter, &nextiter);
162
163         set_selected(dialog);
164 }
165
166 static void folderlist_cursor_changed_cb(GtkTreeView *view, gpointer user_data)
167 {
168         FolderSortDialog *dialog = (FolderSortDialog *)user_data;
169         set_selected(dialog);
170 }
171
172 static void folderlist_row_inserted_cb(GtkTreeModel *model,
173                 GtkTreePath *path, GtkTreeIter *iter,
174                 gpointer user_data)
175 {
176         FolderSortDialog *dialog = (FolderSortDialog *)user_data;
177         GtkTreeSelection *sel;
178
179         /* The only time "row-inserted" signal should be fired is when
180          * a row is reordered using drag&drop. So we want to select
181          * the recently moved row, and call set_selected(), to update
182          * the up/down button sensitivity. */
183         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->folderlist));
184         gtk_tree_selection_select_iter(sel, iter);
185
186         set_selected(dialog);
187 }
188
189 static gint delete_event(GtkWidget *widget, GdkEventAny *event, FolderSortDialog *dialog)
190 {
191         destroy_dialog(dialog);
192         return TRUE;
193 }
194
195 static gboolean key_pressed(GtkWidget *widget, GdkEventKey *event, FolderSortDialog *dialog)
196 {
197         if (event && event->keyval == GDK_KEY_Escape)
198                 destroy_dialog(dialog);
199         return FALSE;
200 }
201
202 void foldersort_open()
203 {
204         FolderSortDialog *dialog = g_new0(FolderSortDialog, 1);
205         GList *flist;
206
207         GtkWidget *window;
208         GtkWidget *vbox;
209         GtkWidget *vbox1;
210         GtkWidget *label1;
211         GtkWidget *hbox;
212         GtkWidget *hbox2;
213         GtkWidget *ok_btn;
214         GtkWidget *cancel_btn;
215         GtkWidget *confirm_area;
216         GtkWidget *moveup_btn;
217         GtkWidget *movedown_btn;
218         GtkWidget *btn_vbox;
219         GtkWidget *scrolledwindow1;
220         GtkWidget *folderlist;
221         GtkTreeViewColumn *col;
222         GtkListStore *store;
223         GtkCellRenderer *rdr;
224         GtkTreeSelection *selector;
225         GtkTreeIter iter;
226
227         window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "foldersort");
228         g_object_set_data(G_OBJECT(window), "window", window);
229         gtk_container_set_border_width(GTK_CONTAINER(window), 8);
230         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
231         gtk_window_set_title(GTK_WINDOW(window), _("Set mailbox order"));
232         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
233         gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
234         g_signal_connect(G_OBJECT(window), "delete_event",
235                          G_CALLBACK(delete_event), dialog);
236         g_signal_connect(G_OBJECT(window), "key_press_event",
237                          G_CALLBACK(key_pressed), dialog);
238
239         vbox = gtk_vbox_new(FALSE, 6);
240         gtk_widget_show(vbox);
241         gtk_container_add(GTK_CONTAINER(window), vbox);
242
243         gtkut_stock_button_set_create(&confirm_area, &cancel_btn, GTK_STOCK_CANCEL,
244                                       &ok_btn, GTK_STOCK_OK,
245                                       NULL, NULL);
246         gtk_widget_show(confirm_area);
247         gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
248         gtk_widget_grab_focus(ok_btn);
249
250         g_signal_connect(G_OBJECT(ok_btn), "clicked",
251                          G_CALLBACK(ok_clicked), dialog);
252         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
253                          G_CALLBACK(cancel_clicked), dialog);
254
255         vbox1 = gtk_vbox_new(FALSE, 8);
256         gtk_widget_show(vbox1);
257         gtk_box_pack_start(GTK_BOX(vbox), vbox1, TRUE, TRUE, 0);
258         gtk_container_set_border_width(GTK_CONTAINER(vbox1), 2);
259
260         hbox = gtk_hbox_new(FALSE, 8);
261         gtk_widget_show(hbox);
262         gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
263
264         label1 = gtk_label_new(_
265                 ("Move mailboxes up or down to change the sort order "
266                  "in the Folder list."));
267         gtk_widget_show(label1);
268         gtk_widget_set_size_request(GTK_WIDGET(label1), 392, -1);
269         gtk_label_set_line_wrap(GTK_LABEL(label1), TRUE);
270         gtk_box_pack_start(GTK_BOX(hbox), label1, FALSE, FALSE, 0);
271
272         hbox2 = gtk_hbox_new(FALSE, 8);
273         gtk_widget_show(hbox2);
274         gtk_box_pack_start(GTK_BOX(vbox1), hbox2, TRUE, TRUE, 0);
275
276         scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL);
277         gtk_widget_show(scrolledwindow1);
278         gtk_widget_set_size_request(scrolledwindow1, -1, 150);
279         gtk_box_pack_start(GTK_BOX(hbox2), scrolledwindow1,
280                            TRUE, TRUE, 0);
281         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolledwindow1),
282                                        GTK_POLICY_AUTOMATIC,
283                                        GTK_POLICY_AUTOMATIC);
284
285         /* Create the list store */
286         store = gtk_list_store_new(N_FOLDERSORT_COLS,
287                         G_TYPE_STRING, G_TYPE_POINTER, -1);
288
289         /* Create the view widget */
290         folderlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
291         g_object_unref(store);
292         gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(folderlist), TRUE);
293         gtk_tree_view_set_reorderable(GTK_TREE_VIEW(folderlist), TRUE);
294         selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(folderlist));
295         gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
296
297         /* The only column for the view widget */
298         rdr = gtk_cell_renderer_text_new();
299         col = gtk_tree_view_column_new_with_attributes(_("Mailboxes"),
300                         rdr, "markup", FOLDERSORT_COL_NAME, NULL);
301         gtk_tree_view_column_set_min_width(col, 80);
302         gtk_tree_view_append_column(GTK_TREE_VIEW(folderlist), col);
303
304         gtk_widget_show(folderlist);
305         gtk_container_add(GTK_CONTAINER(scrolledwindow1), folderlist);
306
307         btn_vbox = gtk_vbox_new(FALSE, 8);
308         gtk_widget_show(btn_vbox);
309         gtk_box_pack_start(GTK_BOX(hbox2), btn_vbox, FALSE, FALSE, 0);
310
311         moveup_btn = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
312         gtk_widget_show(moveup_btn);
313         gtk_box_pack_start(GTK_BOX(btn_vbox), moveup_btn, FALSE, FALSE, 0);
314
315         movedown_btn =  gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
316         gtk_widget_show(movedown_btn);
317         gtk_box_pack_start(GTK_BOX(btn_vbox), movedown_btn, FALSE, FALSE, 0);
318
319         dialog->window = window;
320         dialog->moveup_btn = moveup_btn;
321         dialog->movedown_btn = movedown_btn;
322         dialog->folderlist = folderlist;
323
324         gtk_widget_show(window);
325         gtk_widget_set_sensitive(moveup_btn, FALSE);
326         gtk_widget_set_sensitive(movedown_btn, FALSE);
327
328         /* Connect up the signals for the up/down buttons */
329         g_signal_connect(G_OBJECT(moveup_btn), "clicked",
330                          G_CALLBACK(moveup_clicked), dialog);
331         g_signal_connect(G_OBJECT(movedown_btn), "clicked",
332                          G_CALLBACK(movedown_clicked), dialog);
333
334 //      g_signal_connect(G_OBJECT(folderlist), "select-row",
335 //                       G_CALLBACK(row_selected), dialog);
336 //      g_signal_connect(G_OBJECT(folderlist), "unselect-row",
337 //                       G_CALLBACK(row_unselected), dialog);
338 //      g_signal_connect(G_OBJECT(folderlist), "row-move",
339 //                       G_CALLBACK(row_moved), dialog);
340
341         /* Populate the list with mailboxes */
342         dialog->rows = 0;
343         for (flist = folder_get_list(); flist != NULL; flist = g_list_next(flist)) {
344                 Folder *folder = flist->data;
345
346                 gtk_list_store_append(store, &iter);
347                 gtk_list_store_set(store, &iter,
348                                 FOLDERSORT_COL_NAME, folder->name,
349                                 FOLDERSORT_COL_PTR, folder,
350                                 -1);
351                 dialog->rows++;
352         }
353
354         /* Connect up the signals for the folderlist */
355         g_signal_connect(G_OBJECT(folderlist), "cursor-changed",
356                         G_CALLBACK(folderlist_cursor_changed_cb), dialog);
357         g_signal_connect(G_OBJECT(store), "row-inserted",
358                         G_CALLBACK(folderlist_row_inserted_cb), dialog);
359
360         /* Select the first row and adjust the sensitivity of
361          * the up/down buttons */
362         if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) {
363                 gtk_tree_selection_select_iter(selector, &iter);
364                 set_selected(dialog);
365         }
366
367         inc_lock();
368 }