GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dialog-dup-trans.c
1 /********************************************************************\
2  * dialog-dup-trans.c -- duplicate transaction dialog *
3  * Copyright (C) 2001 Gnumatic, Inc. *
4  * Author: Dave Peticolas <[email protected]> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program 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, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA [email protected] *
22 \********************************************************************/
23 
24 #include "config.h"
25 
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <time.h>
29 #include <stdlib.h>
30 
31 #include "dialog-dup-trans.h"
32 #include "dialog-utils.h"
33 #include "gnc-date-edit.h"
34 #include "qof.h"
35 
36 /* This static indicates the debugging module that this .o belongs to. */
37 G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
38 
39 typedef struct
40 {
41  GtkWidget * dialog;
42 
43  gboolean focus_out;
44 
45  GtkWidget * date_edit;
46  GtkWidget * num_edit;
47  GtkWidget * tnum_edit;
48 
49  GtkWidget *duplicate_title_label; // GtkLabel
50  GtkWidget *duplicate_table; // GtkTable
51  GtkWidget *date_label; // GtkLabel
52  GtkWidget *num_label; // GtkLabel
53  GtkWidget *tnum_label; // GtkLabel
55 
56 /* Parses the string value and returns true if it is a
57  * number. In that case, *num is set to the value parsed.
58  * Copied from numcell.c */
59 static gboolean
60 parse_num (const char *string, long int *num)
61 {
62  long int number;
63 
64  if (string == NULL)
65  return FALSE;
66 
67  if (!gnc_strisnum(string))
68  return FALSE;
69 
70  number = strtol(string, NULL, 10);
71 
72  if ((number == LONG_MIN) || (number == LONG_MAX))
73  return FALSE;
74 
75  if (num != NULL)
76  *num = number;
77 
78  return TRUE;
79 }
80 
81 static gboolean
82 gnc_dup_trans_output_cb(GtkSpinButton *spinbutton,
83  gpointer user_data)
84 {
85  gboolean is_number;
86  long int num;
87  gchar *txt = gtk_editable_get_chars(GTK_EDITABLE(spinbutton), 0, -1);
88  is_number = parse_num(txt, &num);
89  g_free(txt);
90  if (!is_number)
91  gtk_entry_set_text(GTK_ENTRY(spinbutton), "");
92  return !is_number;
93 }
94 
95 static void
96 gnc_dup_trans_dialog_create (GtkWidget * parent, DupTransDialog *dt_dialog,
97  gboolean show_date, time64 date,
98  const char *num_str, const char *tnum_str)
99 {
100  GtkWidget *dialog;
101  GtkBuilder *builder;
102 
103  builder = gtk_builder_new();
104  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "num_adjustment");
105  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "tnum_adjustment");
106  gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "Duplicate Transaction Dialog");
107 
108  dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Duplicate Transaction Dialog"));
109  dt_dialog->dialog = dialog;
110 
111  /* parent */
112  if (parent != NULL)
113  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
114 
115  /* date widget */
116  dt_dialog->date_label = GTK_WIDGET(gtk_builder_get_object (builder, "date_label"));
117  if (show_date)
118  {
119  GtkWidget *date_edit;
120  GtkWidget *hbox;
121  GtkWidget *label;
122 
123  date_edit = gnc_date_edit_new (date, FALSE, FALSE);
124  gnc_date_activates_default(GNC_DATE_EDIT(date_edit), TRUE);
125  hbox = GTK_WIDGET(gtk_builder_get_object (builder, "date_hbox"));
126  gtk_widget_show (date_edit);
127 
128  gnc_date_make_mnemonic_target (GNC_DATE_EDIT(date_edit), dt_dialog->date_label);
129 
130  gtk_box_pack_end (GTK_BOX (hbox), date_edit, TRUE, TRUE, 0);
131  dt_dialog->date_edit = date_edit;
132  }
133  else
134  {
135  GtkWidget *date_edit;
136  date_edit = gnc_date_edit_new (date, FALSE, FALSE);
137  dt_dialog->date_edit = date_edit;
138  }
139 
140  dt_dialog->duplicate_title_label = GTK_WIDGET(gtk_builder_get_object (builder, "duplicate_title_label"));
141  dt_dialog->duplicate_table = GTK_WIDGET(gtk_builder_get_object (builder, "duplicate_table"));
142  dt_dialog->num_label = GTK_WIDGET(gtk_builder_get_object (builder, "num_label"));
143  dt_dialog->tnum_label = GTK_WIDGET(gtk_builder_get_object (builder, "tnum_label"));
144 
145  {
146  GtkWidget *num_spin, *tnum_spin;
147  long int num, tnum;
148 
149  num_spin = GTK_WIDGET(gtk_builder_get_object (builder, "num_spin"));
150  tnum_spin = GTK_WIDGET(gtk_builder_get_object (builder, "tnum_spin"));
151  dt_dialog->num_edit = num_spin;
152  dt_dialog->tnum_edit = tnum_spin;
153 
154  gtk_entry_set_activates_default(GTK_ENTRY(num_spin), TRUE);
155  g_signal_connect(num_spin, "output",
156  G_CALLBACK(gnc_dup_trans_output_cb), dt_dialog);
157  g_signal_connect(tnum_spin, "output",
158  G_CALLBACK(gnc_dup_trans_output_cb), dt_dialog);
159 
160  if (num_str && parse_num (num_str, &num))
161  gtk_spin_button_set_value (GTK_SPIN_BUTTON (num_spin), num + 1);
162  else
163  gtk_entry_set_text (GTK_ENTRY (num_spin), "");
164 
165  if (tnum_str && parse_num (tnum_str, &tnum))
166  gtk_spin_button_set_value (GTK_SPIN_BUTTON (tnum_spin), tnum + 1);
167  else
168  gtk_entry_set_text (GTK_ENTRY (tnum_spin), "");
169  }
170 
171  gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, dt_dialog);
172 
173  g_object_unref(G_OBJECT(builder));
174 }
175 
176 static gboolean
177 gnc_dup_trans_dialog_internal (GtkWidget * parent, const char* title,
178  gboolean show_date, time64 *date_p,
179  GDate *gdate_p, const char *num, char **out_num,
180  const char *tnum, char **out_tnum)
181 {
182  DupTransDialog *dt_dialog;
183  GtkWidget *entry;
184  gboolean ok;
185  gint result;
186 
187  dt_dialog = g_new0 (DupTransDialog, 1);
188 
189  gnc_dup_trans_dialog_create (parent, dt_dialog, show_date,
190  *date_p, num, tnum);
191 
192  if (!show_date)
193  {
194  // The "date" field isn't being asked for, so we make the widgets invisible
195  gtk_widget_set_visible(dt_dialog->date_label, FALSE);
196  if (dt_dialog->date_edit)
197  gtk_widget_set_visible(dt_dialog->date_edit, FALSE);
198  // If no "date" field, there must be a "num" field, so give it focus
199  if (out_num)
200  gtk_widget_grab_focus (dt_dialog->num_edit);
201  }
202  else
203  {
204  GNCDateEdit *gde;
205 
206  gde = GNC_DATE_EDIT (dt_dialog->date_edit);
207  entry = gde->date_entry;
208  gtk_widget_grab_focus (entry);
209  }
210 
211  if (title)
212  {
213  gchar *full_text = g_strdup_printf("<b>%s</b>", title);
214  gtk_label_set_markup(GTK_LABEL (dt_dialog->duplicate_title_label), full_text);
215  g_free(full_text);
216  }
217 
218  if (!out_num)
219  {
220  // The "num" field isn't being asked for, so we make the widgets invisible
221  gtk_widget_set_visible(dt_dialog->num_label, FALSE);
222  gtk_widget_set_visible(dt_dialog->num_edit, FALSE);
223  }
224 
225  if (!tnum)
226  {
227  // The "tnum" field isn't being asked for, so we make the widgets invisible
228  gtk_widget_set_visible(dt_dialog->tnum_label, FALSE);
229  gtk_widget_set_visible(dt_dialog->tnum_edit, FALSE);
230  }
231 
232  if (!show_date && !tnum)
233  {
234  // The "date" and the "tnum" fields aren't being asked for, this is a split copy
235  gtk_label_set_markup(GTK_LABEL (dt_dialog->num_label), _("Action/Number:"));
236  }
237 
238  if (tnum)
239  {
240  gtk_entry_set_activates_default(GTK_ENTRY(dt_dialog->num_edit), FALSE);
241  gtk_entry_set_activates_default(GTK_ENTRY(dt_dialog->tnum_edit), TRUE);
242  }
243 
244  result = gtk_dialog_run (GTK_DIALOG (dt_dialog->dialog));
245 
246  if (result == GTK_RESPONSE_OK)
247  {
248  if (date_p)
249  *date_p = gnc_date_edit_get_date (GNC_DATE_EDIT (dt_dialog->date_edit));
250  if (gdate_p)
251  gnc_date_edit_get_gdate (GNC_DATE_EDIT (dt_dialog->date_edit), gdate_p);
252  if (out_num)
253  *out_num = g_strdup (gtk_entry_get_text (GTK_ENTRY (dt_dialog->num_edit)));
254  if (tnum)
255  *out_tnum = g_strdup (gtk_entry_get_text (GTK_ENTRY (dt_dialog->tnum_edit)));
256  ok = TRUE;
257  }
258  else
259  ok = FALSE;
260 
261  gtk_widget_destroy(GTK_WIDGET(dt_dialog->dialog));
262  g_free (dt_dialog);
263 
264  return ok;
265 }
266 
267 gboolean
268 gnc_dup_trans_dialog (GtkWidget * parent, const char* title, gboolean show_date,
269  time64 *date_p, const char *num, char **out_num,
270  const char *tnum, char **out_tnum)
271 {
272  return gnc_dup_trans_dialog_internal(parent, title, show_date, date_p, NULL,
273  num, out_num, tnum, out_tnum);
274 }
275 
276 gboolean
277 gnc_dup_trans_dialog_gdate (GtkWidget * parent, GDate *gdate_p,
278  const char *num, char **out_num)
279 {
280  time64 tmp_time;
281  g_assert(gdate_p);
282 
283  tmp_time = timespecToTime64(gdate_to_timespec(*gdate_p));
284  return gnc_dup_trans_dialog_internal(parent, NULL, TRUE, &tmp_time, gdate_p,
285  num, out_num, NULL, NULL);
286 }
287 
288 gboolean
289 gnc_dup_date_dialog (GtkWidget * parent, const char* title, GDate *gdate_p)
290 {
291  time64 tmp_time;
292  g_assert(gdate_p);
293 
294  tmp_time = timespecToTime64(gdate_to_timespec(*gdate_p));
295  return gnc_dup_trans_dialog_internal(parent, title, TRUE, &tmp_time, gdate_p,
296  NULL, NULL, NULL, NULL);
297 }
time64 timespecToTime64(Timespec ts)
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
gboolean gnc_strisnum(const gchar *s)
gint64 time64
Definition: gnc-date.h:83
Timespec gdate_to_timespec(GDate d)
const gchar * QofLogModule
Definition: qofid.h:89