5 A Linux/Unix GUI for Nokia mobile phones.
7 Released under the terms of the GNU GPL, see file COPYING for more details.
16 #include "xgnokii_contacts.h"
18 #include "xgnokii_lowlevel.h"
19 #include "xgnokii_common.h"
20 #include "xgnokii_speed.h"
21 #include "xpm/Read.xpm"
22 #include "xpm/Send.xpm"
23 #include "xpm/Open.xpm"
24 #include "xpm/Save.xpm"
25 #include "xpm/Edit.xpm"
26 #include "xpm/quest.xpm"
29 static GtkWidget *GUI_SpeedDialWindow;
30 static ErrorDialog errorDialog = {NULL, NULL};
31 static InfoDialog infoDialog = {NULL, NULL};
32 static ExportDialogData exportDialogData = {NULL};
33 static GtkWidget *clist;
34 static QuestMark questMark;
35 static gint selectedKey;
36 static bool speedDialInitialized;
39 static inline void Help1 (GtkWidget *w, gpointer data)
41 gchar *indx = g_strdup_printf ("/%s/gnokii/xgnokii/speeddial/index.htm", xgnokiiConfig.locale);
47 static void CloseSpeedDial (GtkWidget *w, gpointer data)
49 gtk_widget_hide (GUI_SpeedDialWindow);
53 static inline void DestroyCListData (gpointer data)
56 g_free ((D_SpeedDial *) data);
60 static void DeleteSelectContactDialog (GtkWidget *widget, GdkEvent *event,
61 SelectContactData *data)
63 gtk_widget_destroy (GTK_WIDGET (data->clist));
64 gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
65 gtk_widget_destroy (GTK_WIDGET (widget));
69 static void CancelSelectContactDialog (GtkWidget *widget,
70 SelectContactData *data)
72 gtk_widget_destroy (GTK_WIDGET (data->clist));
73 gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
74 gtk_widget_destroy (GTK_WIDGET (data->dialog));
78 static void OkSelectContactDialog (GtkWidget *widget,
79 SelectContactData *data)
82 PhonebookEntry *pbEntry;
85 if ((sel = GTK_CLIST (data->clist)->selection) != NULL)
87 D_SpeedDial *d = (D_SpeedDial *) g_malloc (sizeof (D_SpeedDial));
89 gtk_clist_freeze (GTK_CLIST (clist));
91 pbEntry = gtk_clist_get_row_data (GTK_CLIST (data->clist),
92 GPOINTER_TO_INT (sel->data));
94 gtk_clist_get_text (GTK_CLIST (clist), selectedKey, 0, &key);
96 gtk_clist_set_text (GTK_CLIST (clist), selectedKey, 1, pbEntry->entry.Name);
97 gtk_clist_set_text (GTK_CLIST (clist), selectedKey, 2, pbEntry->entry.Number);
99 d->entry.Number = *key - '0';
100 d->entry.MemoryType = pbEntry->entry.MemoryType + 2;
101 d->entry.Location = pbEntry->entry.Location;
103 gtk_clist_set_row_data_full (GTK_CLIST (clist), selectedKey,
104 (gpointer) d, DestroyCListData);
106 gtk_clist_sort (GTK_CLIST (clist));
107 gtk_clist_thaw (GTK_CLIST (clist));
110 gtk_widget_destroy (GTK_WIDGET (data->clist));
111 gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
112 gtk_widget_destroy (GTK_WIDGET (data->dialog));
115 static void ShowSelectContactsDialog (void)
117 SelectContactData *r;
119 if (!GUI_ContactsIsIntialized ())
122 if ((r = GUI_SelectContactDialog ()) == NULL)
125 gtk_signal_connect (GTK_OBJECT (r->dialog), "delete_event",
126 GTK_SIGNAL_FUNC (DeleteSelectContactDialog), (gpointer) r);
128 gtk_signal_connect (GTK_OBJECT (r->okButton), "clicked",
129 GTK_SIGNAL_FUNC (OkSelectContactDialog), (gpointer) r);
130 gtk_signal_connect (GTK_OBJECT (r->cancelButton), "clicked",
131 GTK_SIGNAL_FUNC (CancelSelectContactDialog), (gpointer) r);
135 static inline void EditKey (void)
139 if ((sel = GTK_CLIST (clist)->selection) != NULL)
141 selectedKey = GPOINTER_TO_INT (sel->data);
142 ShowSelectContactsDialog ();
147 static inline void ClickEntry (GtkWidget *clist,
150 GdkEventButton *event,
153 if(event && event->type == GDK_2BUTTON_PRESS)
156 ShowSelectContactsDialog ();
161 static void ReadSpeedDial (void)
163 PhonebookEntry *pbEntry;
169 register gint i, row_i = 0;
172 if (!GUI_ContactsIsIntialized ())
175 gtk_label_set_text (GTK_LABEL (infoDialog.text), _("Reading data ..."));
176 gtk_widget_show_now (infoDialog.dialog);
179 gtk_clist_freeze (GTK_CLIST (clist));
180 gtk_clist_clear (GTK_CLIST (clist));
182 for (i = 1; i < 10; i++)
184 if ((d = (D_SpeedDial *) g_malloc (sizeof (D_SpeedDial))) == NULL)
186 g_print (_("Cannot allocate memory!"));
190 if ((e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent))) == NULL)
192 g_print (_("Cannot allocate memory!"));
196 e->event = Event_GetSpeedDial;
199 pthread_mutex_lock (&speedDialMutex);
200 pthread_cond_wait (&speedDialCond, &speedDialMutex);
201 pthread_mutex_unlock (&speedDialMutex);
203 if (d->status != GE_NONE)
204 g_print ("Cannot read speed dial key %d!\n", i);
207 if (d->entry.Location == 0)
210 location = d->entry.Location;
211 if ((pbEntry = GUI_GetEntry (d->entry.MemoryType - 2, location)) == NULL)
218 row[1] = pbEntry->entry.Name;
219 row[2] = pbEntry->entry.Number;
221 gtk_clist_append (GTK_CLIST (clist), row);
222 gtk_clist_set_row_data_full (GTK_CLIST (clist), row_i++,
223 (gpointer) d, DestroyCListData);
226 gtk_widget_hide (infoDialog.dialog);
229 gtk_clist_sort (GTK_CLIST (clist));
230 gtk_clist_thaw (GTK_CLIST (clist));
231 speedDialInitialized = TRUE;
235 static void SaveSpeedDial (void)
242 if (speedDialInitialized)
243 for(i = 1; i < 10; i++)
245 if ((d = (D_SpeedDial *) gtk_clist_get_row_data (GTK_CLIST (clist), i - 1)))
247 if (d->entry.Location == 0)
249 if ((e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent))) == NULL)
251 g_print (_("Cannot allocate memory!"));
254 e->event = Event_SendSpeedDial;
257 /* pthread_mutex_lock (&speedDialMutex);
258 pthread_cond_wait (&speedDialCond, &speedDialMutex);
259 pthread_mutex_unlock (&speedDialMutex);
261 if (d->status != GE_NONE)
263 g_snprintf (buf, 80, _("Error writing speed\ndial for key %d!\n"),
265 gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
266 gtk_widget_show (errorDialog.dialog);
274 static bool ParseLine (D_SpeedDial *d, gchar *buf)
276 gchar **strings = g_strsplit (buf, ";", 3);
278 d->entry.Number = *strings[0] - '0';
279 if (d->entry.Number < 1 || d->entry.Number > 9)
281 g_strfreev (strings);
285 d->entry.MemoryType = *strings[1] - '0';
286 if (d->entry.MemoryType < 2 || d->entry.MemoryType > 3)
288 g_strfreev (strings);
292 d->entry.Location = atoi (strings[2]);
293 if (d->entry.Location == LONG_MIN || d->entry.Location == LONG_MAX ||
294 d->entry.Location < 0)
296 g_strfreev (strings);
300 g_strfreev (strings);
305 static void OkImportDialog (GtkWidget *w, GtkFileSelection *fs)
309 PhonebookEntry *pbEntry;
310 gchar buf[IO_BUF_LEN];
314 register gint i, row_i = 0;
316 fileName = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
317 gtk_widget_hide (GTK_WIDGET (fs));
319 if ((f = fopen (fileName, "r")) == NULL)
321 g_snprintf (buf, IO_BUF_LEN, _("Can't open file %s for reading!"), fileName);
322 gtk_label_set_text (GTK_LABEL(errorDialog.text), buf);
323 gtk_widget_show (errorDialog.dialog);
327 if (!GUI_ContactsIsIntialized ())
330 gtk_clist_freeze (GTK_CLIST (clist));
331 gtk_clist_clear (GTK_CLIST (clist));
332 speedDialInitialized = FALSE;
335 while (fgets (buf, IO_BUF_LEN, f) && i++ < 9)
337 if ((d = (D_SpeedDial *) g_malloc (sizeof (D_SpeedDial))) == NULL)
339 g_print (_("Cannot allocate memory!\n"));
340 gtk_clist_clear (GTK_CLIST (clist));
341 gtk_clist_sort (GTK_CLIST (clist));
342 gtk_clist_thaw (GTK_CLIST (clist));
345 if (ParseLine (d, buf))
347 if (d->entry.Number != i)
350 gtk_clist_clear (GTK_CLIST (clist));
351 gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Error reading file!"));
352 gtk_widget_show (errorDialog.dialog);
353 gtk_clist_sort (GTK_CLIST (clist));
354 gtk_clist_thaw (GTK_CLIST (clist));
357 if (d->entry.Location == 0)
360 location = d->entry.Location;
361 if ((pbEntry = GUI_GetEntry (d->entry.MemoryType - 2, location)) == NULL)
369 row[1] = pbEntry->entry.Name;
370 row[2] = pbEntry->entry.Number;
371 gtk_clist_append (GTK_CLIST (clist), row);
372 gtk_clist_set_row_data_full (GTK_CLIST (clist), row_i++,
373 (gpointer) d, DestroyCListData);
378 gtk_clist_clear (GTK_CLIST (clist));
379 gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Error reading file!"));
380 gtk_widget_show (errorDialog.dialog);
381 gtk_clist_sort (GTK_CLIST (clist));
382 gtk_clist_thaw (GTK_CLIST (clist));
387 gtk_clist_sort (GTK_CLIST (clist));
388 gtk_clist_thaw (GTK_CLIST (clist));
389 speedDialInitialized = TRUE;
393 static void ImportSpeedDial (void)
395 static GtkWidget *fileDialog = NULL;
397 if (fileDialog == NULL)
399 fileDialog = gtk_file_selection_new (_("Import"));
400 gtk_signal_connect (GTK_OBJECT (fileDialog), "delete_event",
401 GTK_SIGNAL_FUNC (DeleteEvent), NULL);
402 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->ok_button),
403 "clicked", GTK_SIGNAL_FUNC (OkImportDialog), (gpointer) fileDialog);
404 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->cancel_button),
405 "clicked", GTK_SIGNAL_FUNC (CancelDialog), (gpointer) fileDialog);
408 gtk_widget_show (fileDialog);
412 static void ExportSpeedDialMain (gchar *name)
416 gchar buf[IO_BUF_LEN];
419 if ((f = fopen( name, "w")) == NULL)
421 g_snprintf (buf, IO_BUF_LEN, _("Can't open file %s for writing!"), name);
422 gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
423 gtk_widget_show (errorDialog.dialog);
427 for(i = 1; i < 10; i++)
429 if ((d = (D_SpeedDial *) gtk_clist_get_row_data (GTK_CLIST (clist), i - 1)))
431 sprintf (buf, "%d;%d;%d;", d->entry.Number, d->entry.MemoryType, d->entry.Location);
432 fprintf (f, "%s\n", buf);
440 static void YesExportDialog (GtkWidget *w, gpointer data)
442 gtk_widget_hide (GTK_WIDGET (data));
443 ExportSpeedDialMain (exportDialogData.fileName);
447 static void OkExportDialog (GtkWidget *w, GtkFileSelection *fs)
449 static YesNoDialog dialog = { NULL, NULL};
454 exportDialogData.fileName = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
455 gtk_widget_hide (GTK_WIDGET (fs));
457 if ((f = fopen (exportDialogData.fileName, "r")) != NULL)
460 if (dialog.dialog == NULL)
462 CreateYesNoDialog (&dialog, YesExportDialog, CancelDialog, GUI_SpeedDialWindow);
463 gtk_window_set_title (GTK_WINDOW (dialog.dialog), _("Overwrite file?"));
464 g_snprintf ( err, 80, _("File %s already exist.\nOverwrite?"), exportDialogData.fileName);
465 gtk_label_set_text (GTK_LABEL(dialog.text), err);
467 gtk_widget_show (dialog.dialog);
470 ExportSpeedDialMain (exportDialogData.fileName);
474 static void ExportSpeedDial (void)
476 static GtkWidget *fileDialog = NULL;
478 if (speedDialInitialized)
480 if (fileDialog == NULL)
482 fileDialog = gtk_file_selection_new (_("Export"));
483 gtk_signal_connect (GTK_OBJECT (fileDialog), "delete_event",
484 GTK_SIGNAL_FUNC (DeleteEvent), NULL);
485 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->ok_button),
486 "clicked", GTK_SIGNAL_FUNC (OkExportDialog), (gpointer) fileDialog);
487 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->cancel_button),
488 "clicked", GTK_SIGNAL_FUNC (CancelDialog), (gpointer) fileDialog);
491 gtk_widget_show (fileDialog);
496 inline void GUI_ShowSpeedDial (void)
499 gtk_widget_show (GUI_SpeedDialWindow);
503 static GtkItemFactoryEntry menu_items[] = {
504 { NULL, NULL, NULL, 0, "<Branch>"},
505 { NULL, "<control>R", ReadSpeedDial, 0, NULL},
506 { NULL, "<control>S", SaveSpeedDial, 0, NULL},
507 { NULL, NULL, NULL, 0, "<Separator>"},
508 { NULL, "<control>I", ImportSpeedDial, 0, NULL},
509 { NULL, "<control>E", ExportSpeedDial, 0, NULL},
510 { NULL, NULL, NULL, 0, "<Separator>"},
511 { NULL, "<control>W", CloseSpeedDial, 0, NULL},
512 { NULL, NULL, NULL, 0, "<Branch>"},
513 { NULL, NULL, EditKey, 0, NULL},
514 { NULL, NULL, NULL, 0, "<LastBranch>"},
515 { NULL, NULL, Help1, 0, NULL},
516 { NULL, NULL, GUI_ShowAbout, 0, NULL},
520 static void InitMainMenu (void)
522 menu_items[0].path = g_strdup (_("/_File"));
523 menu_items[1].path = g_strdup (_("/File/_Read from phone"));
524 menu_items[2].path = g_strdup (_("/File/_Save to phone"));
525 menu_items[3].path = g_strdup (_("/File/Sep1"));
526 menu_items[4].path = g_strdup (_("/File/_Import from file"));
527 menu_items[5].path = g_strdup (_("/File/_Export to file"));
528 menu_items[6].path = g_strdup (_("/File/Sep2"));
529 menu_items[7].path = g_strdup (_("/File/_Close"));
530 menu_items[8].path = g_strdup (_("/_Edit"));
531 menu_items[9].path = g_strdup (_("/Edit/_Edit"));
532 menu_items[10].path = g_strdup (_("/_Help"));
533 menu_items[11].path = g_strdup (_("/Help/_Help"));
534 menu_items[12].path = g_strdup (_("/Help/_About"));
538 void GUI_CreateSpeedDialWindow (void)
540 int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
541 GtkItemFactory *item_factory;
542 GtkAccelGroup *accel_group;
545 GtkWidget *main_vbox;
547 GtkWidget *clistScrolledWindow;
549 gchar *titles[3] = {_("Key"), _("Name"), _("Number")};
553 GUI_SpeedDialWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
554 gtk_window_set_title (GTK_WINDOW (GUI_SpeedDialWindow), _("Speed Dial"));
555 gtk_widget_set_usize (GTK_WIDGET (GUI_SpeedDialWindow), 332, 220);
556 //gtk_container_set_border_width (GTK_CONTAINER (GUI_SpeedDialWindow), 10);
557 gtk_signal_connect (GTK_OBJECT (GUI_SpeedDialWindow), "delete_event",
558 GTK_SIGNAL_FUNC (DeleteEvent), NULL);
559 gtk_widget_realize (GUI_SpeedDialWindow);
561 accel_group = gtk_accel_group_new ();
562 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
565 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
567 gtk_accel_group_attach (accel_group, GTK_OBJECT (GUI_SpeedDialWindow));
569 /* Finally, return the actual menu bar created by the item factory. */
570 menubar = gtk_item_factory_get_widget (item_factory, "<main>");
572 main_vbox = gtk_vbox_new (FALSE, 1);
573 gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
574 gtk_container_add (GTK_CONTAINER (GUI_SpeedDialWindow), main_vbox);
575 gtk_widget_show (main_vbox);
577 gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, FALSE, 0);
578 gtk_widget_show (menubar);
580 /* Create the toolbar */
582 toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
583 gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
585 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Read from phone"), NULL,
586 NewPixmap(Read_xpm, GUI_SpeedDialWindow->window,
587 &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
588 (GtkSignalFunc) ReadSpeedDial, NULL);
589 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Save to phone"), NULL,
590 NewPixmap(Send_xpm, GUI_SpeedDialWindow->window,
591 &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
592 (GtkSignalFunc) SaveSpeedDial, NULL);
594 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
596 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Import from file"), NULL,
597 NewPixmap(Open_xpm, GUI_SpeedDialWindow->window,
598 &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
599 (GtkSignalFunc) ImportSpeedDial, NULL);
600 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Export to file"), NULL,
601 NewPixmap(Save_xpm, GUI_SpeedDialWindow->window,
602 &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
603 (GtkSignalFunc) ExportSpeedDial, NULL);
605 gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
607 gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Edit entry"), NULL,
608 NewPixmap(Edit_xpm, GUI_SpeedDialWindow->window,
609 &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
610 (GtkSignalFunc) EditKey, NULL);
612 gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
613 gtk_widget_show (toolbar);
615 clist = gtk_clist_new_with_titles (3, titles);
616 gtk_clist_set_shadow_type (GTK_CLIST (clist), GTK_SHADOW_OUT);
617 // gtk_clist_set_compare_func (GTK_CLIST (clist), CListCompareFunc);
618 gtk_clist_set_sort_column (GTK_CLIST (clist), 0);
619 gtk_clist_set_sort_type (GTK_CLIST (clist), GTK_SORT_ASCENDING);
620 gtk_clist_set_auto_sort (GTK_CLIST (clist), FALSE);
621 //gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
623 gtk_clist_set_column_width (GTK_CLIST (clist), 1, 150);
624 gtk_clist_set_column_width (GTK_CLIST (clist), 2, 115);
625 gtk_clist_set_column_justification (GTK_CLIST (clist), 0, GTK_JUSTIFY_CENTER);
626 // gtk_clist_set_column_visibility (GTK_CLIST (clist), 3, xgnokiiConfig.callerGroupsSupported);
628 for (i = 0; i < 3; i++)
630 if ((sColumn = g_malloc (sizeof (SortColumn))) == NULL)
632 g_print (_("Error: %s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
635 sColumn->clist = clist;
637 gtk_signal_connect (GTK_OBJECT (GTK_CLIST (clist)->column[i].button), "clicked",
638 GTK_SIGNAL_FUNC (SetSortColumn), (gpointer) sColumn);
641 gtk_signal_connect (GTK_OBJECT (clist), "select_row",
642 GTK_SIGNAL_FUNC (ClickEntry), NULL);
644 clistScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
645 gtk_container_add (GTK_CONTAINER (clistScrolledWindow), clist);
646 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clistScrolledWindow),
647 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
648 gtk_box_pack_start (GTK_BOX (main_vbox), clistScrolledWindow,
651 gtk_widget_show (clist);
652 gtk_widget_show (clistScrolledWindow);
654 questMark.pixmap = gdk_pixmap_create_from_xpm_d (GUI_SpeedDialWindow->window,
656 &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL],
659 CreateErrorDialog (&errorDialog, GUI_SpeedDialWindow);
660 CreateInfoDialog (&infoDialog, GUI_SpeedDialWindow);
661 speedDialInitialized = FALSE;