1 /*  HomeBank -- Free, easy, personal accounting for everyone.
2  *  Copyright (C) 1995-2021 Maxime DOYEN
3  *
4  *  This file is part of HomeBank.
5  *
6  *  HomeBank is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  HomeBank is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 #include "homebank.h"
22 
23 #include "ui-archive.h"
24 #include "ui-account.h"
25 #include "ui-category.h"
26 #include "ui-payee.h"
27 #include "ui-split.h"
28 #include "ui-tag.h"
29 
30 #include "gtk-dateentry.h"
31 
32 /****************************************************************************/
33 /* Debug macros                                                             */
34 /****************************************************************************/
35 #define MYDEBUG 0
36 
37 #if MYDEBUG
38 #define DB(x) (x);
39 #else
40 #define DB(x);
41 #endif
42 
43 /* our global datas */
44 extern struct HomeBank *GLOBALS;
45 extern struct Preferences *PREFS;
46 
47 
48 extern gchar *RA_ARC_TYPE[];
49 extern gchar *CYA_ARC_UNIT[];
50 extern gchar *RA_ARC_WEEKEND[];
51 
52 extern HbKvData CYA_TXN_STATUS[];
53 
54 extern gchar *CYA_TXN_TYPE[];
55 
56 
57 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
58 
59 
60 
61 
list_tpl_select_by_pointer(GtkTreeView * treeview,gpointer user_data)62 static void list_tpl_select_by_pointer(GtkTreeView *treeview, gpointer user_data)
63 {
64 GtkTreeModel *model;
65 GtkTreeIter	iter;
66 GtkTreeSelection *selection;
67 gboolean valid;
68 Archive *arc = user_data;
69 
70 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
71 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
72 
73 	valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
74 	while (valid)
75 	{
76 	Archive *tmp_arc;
77 
78 		gtk_tree_model_get (model, &iter, LST_DEFARC_DATAS, &tmp_arc, -1);
79 		if( arc == tmp_arc )
80 		{
81 			gtk_tree_selection_select_iter (selection, &iter);
82 			break;
83 		}
84 
85 		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
86 	}
87 }
88 
89 
90 /*
91 **
92 ** The function should return:
93 ** a negative integer if the first value comes before the second,
94 ** 0 if they are equal,
95 ** or a positive integer if the first value comes after the second.
96 */
list_tpl_compare_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)97 static gint list_tpl_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
98 {
99 gint sortcol = GPOINTER_TO_INT(userdata);
100 Archive *item1, *item2;
101 gdouble tmpval;
102 gint retval = 0;
103 
104 	gtk_tree_model_get(model, a, LST_DEFARC_DATAS, &item1, -1);
105 	gtk_tree_model_get(model, b, LST_DEFARC_DATAS, &item2, -1);
106 
107     switch (sortcol)
108     {
109 		case LST_DEFARC_SORT_DATE:
110 			retval = item1->nextdate - item2->nextdate;
111 			break;
112 		case LST_DEFARC_SORT_MEMO:
113 			retval = (item1->flags & GF_INCOME) - (item2->flags & GF_INCOME);
114 			if(!retval)
115 			{
116 				retval = hb_string_utf8_compare(item1->memo, item2->memo);
117 			}
118 			break;
119 		case LST_DEFARC_SORT_PAYEE:
120 			{
121 			Payee *p1, *p2;
122 
123 				p1 = da_pay_get(item1->kpay);
124 				p2 = da_pay_get(item2->kpay);
125 				if( p1 != NULL && p2 != NULL )
126 				{
127 					retval = hb_string_utf8_compare(p1->name, p2->name);
128 				}
129 			}
130 			break;
131 		case LST_DEFARC_SORT_AMOUNT:
132 			tmpval = item1->amount - item2->amount;
133 			retval = tmpval > 0 ? 1 : -1;
134 			break;
135 
136 
137 		default:
138 			g_return_val_if_reached(0);
139 	}
140     return retval;
141 }
142 
143 
144 static void
list_tpl_auto_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)145 list_tpl_auto_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
146 {
147 Archive *item;
148 gchar *info, *iconname;
149 
150 	// get the transaction
151 	gtk_tree_model_get(model, iter, LST_DEFARC_DATAS, &item, -1);
152 
153 	switch(GPOINTER_TO_INT(user_data))
154 	{
155 		case 1:
156 			iconname = ( item->flags & OF_AUTO ) ? ICONNAME_HB_OPE_AUTO : NULL;
157 			g_object_set(renderer, "icon-name", iconname, NULL);
158 			break;
159 		case 2:
160 			info = NULL;
161 			//TODO: this is crappy/unsafe to call CYA_ARC_UNIT here
162 			//#1898294 not translated
163 			if( ( item->flags & OF_AUTO ) )
164 			   info = g_strdup_printf("%d %s", item->every, _(CYA_ARC_UNIT[item->unit]));
165 
166 			g_object_set(renderer, "text", info, NULL);
167 
168 			g_free(info);
169 			break;
170 	}
171 }
172 
173 
174 static void
list_tpl_date_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)175 list_tpl_date_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
176 {
177 Archive *arc;
178 gchar buffer[256];
179 GDate *date;
180 
181 	gtk_tree_model_get(model, iter,
182 		LST_DEFARC_DATAS, &arc,
183 		-1);
184 
185 	if(arc && (arc->flags & OF_AUTO) )
186 	{
187 		date = g_date_new_julian (arc->nextdate);
188 		g_date_strftime (buffer, 256-1, PREFS->date_format, date);
189 		g_date_free(date);
190 
191 		//g_snprintf(buf, sizeof(buf), "%d", ope->ope_Date);
192 
193 		g_object_set(renderer, "text", buffer, NULL);
194 
195 	}
196 	else
197 		g_object_set(renderer, "text", NULL, NULL);
198 
199 }
200 
201 
202 /*
203 ** draw some text from the stored data structure
204 */
205 static void
list_tpl_cell_data_function_memo(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)206 list_tpl_cell_data_function_memo (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
207 {
208 Archive *item;
209 
210 	gtk_tree_model_get(model, iter, LST_DEFARC_DATAS, &item, -1);
211 	g_object_set(renderer, "text", item->memo, NULL);
212 }
213 
214 
215 
216 static void
list_tpl_cell_data_function_payee(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)217 list_tpl_cell_data_function_payee (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
218 {
219 Archive *arc;
220 Payee *pay;
221 
222 	gtk_tree_model_get(model, iter,
223 		LST_DEFARC_DATAS, &arc,
224 		-1);
225 
226 	if(arc)
227 	{
228 
229 		pay = da_pay_get(arc->kpay);
230 
231 		if(pay != NULL)
232 			g_object_set(renderer, "text", pay->name, NULL);
233 	}
234 	else
235 		g_object_set(renderer, "text", NULL, NULL);
236 
237 }
238 
239 
240 static void
list_tpl_amount_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)241 list_tpl_amount_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
242 {
243 Archive *arc;
244 gdouble amount;
245 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
246 Account *acc;
247 gchar *color;
248 gint weight;
249 
250 	gtk_tree_model_get(model, iter,
251 		LST_DEFARC_DATAS, &arc,
252 		-1);
253 
254 	amount = arc->amount;
255 
256 	if( amount != 0.0)
257 	{
258 	acc = da_acc_get(arc->kacc);
259 
260 		if( acc != NULL )
261 			hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, amount, acc->kcur, GLOBALS->minor);
262 		else
263 			hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, amount, GLOBALS->kcur, GLOBALS->minor);
264 
265 		color = get_normal_color_amount(amount);
266 
267 		weight = arc == NULL ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
268 
269 		g_object_set(renderer,
270 			"weight", weight,
271 			"foreground", color,
272 			"text", buf,
273 			NULL);
274 	}
275 	else
276 	{
277 		g_object_set(renderer, "text", NULL, NULL);
278 	}
279 
280 }
281 
282 
283 static void
list_tpl_cell_data_function_account(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)284 list_tpl_cell_data_function_account (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
285 {
286 Archive *arc;
287 Account *acc;
288 
289 	gtk_tree_model_get(model, iter,
290 		LST_DEFARC_DATAS, &arc,
291 		-1);
292 
293 	acc = da_acc_get(arc->kacc);
294 	if(acc != NULL)
295 		g_object_set(renderer, "text", acc->name, NULL);
296 	else
297 		g_object_set(renderer, "text", NULL, NULL);
298 }
299 
300 
301 #if MYDEBUG == 1
302 static void
list_tpl_cell_data_function_debugkey(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)303 list_tpl_cell_data_function_debugkey (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
304 {
305 Archive *item;
306 gchar *string;
307 
308 	gtk_tree_model_get(model, iter, LST_DEFARC_DATAS, &item, -1);
309 	string = g_strdup_printf ("[%d]", item->key );
310 	g_object_set(renderer, "text", string, NULL);
311 	g_free(string);
312 }
313 #endif
314 
315 
316 static GtkTreeViewColumn *
list_tpl_column_text_create(gchar * title,gint sortcolumnid,GtkTreeCellDataFunc func,gpointer user_data)317 list_tpl_column_text_create(gchar *title, gint sortcolumnid, GtkTreeCellDataFunc func, gpointer user_data)
318 {
319 GtkTreeViewColumn  *column;
320 GtkCellRenderer    *renderer;
321 
322 	renderer = gtk_cell_renderer_text_new ();
323 	g_object_set(renderer,
324 		"ellipsize", PANGO_ELLIPSIZE_END,
325 	    "ellipsize-set", TRUE,
326 		//taken from nemo, not exactly a resize to content, but good compromise
327 	    "width-chars", 40,
328 	    NULL);
329 
330 	column = gtk_tree_view_column_new_with_attributes(title, renderer, NULL);
331 
332 	gtk_tree_view_column_set_alignment (column, 0.5);
333 	gtk_tree_view_column_set_resizable(column, TRUE);
334 
335 	gtk_tree_view_column_set_sort_column_id (column, sortcolumnid);
336 	//gtk_tree_view_column_set_reorderable(column, TRUE);
337 	gtk_tree_view_column_set_min_width (column, HB_MINWIDTH_COLUMN);
338 	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
339 	//gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
340 	//gtk_tree_view_column_set_expand (column, TRUE);
341 	gtk_tree_view_column_set_cell_data_func(column, renderer, func, user_data, NULL);
342 
343 	return column;
344 }
345 
346 
347 
348 
349 
350 
351 //TODO: we could maybe merge this list with the scheduled list
352 
list_tpl_new(void)353 static GtkWidget *list_tpl_new(void)
354 {
355 GtkListStore *store;
356 GtkWidget *view;
357 GtkCellRenderer    *renderer;
358 GtkTreeViewColumn  *column;
359 
360 	//store
361 	store = gtk_list_store_new (
362 		NUM_LST_DEFARC,
363 		G_TYPE_POINTER,
364 		G_TYPE_UINT,
365 		G_TYPE_BOOLEAN
366 		);
367 
368 	//treeview
369 	view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
370 	g_object_unref(store);
371 
372 	gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
373 
374 
375 	#if MYDEBUG == 1
376 	column = list_tpl_column_text_create(NULL, 0, list_tpl_cell_data_function_debugkey, NULL);
377 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
378 	#endif
379 
380 	/* column: Scheduled icon */
381 	column = gtk_tree_view_column_new();
382 	renderer = gtk_cell_renderer_pixbuf_new ();
383 	//gtk_cell_renderer_set_fixed_size(renderer, GLOBALS->lst_pixbuf_maxwidth, -1);
384 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
385 	gtk_tree_view_column_set_cell_data_func(column, renderer, list_tpl_auto_cell_data_function, GINT_TO_POINTER(1), NULL);
386 
387 	renderer = gtk_cell_renderer_text_new ();
388 	g_object_set(renderer,
389 		"ellipsize", PANGO_ELLIPSIZE_END,
390 	    "ellipsize-set", TRUE,
391 		//taken from nemo, not exactly a resize to content, but good compromise
392 	    "width-chars", 40,
393 	    NULL);
394 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
395 	gtk_tree_view_column_set_cell_data_func(column, renderer, list_tpl_auto_cell_data_function, GINT_TO_POINTER(2), NULL);
396 
397 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
398 
399 	/* column: Next on */
400 	renderer = gtk_cell_renderer_text_new ();
401 	g_object_set(renderer, "xalign", 1.0, NULL);
402 	column = gtk_tree_view_column_new();
403 	gtk_tree_view_column_set_title(column, _("Next date"));
404 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
405 	gtk_tree_view_column_set_cell_data_func(column, renderer, list_tpl_date_cell_data_function, NULL, NULL);
406 	gtk_tree_view_column_set_sort_column_id (column, LST_DEFARC_SORT_DATE);
407 	gtk_tree_view_column_set_alignment (column, 0.5);
408 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
409 
410 	/* column: Payee */
411 	column = list_tpl_column_text_create(_("Payee"), LST_DEFARC_SORT_PAYEE, list_tpl_cell_data_function_payee, NULL);
412 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
413 
414 	/* column: Memo */
415 	column = list_tpl_column_text_create(_("Memo"), LST_DEFARC_SORT_MEMO, list_tpl_cell_data_function_memo, NULL);
416 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
417 
418 	/* column : amount */
419 	column = gtk_tree_view_column_new();
420 	gtk_tree_view_column_set_title(column, _("Amount"));
421 	renderer = gtk_cell_renderer_text_new ();
422 	g_object_set(renderer, "xalign", 1.0, NULL);
423 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
424 	gtk_tree_view_column_set_cell_data_func(column, renderer, list_tpl_amount_cell_data_function, NULL, NULL);
425 	gtk_tree_view_column_set_sort_column_id (column, LST_DEFARC_SORT_AMOUNT);
426 	gtk_tree_view_column_set_alignment (column, 0.5);
427 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
428 
429 	/* column : Account */
430 	column = list_tpl_column_text_create(_("Account"), LST_DEFARC_SORT_ACCOUNT, list_tpl_cell_data_function_account, NULL);
431 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
432 
433 	//sortable
434 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_DATE, list_tpl_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_DATE), NULL);
435 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_MEMO, list_tpl_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_MEMO), NULL);
436 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_PAYEE, list_tpl_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_PAYEE), NULL);
437 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_AMOUNT, list_tpl_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_AMOUNT), NULL);
438 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_ACCOUNT, list_tpl_compare_func, GINT_TO_POINTER(LST_DEFARC_SORT_ACCOUNT), NULL);
439 
440 	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), LST_DEFARC_SORT_MEMO, GTK_SORT_ASCENDING);
441 
442 	//gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(view), FALSE);
443 	//gtk_tree_view_set_reorderable (GTK_TREE_VIEW(view), TRUE);
444 
445 	return(view);
446 }
447 
448 
449 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
450 
451 
452 static void
ui_arc_manage_update(GtkWidget * widget,gpointer user_data)453 ui_arc_manage_update(GtkWidget *widget, gpointer user_data)
454 {
455 struct ui_arc_manage_data *data;
456 GtkTreeModel *model;
457 GtkTreeIter iter;
458 Archive *arc;
459 gboolean selected, sensitive;
460 
461 	DB( g_print("\n[ui_scheduled] update\n") );
462 
463 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
464 
465 	selected = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter);
466 
467 	sensitive = (selected == TRUE) ? TRUE : FALSE;
468 	gtk_widget_set_sensitive(data->BT_edit, sensitive);
469 	gtk_widget_set_sensitive(data->BT_rem, sensitive);
470 	gtk_widget_set_sensitive(data->MB_schedule, sensitive);
471 	gtk_widget_set_sensitive(data->CM_auto, sensitive);
472 
473 	sensitive = FALSE;
474 	if(selected)
475 	{
476 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &arc, -1);
477 
478 		if( arc->flags & OF_AUTO )
479 			sensitive = TRUE;
480 	}
481 
482 	gtk_widget_set_sensitive(data->LB_next, sensitive);
483 	gtk_widget_set_sensitive(data->PO_next, sensitive);
484 
485 	gtk_widget_set_sensitive(data->LB_every, sensitive);
486 	gtk_widget_set_sensitive(data->NB_every, sensitive);
487 
488 	gtk_widget_set_sensitive(data->LB_weekend, sensitive);
489 	gtk_widget_set_sensitive(data->CY_weekend, sensitive);
490 
491 	gtk_widget_set_sensitive(data->EX_options, sensitive);
492 
493 	gtk_widget_set_sensitive(data->CY_unit, sensitive);
494 	gtk_widget_set_sensitive(data->CM_limit, sensitive);
495 
496 	gtk_widget_set_sensitive(data->LB_posts, sensitive);
497 
498 
499 	sensitive = (sensitive == TRUE) ? gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_limit)) : sensitive;
500 	gtk_widget_set_sensitive(data->NB_limit, sensitive);
501 
502 	if(selected)
503 	{
504 	GtkTreePath *path;
505 
506 		/* redraw the row to display/hide the icon */
507 		path = gtk_tree_model_get_path(model, &iter);
508 		gtk_tree_model_row_changed(model, path, &iter);
509 		gtk_tree_path_free (path);
510 
511 		//	gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_arc));
512 		//gtk_widget_queue_draw (GTK_WIDGET(data->LV_arc));
513 	}
514 }
515 
516 
517 static void
ui_arc_manage_cd_schedule_changed(GtkWidget * widget,gpointer user_data)518 ui_arc_manage_cd_schedule_changed(GtkWidget *widget, gpointer user_data)
519 {
520 struct ui_arc_manage_data *data;
521 Archive *arcitem;
522 GtkTreeModel		 *model;
523 GtkTreeIter			 iter;
524 
525 gboolean selected, sensitive;
526 
527 	DB( g_print("\n[ui_scheduled] scheduled\n") );
528 
529 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
530 
531 	sensitive = FALSE;
532 
533 	selected = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter);
534 	if(selected)
535 	{
536 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &arcitem, -1);
537 
538 		arcitem->flags &= ~(OF_AUTO);
539 		sensitive = gtk_switch_get_active(GTK_SWITCH(data->CM_auto)) ? TRUE : FALSE;
540 		if(sensitive)
541 			arcitem->flags |= OF_AUTO;
542 	}
543 
544 	ui_arc_manage_update(widget, user_data);
545 
546 }
547 
548 
549 
550 
551 
552 static void
ui_arc_manage_populate_listview(struct ui_arc_manage_data * data)553 ui_arc_manage_populate_listview(struct ui_arc_manage_data *data)
554 {
555 GtkTreeModel *model;
556 GtkTreeIter  iter;
557 GList *list;
558 gchar *needle;
559 gboolean hastext;
560 gint i, typsch, typtpl;
561 
562 	DB( g_print("\n[ui_scheduled] populate listview\n") );
563 
564 	typsch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->BT_typsch));
565 	typtpl = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->BT_typtpl));
566 
567 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_arc));
568 	hastext = (gtk_entry_get_text_length (GTK_ENTRY(data->ST_search)) >= 2) ? TRUE : FALSE;
569 	needle = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_search));
570 
571 	DB( g_print(" - typsch=%d / typtpl=%d\n", typsch, typtpl) );
572 
573 	gtk_list_store_clear (GTK_LIST_STORE(model));
574 
575 	i=0;
576 	list = g_list_first(GLOBALS->arc_list);
577 	while (list != NULL)
578 	{
579 	Archive *item = list->data;
580 	gboolean insert = FALSE;
581 
582 		if( (typsch) && (item->flags & OF_AUTO) )
583 			insert = TRUE;
584 
585 		if( (typtpl) && !(item->flags & OF_AUTO) )
586 			insert = TRUE;
587 
588 		if( insert )
589 		{
590 		gboolean qinsert = TRUE;
591 
592 			if(hastext)
593 			{
594 				qinsert = filter_tpl_search_match(needle, item);
595 			}
596 
597 			if( qinsert )
598 			{
599 				gtk_list_store_insert_with_values (GTK_LIST_STORE(model), &iter, -1,
600 					LST_DEFARC_DATAS, item,	//data struct
601 					LST_DEFARC_OLDPOS, i,		//oldpos
602 					-1);
603 			}
604 		}
605 		//DB( g_print(" populate_treeview: %d %08x\n", i, list->data) );
606 
607 		i++; list = g_list_next(list);
608 	}
609 
610 
611 //	gtk_tree_view_expand_all (GTK_TREE_VIEW(data->LV_arc));
612 }
613 
614 
615 static void
ui_arc_manage_cb_add_clicked(GtkWidget * widget,gpointer user_data)616 ui_arc_manage_cb_add_clicked(GtkWidget *widget, gpointer user_data)
617 {
618 struct ui_arc_manage_data *data;
619 GtkTreeModel *model;
620 GtkTreeIter  iter;
621 Archive *item;
622 gint typsch, typtpl;
623 
624 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
625 	DB( g_print("\n[ui_scheduled] add\n") );
626 
627 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_arc));
628 
629 
630 
631 GtkWidget *dialog;
632 Transaction *new_txn = da_transaction_malloc();
633 gboolean result;
634 
635 	dialog = create_deftransaction_window(GTK_WINDOW(data->dialog), TXN_DLG_ACTION_ADD, TXN_DLG_TYPE_TPL, 0);
636 	deftransaction_set_transaction(dialog, new_txn);
637 
638 	result = gtk_dialog_run (GTK_DIALOG (dialog));
639 	if(result == HB_RESPONSE_ADD)
640 	{
641 		deftransaction_get(dialog, NULL);
642 
643 		item = da_archive_malloc();
644 		//item->memo = g_strdup_printf(_("(template %d)"), g_list_length(GLOBALS->arc_list) + 1);
645 
646 		da_archive_init_from_transaction(item, new_txn, FALSE);
647 
648 		typsch = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->BT_typsch));
649 		typtpl = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->BT_typtpl));
650 
651 		if( typsch && !typtpl )
652 			item->flags |= OF_AUTO;
653 
654 		item->every = 1;
655 		item->unit = 2;
656 		item->nextdate = GLOBALS->today;
657 
658 		//GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, item);
659 		da_archive_append_new(item);
660 
661 		DB( g_print(" - kacc: '%d'\n", item->kacc) );
662 
663 
664 		gtk_list_store_append (GTK_LIST_STORE(model), &iter);
665 		gtk_list_store_set (GTK_LIST_STORE(model), &iter,
666 			LST_DEFARC_DATAS, item,
667 			LST_DEFARC_OLDPOS, 0,
668 			-1);
669 
670 		gtk_tree_selection_select_iter (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &iter);
671 
672 		data->change++;
673 	}
674 
675 	deftransaction_dispose(dialog, NULL);
676 	gtk_widget_destroy (dialog);
677 
678 	da_transaction_free(new_txn);
679 
680 }
681 
682 
683 static void
ui_arc_manage_cb_edit_clicked(GtkWidget * widget,gpointer user_data)684 ui_arc_manage_cb_edit_clicked(GtkWidget *widget, gpointer user_data)
685 {
686 struct ui_arc_manage_data *data;
687 GtkTreeModel *model;
688 GtkTreeIter iter;
689 gboolean selected;
690 Archive *arcitem;
691 GtkWidget *dialog;
692 Transaction *new_txn = da_transaction_malloc();
693 gboolean result;
694 
695 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data");
696 
697 	selected = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter);
698 	if(selected)
699 	{
700 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &arcitem, -1);
701 
702 		dialog = create_deftransaction_window(GTK_WINDOW(data->dialog), TXN_DLG_ACTION_EDIT, TXN_DLG_TYPE_TPL, 0);
703 
704 		da_transaction_init_from_template(new_txn, arcitem);
705 		deftransaction_set_transaction(dialog, new_txn);
706 
707 		result = gtk_dialog_run (GTK_DIALOG (dialog));
708 		if(result == GTK_RESPONSE_ACCEPT)
709 		{
710 			deftransaction_get(dialog, NULL);
711 
712 			da_archive_init_from_transaction(arcitem, new_txn, FALSE);
713 
714 			//this redraw the row
715 			gtk_tree_selection_select_iter (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &iter);
716 
717 			data->change++;
718 		}
719 
720 		deftransaction_dispose(dialog, NULL);
721 		gtk_widget_destroy (dialog);
722 
723 		da_transaction_free(new_txn);
724 	}
725 }
726 
727 
728 static void
ui_arc_manage_cb_delete_clicked(GtkWidget * widget,gpointer user_data)729 ui_arc_manage_cb_delete_clicked(GtkWidget *widget, gpointer user_data)
730 {
731 struct ui_arc_manage_data *data;
732 GtkTreeSelection *selection;
733 GtkTreeModel		 *model;
734 GtkTreeIter			 iter;
735 Archive *item;
736 gint result;
737 
738 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
739 	DB( g_print("\n[ui_scheduled] delete (data=%p)\n", data) );
740 
741 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc));
742 	//if true there is a selected node
743 	if (gtk_tree_selection_get_selected(selection, &model, &iter))
744 	{
745 	gchar *title;
746 	gchar *secondtext;
747 
748 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &item, -1);
749 
750 		title = g_strdup_printf (
751 			_("Are you sure you want to permanently delete '%s'?"), item->memo);
752 
753 		secondtext = _("If you delete a scheduled/template, it will be permanently lost.");
754 
755 		result = ui_dialog_msg_confirm_alert(
756 				GTK_WINDOW(data->dialog),
757 				title,
758 				secondtext,
759 				_("_Delete")
760 			);
761 
762 		g_free(title);
763 
764 		if( result == GTK_RESPONSE_OK )
765 		{
766 			gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
767 
768 			GLOBALS->arc_list = g_list_remove(GLOBALS->arc_list, item);
769 
770 			data->change++;
771 
772 		}
773 		//DB( g_print(" delete =%08x (pos=%d)\n", entry, g_list_index(data->tmp_list, entry) ) );
774 	}
775 }
776 
777 
778 static void
ui_arc_manage_set(GtkWidget * widget,gpointer user_data)779 ui_arc_manage_set(GtkWidget *widget, gpointer user_data)
780 {
781 struct ui_arc_manage_data *data;
782 GtkTreeModel *model;
783 GtkTreeIter iter;
784 Archive *item;
785 
786 	DB( g_print("\n[ui_scheduled] set\n") );
787 
788 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
789 
790 	if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter))
791 	{
792 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &item, -1);
793 
794 		gtk_switch_set_active(GTK_SWITCH(data->CM_auto), (item->flags & OF_AUTO) ? 1 : 0);
795 		gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_every), item->every);
796 		gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_unit), item->unit);
797 		gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_next), item->nextdate);
798 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_limit), (item->flags & OF_LIMIT) ? 1 : 0);
799 		DB( g_print("nb_limit = %d %g\n", item->limit, (gdouble)item->limit) );
800 		gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_limit), (gdouble)item->limit);
801 		gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_weekend), item->weekend);
802 	}
803 }
804 
805 
806 static void
ui_arc_manage_getlast(struct ui_arc_manage_data * data)807 ui_arc_manage_getlast(struct ui_arc_manage_data *data)
808 {
809 GtkTreeModel *model;
810 GtkTreeIter iter;
811 Archive *item;
812 gboolean active;
813 
814 	DB( g_print("\n[ui_scheduled] getlast\n") );
815 
816 	if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter))
817 	{
818 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &item, -1);
819 
820 		//#1863484: reset flag to enable remove auto and limit :)
821 		item->flags &= ~(OF_AUTO|OF_LIMIT);
822 
823 		active = gtk_switch_get_active(GTK_SWITCH(data->CM_auto));
824 		if(active == 1) item->flags |= OF_AUTO;
825 
826 		gtk_spin_button_update(GTK_SPIN_BUTTON(data->NB_every));
827 		item->every   = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->NB_every));
828 		item->unit    = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_unit));
829 		item->nextdate	= gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_next));
830 
831 		active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_limit));
832 		if(active == 1) item->flags |= OF_LIMIT;
833 
834 		gtk_spin_button_update(GTK_SPIN_BUTTON(data->NB_limit));
835 		item->limit   = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->NB_limit));
836 
837 		item->weekend = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_weekend));
838 
839 		data->change++;
840 	}
841 }
842 
843 
844 static void
ui_arc_manage_cb_popover_closed(GtkWidget * popover,gpointer user_data)845 ui_arc_manage_cb_popover_closed(GtkWidget *popover, gpointer user_data)
846 {
847 struct ui_arc_manage_data *data;
848 GtkTreeModel		 *model;
849 GtkTreeIter			 iter;
850 GtkTreePath			*path;
851 gboolean selected;
852 
853 	DB( g_print("\n[ui_scheduled] cb popover closed\n") );
854 
855 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(popover, GTK_TYPE_WINDOW)), "inst_data");
856 
857 	/* redraw the row to display/hide the icon */
858 	selected = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter);
859 	if(selected)
860 	{
861 		ui_arc_manage_getlast(data);
862 
863 		path = gtk_tree_model_get_path(model, &iter);
864 		#if MYDEBUG == 1
865 			gchar *spath = gtk_tree_path_to_string(path);
866 			g_print(" selected '%s'\n", spath);
867 			g_free(spath);
868 		#endif
869 		gtk_tree_model_row_changed(model, path, &iter);
870 		gtk_tree_path_free (path);
871 	}
872 }
873 
874 
875 static void
ui_arc_manage_cb_selection_changed(GtkTreeSelection * treeselection,gpointer user_data)876 ui_arc_manage_cb_selection_changed(GtkTreeSelection *treeselection, gpointer user_data)
877 {
878 struct ui_arc_manage_data *data;
879 GtkWidget *treeview;
880 GtkTreeModel		 *model;
881 GtkTreeIter			 iter;
882 gboolean selected;
883 Archive *arcitem;
884 
885 	DB( g_print("\n[ui_scheduled] selection\n") );
886 
887 	treeview = (GtkWidget *)gtk_tree_selection_get_tree_view (treeselection);
888 
889 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(treeview, GTK_TYPE_WINDOW)), "inst_data");
890 
891 	selected = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), &model, &iter);
892 	if(selected)
893 	{
894 		gtk_tree_model_get(model, &iter, LST_DEFARC_DATAS, &arcitem, -1);
895 
896 		ui_arc_manage_set(treeview, NULL);
897 	}
898 
899 	ui_arc_manage_update(GTK_WIDGET(treeview), NULL);
900 }
901 
902 
903 static void
ui_arc_manage_cb_row_activated(GtkTreeView * treeview,GtkTreePath * path,GtkTreeViewColumn * col,gpointer userdata)904 ui_arc_manage_cb_row_activated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata)
905 {
906 	ui_arc_manage_cb_edit_clicked(GTK_WIDGET(treeview), userdata);
907 }
908 
909 
910 static void
ui_arc_manage_cb_flttype_changed(GtkToggleButton * button,gpointer user_data)911 ui_arc_manage_cb_flttype_changed (GtkToggleButton *button, gpointer user_data)
912 {
913 	ui_arc_manage_populate_listview(user_data);
914 	//g_print(" toggle type=%d\n", gtk_toggle_button_get_active(button));
915 }
916 
917 
918 static gboolean
ui_arc_manage_cleanup(struct ui_arc_manage_data * data,gint result)919 ui_arc_manage_cleanup(struct ui_arc_manage_data *data, gint result)
920 {
921 gboolean doupdate = FALSE;
922 
923 	DB( g_print("\n[ui_scheduled] cleanup\n") );
924 
925 	da_archive_glist_sorted(1);
926 
927 	GLOBALS->changes_count += data->change;
928 
929 	return doupdate;
930 }
931 
932 
933 static void
ui_arc_manage_setup(struct ui_arc_manage_data * data)934 ui_arc_manage_setup(struct ui_arc_manage_data *data)
935 {
936 
937 	DB( g_print("\n[ui_scheduled] setup\n") );
938 
939 	//init GList
940 	data->tmp_list = NULL; //hb-glist_clone_list(GLOBALS->arc_list, sizeof(struct _Archive));
941 	data->change = 0;
942 
943 	//hb-glist_populate_treeview(data->tmp_list, data->LV_arc, LST_DEFARC_DATAS, LST_DEFARC_OLDPOS);
944 
945 	//insert all glist item into treeview
946 	ui_arc_manage_populate_listview(data);
947 
948 }
949 
950 
951 static GtkWidget *
ui_arc_manage_create_scheduling(struct ui_arc_manage_data * data)952 ui_arc_manage_create_scheduling(struct ui_arc_manage_data *data)
953 {
954 GtkWidget *content, *group_grid, *hbox, *expander, *label, *widget;
955 gint row;
956 
957 	content = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_SMALL);
958 
959 	// group :: Scheduled insertion
960 	group_grid = gtk_grid_new ();
961 	gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
962 	gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
963 	gtk_box_pack_start (GTK_BOX (content), group_grid, FALSE, FALSE, 0);
964 
965 	row = 0;
966 	widget = gtk_switch_new();
967 	data->CM_auto = widget;
968 	gtk_widget_set_halign(widget, GTK_ALIGN_START);
969 	gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
970 
971 	row++;
972 	label = gtk_label_new_with_mnemonic (_("Next _date:"));
973 	data->LB_next = label;
974 	gtk_grid_attach (GTK_GRID (group_grid), label, 0, row, 1, 1);
975 	widget = gtk_date_entry_new(label);
976 	data->PO_next = widget;
977 	gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
978 
979 	row++;
980 	label = make_label_widget(_("Ever_y:"));
981 	data->LB_every = label;
982 	gtk_grid_attach (GTK_GRID (group_grid), label, 0, row, 1, 1);
983 
984 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
985 	gtk_grid_attach (GTK_GRID (group_grid), hbox, 1, row, 1, 1);
986 	widget = make_numeric(label, 1, 100);
987 	data->NB_every = widget;
988     gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
989 	//label = gtk_label_new_with_mnemonic (_("_Unit:"));
990     //gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
991 	widget = make_cycle(label, CYA_ARC_UNIT);
992 	data->CY_unit = widget;
993     gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
994 
995 	expander = gtk_expander_new_with_mnemonic(_("More options"));
996 	data->EX_options = expander;
997 	gtk_box_pack_start (GTK_BOX (content), expander, FALSE, FALSE, 0);
998 
999 	// group :: Scheduled insertion
1000 	group_grid = gtk_grid_new ();
1001 	gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
1002 	gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
1003 	g_object_set(group_grid, "margin", SPACING_SMALL, NULL);
1004 	gtk_container_add(GTK_CONTAINER(expander), group_grid);
1005 
1006 	row++;
1007 	label = make_label_widget(_("Week end:"));
1008 	data->LB_weekend = label;
1009 	gtk_grid_attach (GTK_GRID (group_grid), label, 0, row, 1, 1);
1010 	widget = make_cycle(label, RA_ARC_WEEKEND);
1011 	data->CY_weekend = widget;
1012 	gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
1013 
1014 	row++;
1015 	label = make_label_widget(_("_Stop after:"));
1016 	gtk_grid_attach (GTK_GRID (group_grid), label, 0, row, 1, 1);
1017 
1018 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
1019 	gtk_grid_attach (GTK_GRID (group_grid), hbox, 1, row, 1, 1);
1020 
1021 		widget = gtk_check_button_new();
1022 		data->CM_limit = widget;
1023 		gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1024 
1025 		widget = make_numeric(label, 1, 366);
1026 		data->NB_limit = widget;
1027 	    gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
1028 
1029 		label = gtk_label_new_with_mnemonic (_("posts"));
1030 		data->LB_posts = label;
1031 	    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1032 
1033 	gtk_widget_show_all(content);
1034 
1035 	return content;
1036 }
1037 
1038 
1039 GtkWidget *
ui_arc_manage_dialog(Archive * ext_arc)1040 ui_arc_manage_dialog (Archive *ext_arc)
1041 {
1042 struct ui_arc_manage_data *data;
1043 GtkWidget *dialog, *content_area, *bbox, *hbox, *vbox, *tbar;
1044 GtkWidget *box, *treeview, *scrollwin;
1045 GtkWidget *widget, *content, *menubutton, *image, *label;
1046 GtkToolItem *toolitem;
1047 gint w, h, dw, dh;
1048 
1049 	data = g_malloc0(sizeof(struct ui_arc_manage_data));
1050 	if(!data) return NULL;
1051 
1052 	dialog = gtk_dialog_new_with_buttons (_("Manage scheduled/template transactions"),
1053 					    GTK_WINDOW(GLOBALS->mainwindow),
1054 					    0,
1055 					    _("_Close"),
1056 					    GTK_RESPONSE_ACCEPT,
1057 					    NULL);
1058 
1059 	data->dialog = dialog;
1060 
1061 	gtk_window_set_icon_name(GTK_WINDOW (dialog), ICONNAME_HB_ARCHIVE);
1062 
1063 	//set a nice dialog size
1064 	gtk_window_get_size(GTK_WINDOW(GLOBALS->mainwindow), &w, &h);
1065 	dh = (h*1.33/PHI);
1066 	//ratio 3:2
1067 	dw = (dh * 3) / 2;
1068 	DB( g_print(" main w=%d h=%d => diag w=%d h=%d\n", w, h, dw, dh) );
1069 	gtk_window_set_default_size (GTK_WINDOW(dialog), dw, dh);
1070 
1071 
1072 	//store our dialog private data
1073 	g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)data);
1074 	DB( g_print("\n[ui_scheduled] dialog=%p, inst_data=%p\n", dialog, data) );
1075 
1076 	//dialog content
1077 	content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));	 	// return a vbox
1078 
1079 	content = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM);
1080 	g_object_set(content, "margin", SPACING_LARGE, NULL);
1081 	gtk_box_pack_start (GTK_BOX (content_area), content, TRUE, TRUE, 0);
1082 
1083 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1084 	gtk_box_pack_start (GTK_BOX (content), hbox, FALSE, FALSE, 0);
1085 
1086 		box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1087 		gtk_box_pack_start (GTK_BOX (hbox), box, TRUE, TRUE, 0);
1088 
1089 		gtk_style_context_add_class (gtk_widget_get_style_context (box), GTK_STYLE_CLASS_LINKED);
1090 		gtk_style_context_add_class (gtk_widget_get_style_context (box), GTK_STYLE_CLASS_RAISED);
1091 		gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
1092 
1093 		widget = gtk_toggle_button_new_with_label(_("Scheduled"));
1094 		data->BT_typsch = widget;
1095 		gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
1096 
1097 		widget = gtk_toggle_button_new_with_label(_("Template"));
1098 		data->BT_typtpl = widget;
1099 		gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
1100 
1101 	widget = make_search ();
1102 	data->ST_search = widget;
1103 	gtk_widget_set_size_request(widget, HB_MINWIDTH_SEARCH, -1);
1104 	gtk_widget_set_halign(widget, GTK_ALIGN_END);
1105 	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1106 
1107 	//list + toolbar
1108 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1109 	gtk_box_pack_start (GTK_BOX (content), vbox, TRUE, TRUE, 0);
1110 
1111 	// listview
1112 	scrollwin = gtk_scrolled_window_new(NULL,NULL);
1113     gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
1114 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1115  	treeview = (GtkWidget *)list_tpl_new();
1116   	data->LV_arc = treeview;
1117 	gtk_widget_set_size_request(treeview, HB_MINWIDTH_LIST, -1);
1118 	gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
1119 	gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0);
1120 
1121 	tbar = gtk_toolbar_new();
1122 	gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
1123 	gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
1124 	gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
1125 	gtk_box_pack_start (GTK_BOX (vbox), tbar, FALSE, FALSE, 0);
1126 
1127 	bbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1128 	toolitem = gtk_tool_item_new();
1129 	gtk_container_add (GTK_CONTAINER(toolitem), bbox);
1130 	gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
1131 
1132 	//widget = gtk_button_new_with_mnemonic(_("_Add"));
1133 	widget = make_image_button(ICONNAME_LIST_ADD, _("Add"));
1134 	data->BT_add = widget;
1135 	gtk_container_add (GTK_CONTAINER(bbox), widget);
1136 
1137 	//widget = gtk_button_new_with_mnemonic(_("_Edit"));
1138 	widget = make_image_button(ICONNAME_LIST_EDIT, _("Edit"));
1139 	data->BT_edit = widget;
1140 	gtk_container_add (GTK_CONTAINER(bbox), widget);
1141 
1142 	//schedule button
1143 	menubutton = gtk_menu_button_new ();
1144 	data->MB_schedule = menubutton;
1145 	gtk_menu_button_set_direction (GTK_MENU_BUTTON(menubutton), GTK_ARROW_DOWN );
1146 	gtk_widget_set_halign (menubutton, GTK_ALIGN_END);
1147 	//gtk_widget_set_hexpand (menubutton, TRUE);
1148 	gtk_widget_show_all(menubutton);
1149 	gtk_container_add (GTK_CONTAINER(bbox), menubutton);
1150 
1151 	box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
1152 	label = gtk_label_new_with_mnemonic (_("_Schedule"));
1153 	gtk_box_pack_start (GTK_BOX(box), label, FALSE, FALSE, 0);
1154 	image = gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON);
1155 	gtk_box_pack_start (GTK_BOX(box), image, FALSE, FALSE, 0);
1156 	gtk_container_add(GTK_CONTAINER(menubutton), box);
1157 	GtkWidget *template = ui_arc_manage_create_scheduling(data);
1158 	GtkWidget *popover = create_popover (menubutton, template, GTK_POS_TOP);
1159 	gtk_menu_button_set_popover(GTK_MENU_BUTTON(menubutton), popover);
1160 
1161 	//widget = gtk_button_new_with_mnemonic(_("_Delete"));
1162 	widget = make_image_button(ICONNAME_LIST_DELETE, _("_Delete"));
1163 	data->BT_rem = widget;
1164 	gtk_container_add (GTK_CONTAINER(bbox), widget);
1165 
1166 	toolitem = gtk_separator_tool_item_new ();
1167 	gtk_tool_item_set_expand (toolitem, TRUE);
1168 	gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
1169 	gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
1170 
1171 	//toolitem = gtk_tool_item_new();
1172 	//gtk_container_add (GTK_CONTAINER(toolitem), widget);
1173 	//gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
1174 
1175 	toolitem = gtk_separator_tool_item_new ();
1176 	gtk_tool_item_set_expand (toolitem, TRUE);
1177 	gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
1178 	gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
1179 
1180 
1181 
1182 	/* set default periodicity to month */
1183 	//todo: move elsewhere
1184 	gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_unit), 2);
1185 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->BT_typsch), TRUE);
1186 
1187 	gtk_widget_show_all(content);
1188 
1189 	//connect all our signals
1190 	g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &dialog);
1191 
1192 	g_signal_connect (data->BT_typsch, "toggled", G_CALLBACK (ui_arc_manage_cb_flttype_changed), data);
1193 	g_signal_connect (data->BT_typtpl, "toggled", G_CALLBACK (ui_arc_manage_cb_flttype_changed), data);
1194 
1195 	g_signal_connect (data->ST_search, "search-changed", G_CALLBACK (ui_arc_manage_cb_flttype_changed), data);
1196 
1197 	g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_arc)), "changed", G_CALLBACK (ui_arc_manage_cb_selection_changed), NULL);
1198 	g_signal_connect (data->LV_arc, "row-activated", G_CALLBACK (ui_arc_manage_cb_row_activated), NULL);
1199 
1200 	g_signal_connect (data->BT_add , "clicked", G_CALLBACK (ui_arc_manage_cb_add_clicked), NULL);
1201 	g_signal_connect (data->BT_edit, "clicked", G_CALLBACK (ui_arc_manage_cb_edit_clicked), NULL);
1202 	g_signal_connect (data->BT_rem , "clicked", G_CALLBACK (ui_arc_manage_cb_delete_clicked), NULL);
1203 
1204 	g_signal_connect (popover, "closed", G_CALLBACK (ui_arc_manage_cb_popover_closed), NULL);
1205 
1206 	g_signal_connect (data->CM_auto,  "notify::active", G_CALLBACK (ui_arc_manage_cd_schedule_changed), NULL);
1207 	g_signal_connect (data->CM_limit, "toggled", G_CALLBACK (ui_arc_manage_cd_schedule_changed), NULL);
1208 
1209 	//setup, init and show dialog
1210 	ui_arc_manage_setup(data);
1211 	ui_arc_manage_update(data->LV_arc, NULL);
1212 	gtk_widget_grab_focus(GTK_WIDGET(data->LV_arc));
1213 
1214 
1215 	gtk_widget_show (dialog);
1216 
1217 	if(ext_arc != NULL)
1218 		list_tpl_select_by_pointer(GTK_TREE_VIEW(data->LV_arc), ext_arc);
1219 
1220 	//wait for the user
1221 	gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1222 
1223 	switch (result)
1224     {
1225 	case GTK_RESPONSE_ACCEPT:
1226 	   //do_application_specific_something ();
1227 	   break;
1228 	default:
1229 	   //do_nothing_since_dialog_was_cancelled ();
1230 	   break;
1231     }
1232 
1233 	// cleanup and destroy
1234 	ui_arc_manage_cleanup(data, result);
1235 	gtk_widget_destroy (dialog);
1236 
1237 	g_free(data);
1238 
1239 	return NULL;
1240 }
1241 
1242 
1243