#include "main.h" #include "guivars.h" /* Some background colors for the clist */ GdkColor light_red, white; void gse_init_colors (void) { light_red.pixel = 0; light_red.red = 0xffff; light_red.green = 0xb500; light_red.blue = 0xb500; white.pixel = 0; white.red = 0xffff; white.green = 0xffff; white.blue = 0xffff; } /* Last function called by the program. Frees all (?) memory and saves configuration to disk */ void gse_exit_program (GtkWidget *wgt, gpointer data) { gint i; cfg_write_config_file (); g_free (cur_open_file.filename); g_free (cfg.last_open_dir); g_free (cfg.last_save_dir); for (i = 0; i < CFG_NUM_PRE_FPS; i++) g_free (cfg.predef_fps[i]); g_free (cfg.isp_cmd); g_free (cfg.isp_opt); for (i = 0; i < cfg.isp_langcount; i++) g_free (cfg.lang_list[i]); g_free (cfg.lang_list); gtk_main_quit (); } /* Called from the gui (exit button/windowmanager close button). * If there are unsaved files, a dialog is shown */ int gse_delete_main_window (GtkWidget *win, gpointer data) { if (cur_open_file.filename != NULL && cur_open_file.changed) { switch (gse_ask_user_save_changes (cur_open_file.filename)) { case 2: return TRUE; break; case 1: break; case 0: gse_fl_write_file (cur_open_file.filename, cur_open_file.filetype, GSE_NO_SPLIT); break; } gse_exit_program (NULL, NULL); return FALSE; } else { gse_exit_program (NULL, NULL); return FALSE; } return TRUE; } /* Re-index the first column of the main clist * caller should freeze and thaw the clist */ void gse_mwin_clist_update_index (void) { gint i; gchar idx[10]; for (i = 0; i < GTK_CLIST (mwin_clist)->rows; i++) { g_snprintf (idx, 10, "%d", i + 1); gtk_clist_set_text (GTK_CLIST (mwin_clist), i, 0, idx); } } /* Returns true if clist is NULL or if it contains 0 rows */ gboolean gse_clist_is_empty (GtkWidget *clist) { gint rows; if (mwin_clist == NULL) return TRUE; rows = GTK_CLIST(mwin_clist)->rows; if (rows < 1) return TRUE; return FALSE; } /* Sets the window titlebar to GSubEdit ($version) - $current_open_file * if 'changed' is true, then "(Changed)" is appended to the title */ void gse_set_title_changed (gboolean changed) { gchar title[BUF_LEN]; gchar *fname; if (cur_open_file.filename == NULL) fname = g_strdup (""); else fname = g_strdup_printf ("- %s", cur_open_file.filename); g_snprintf (title, BUF_LEN, "GSubEdit (v" VERSION ") %s %s", g_basename (fname), changed ? _("(Changed)"): ""); gtk_window_set_title (GTK_WINDOW (main_window), title); g_free (fname); } /* Sets the sensitive state of the menu and toolbar according to the state * (if a file is opened or not, and what type is open) */ void gse_set_menu_toolbar_state (gint state) { gboolean bol; if (state) bol = TRUE; else bol = FALSE; /* The menus and toolbar */ gtk_widget_set_sensitive (file_menu[GSE_MENU_FILE_SAVE].widget, state); gtk_widget_set_sensitive (file_menu[GSE_MENU_FILE_SAVE_AS].widget, state); gtk_widget_set_sensitive (file_menu[GSE_MENU_FILE_REVERT].widget, bol); gtk_widget_set_sensitive (file_menu[GSE_MENU_FILE_CLOSE].widget, bol); gtk_widget_set_sensitive (edit_menu[GSE_MENU_EDIT_FIND].widget, bol); gtk_widget_set_sensitive (edit_menu[GSE_MENU_EDIT_REPLACE].widget, bol); /* Only active if currently open file is MicroDVD */ gtk_widget_set_sensitive (edit_menu[GSE_MENU_EDIT_CALC_FPS].widget, state & GSE_FILE_OPEN_MICRODVD); gtk_widget_set_sensitive (edit_menu[GSE_MENU_EDIT_SPELL].widget, bol); gtk_widget_set_sensitive (action_menu[GSE_MENU_ACTION_DISPLACE].widget, bol); gtk_widget_set_sensitive (action_menu[GSE_MENU_ACTION_FPSCONV].widget, bol); gtk_widget_set_sensitive (action_menu[GSE_MENU_ACTION_HICLEAN].widget, bol); gtk_widget_set_sensitive (action_menu[GSE_MENU_ACTION_SPLIT].widget, bol); gtk_widget_set_sensitive (main_toolbar[GSE_TOOLBAR_CLOSE].widget, bol); gtk_widget_set_sensitive (main_toolbar[GSE_TOOLBAR_SAVE].widget, bol); gtk_widget_set_sensitive (main_toolbar[GSE_TOOLBAR_DISPLACE].widget, bol); gtk_widget_set_sensitive (main_toolbar[GSE_TOOLBAR_FPSCONV].widget, bol); gtk_widget_set_sensitive (main_toolbar[GSE_TOOLBAR_HICLEAN].widget, bol); gtk_widget_set_sensitive (main_toolbar[GSE_TOOLBAR_SPLIT].widget, bol); /* The infobox */ gtk_widget_set_sensitive (infobox.combo, bol); /* The edit-entries */ gtk_widget_set_sensitive (mwin_text_sub, bol); gtk_widget_set_sensitive (mwin_entry_start, bol); gtk_widget_set_sensitive (mwin_entry_end, bol); } /* Checks if a string contains _only_ digits (CR / LF ignored) or if str is NULL */ gboolean gse_str_only_digits (gchar *str) { gint i; gboolean other_char_found = FALSE, digit_found = FALSE; if (str == NULL) /* Special occasion, have to return TRUE */ return TRUE; for (i = 0; i < strlen (str); i++) { if (isdigit (str[i])) digit_found = TRUE; else if (str[i] != '\r' && str[i] != '\n') other_char_found = TRUE; } /* Returns true if string contains at least one digit and nothing else except CR/LF */ return (digit_found & !other_char_found); } /* Checks if a string contains _only_ whitespaces or if str is NULL*/ gboolean gse_str_only_spaces (gchar *str) { gint i; gboolean ret = TRUE; if (str == NULL) return TRUE; for (i = 0; i < strlen (str); i++) if (!isspace (str[i])) ret = FALSE; return ret; } /* Called when an automatic action to clean the subtitle (such as "hearing impared remover") is performed * It takes an pointer to a string as arg and checks it for empty parts: * the string "first line||another line|" would become "first line|another line" */ void gse_str_remove_empty_lines (gchar **str) { gchar **str_v, *ptr; GString *new_str; gboolean empty; gint i, max_len = strlen (*str) + 1; str_v = g_strsplit (*str, "|", 4); new_str = g_string_new (""); for (i = 0; str_v[i] != NULL; i++) { empty = TRUE; for (ptr = str_v[i]; *ptr != '\0'; ptr++) { if (isalpha (*ptr)) { empty = FALSE; break; } } if (!empty) { g_string_append (new_str, str_v[i]); g_string_append (new_str, "|"); } } g_snprintf (*str, max_len, "%s", new_str->str); if ((*str) [strlen (*str) - 1] == '|') (*str) [strlen (*str) - 1] = '\0'; g_strfreev (str_v); g_string_free (new_str, TRUE); } /* Converts a number of seconds to hours, minutes, seconds and milliseconds * returns -1 on failure, otherwise 0 */ gint gse_parse_time (gdouble in_sec, gint *hr, gint *min, gint *sec, gint *msec) { if (in_sec < 0) { *hr = *min = *sec = *msec = 0; return -1; } *hr = in_sec / 3600; in_sec -= (3600 * (*hr)); *min = in_sec / 60; in_sec -= (60 * (*min)); *sec = (int) in_sec; in_sec -= (*sec); *msec = (int) (in_sec * 1000); return 0; } /* Converts a string in the format HH:MM:SS,msec to int values */ gint gse_str_to_time (const gchar *str, gint *hr, gint *min, gint *sec, gint *msec) { gint check; check = sscanf (str, "%d:%d:%d,%d", hr, min, sec, msec); if (check < 4) return -1; else return 0; } /* Returns a formatted SubRip timestring * The returnvalue should be free'd when no longer used */ gchar *gse_time_to_str (gint hr, gint min, gint sec, gint msec) { return g_strdup_printf ("%.2d:%.2d:%.2d,%.3d", hr, min, sec, msec); } /* Adds 'add_sec' seconds to a time and does proper formatting of the time */ gint gse_add_to_time (gdouble add_sec, gint *hr, gint *min, gint *sec, gint *msec) { gdouble tot_sec = 0; tot_sec = (*hr * 3600) + (*min * 60) + (*sec); tot_sec += (gdouble) *msec / 1000; tot_sec += add_sec; return gse_parse_time (tot_sec, hr, min, sec, msec); } /* Converts a time (hour, min, sec, millisec) to a frame-value according to 'fps' (frames per second) */ gdouble gse_time_to_frame (gdouble fps, gint hr, gint min, gint sec, gint msec) { gdouble tot_sec = 0; tot_sec = (hr * 3600) + (min * 60) + (sec); tot_sec += (gdouble) msec / 1000; return (tot_sec * fps); } /* Returns the number of seconds a frame is equal to according to the current framerate */ gdouble gse_frame_to_time (gdouble fps, gint frame) { return (gdouble) frame / fps; } /* Converts a frame of src_fps to dest_fps */ glong gse_frame_rate_convert (gint frame, gdouble src_fps, gdouble dest_fps) { gdouble tot_sec; tot_sec = gse_frame_to_time (src_fps, frame); return (glong) (tot_sec * dest_fps); } /* The about dialog */ void gse_about (GtkWidget *wgt, gpointer data) { GtkWidget *box; const char *authors[] = { "Isak Savo ", NULL }; box = gnome_about_new("GSubEdit", VERSION, "(C) 2002 Isak Savo", authors, _("A Gnome application for editing DivX ;-) subtitles\n" "Released under the terms of the GNU General Public License\n" "Visit http://gsubedit.sourceforge.net/ for updates"), NULL); gtk_widget_show(box); } /* Function that updates the toolbar style according to the preferences * (Taken from Gnome Transfer Manager (gtm) written by Bruno Pires Marinho) */ void gse_update_toolbar_style (void) { GnomeDockItem *item; GtkWidget *toolbar; item = gnome_app_get_dock_item_by_name (GNOME_APP (main_window), GNOME_APP_TOOLBAR_NAME); toolbar = gnome_dock_item_get_child (item); gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), cfg.toolbar_style); gtk_widget_queue_resize (main_window); } void gse_gui_set_infobox_values (void) { gchar tmp[100]; GList *lang = NULL; gint i; g_snprintf (tmp, 100, _("Filesize: %d kb"), cur_open_file.size); gtk_label_set_text (GTK_LABEL (infobox.fsize), tmp); g_snprintf (tmp, 100, _("Lines: %d"), cur_open_file.lines); gtk_label_set_text (GTK_LABEL (infobox.lines), tmp); g_snprintf (tmp, 100, _("Framerate: %.3lf fps"), cur_open_file.fps); gtk_label_set_text (GTK_LABEL (infobox.fps), tmp); for (i = 0; i < cfg.isp_langcount; i += 2) lang = g_list_append (lang, cfg.lang_list[i]); gtk_combo_set_popdown_strings (GTK_COMBO (infobox.combo), lang); g_list_free (lang); } GtkWidget *gse_create_vbox_edit_entry (void) { GtkWidget *f_vbox, *f_hbox, *f_scr_win, *lbl, *btn; f_vbox = gtk_vbox_new (FALSE, 5); f_hbox = gtk_hbox_new (FALSE, 5); btn = gtk_button_new_with_label (_("Update")); gtk_widget_show (btn); gtk_signal_connect (GTK_OBJECT (btn), "clicked", GTK_SIGNAL_FUNC (gse_cb_update_edit_changes), GINT_TO_POINTER (1)); gtk_box_pack_end (GTK_BOX (f_hbox), btn, TRUE, TRUE, 0); lbl = gtk_label_new (_("End:")); mwin_entry_end = gtk_entry_new_with_max_length (GSE_START_STOP_ENTRY_MAX); gtk_widget_set_usize (mwin_entry_end, 80, 22); gtk_widget_show (lbl); gtk_widget_show (mwin_entry_end); gtk_signal_connect (GTK_OBJECT (mwin_entry_end), "changed", GTK_SIGNAL_FUNC (gse_cb_update_edit_changes), NULL); gtk_signal_connect (GTK_OBJECT (mwin_entry_end), "key-press-event", GTK_SIGNAL_FUNC (gse_cb_text_edit_key_press_event), NULL); gtk_box_pack_end (GTK_BOX (f_hbox), mwin_entry_end, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (f_hbox), lbl, FALSE, FALSE, 0); lbl = gtk_label_new (_("Start:")); mwin_entry_start = gtk_entry_new_with_max_length (GSE_START_STOP_ENTRY_MAX); gtk_widget_set_usize (mwin_entry_start, 80, 22); gtk_widget_show (lbl); gtk_widget_show (mwin_entry_start); gtk_signal_connect (GTK_OBJECT (mwin_entry_start), "changed", GTK_SIGNAL_FUNC (gse_cb_update_edit_changes), NULL); gtk_signal_connect (GTK_OBJECT (mwin_entry_start), "key-press-event", GTK_SIGNAL_FUNC (gse_cb_text_edit_key_press_event), NULL); gtk_box_pack_end (GTK_BOX (f_hbox), mwin_entry_start, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (f_hbox), lbl, FALSE, FALSE, 0); mwin_text_sub = gtk_text_new (NULL, NULL); gtk_text_set_editable (GTK_TEXT (mwin_text_sub), TRUE); f_scr_win = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (f_scr_win), mwin_text_sub); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (f_scr_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_signal_connect (GTK_OBJECT (mwin_text_sub), "changed", GTK_SIGNAL_FUNC (gse_cb_update_edit_changes), NULL); gtk_signal_connect (GTK_OBJECT (mwin_text_sub), "key-press-event", GTK_SIGNAL_FUNC (gse_cb_text_edit_key_press_event), NULL); gtk_box_pack_start (GTK_BOX (f_vbox), f_hbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (f_vbox), f_scr_win, FALSE, FALSE, 0); gtk_widget_show (mwin_text_sub); gtk_widget_show (f_vbox); return (f_vbox); } /* The lower left box! */ GtkWidget *gse_create_vbox_bottom_left (void) { GtkWidget *fix_box, *hbox, *frame, *lbl; #define X_POS 10 frame = gtk_frame_new (_("Subtitle information")); fix_box = gtk_fixed_new (); infobox.fsize = gtk_label_new (NULL); gtk_fixed_put (GTK_FIXED (fix_box), infobox.fsize, X_POS, 10); infobox.lines = gtk_label_new (NULL); gtk_fixed_put (GTK_FIXED (fix_box), infobox.lines, X_POS, 30); infobox.fps = gtk_label_new (NULL); gtk_fixed_put (GTK_FIXED (fix_box), infobox.fps, X_POS, 50); hbox = gtk_hbox_new (FALSE, 0); lbl = gtk_label_new (_("Language:")); infobox.combo = gtk_combo_new (); gtk_combo_set_popdown_strings (GTK_COMBO (infobox.combo), lang_list); gtk_box_pack_start (GTK_BOX (hbox), lbl, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), infobox.combo, FALSE, FALSE, 5); gtk_signal_connect (GTK_OBJECT (GTK_COMBO (infobox.combo)->entry), "changed", GTK_SIGNAL_FUNC (gse_cb_combolang_changed), NULL); gtk_fixed_put (GTK_FIXED (fix_box), hbox, X_POS, 70); gtk_container_add (GTK_CONTAINER (frame), fix_box); gtk_widget_show_all (frame); gse_gui_set_infobox_values (); return (frame); } int gse_create_main_window (void) { GtkWidget *mwin_vbox_main, *mwin_hbox, *mwin_vbox_bottom_left, *mwin_vbox_edit_entry; GtkWidget *mwin_scrollwin, *clist_popup; gint i; static GtkTargetEntry target_table[] = { { "text/uri-list", 0, GSE_DROP_URL }, { "text/plain", 0, GSE_DROP_TEXT_PLAIN }, { "STRING", 0, GSE_DROP_STRING } }; gchar *tmp_titles[4]; #define GSE_DROP_TABLE_COUNT 3 gse_init_colors (); /* Define the standard colors */ main_window = gnome_app_new ("gsubedit", "GSubEdit (v" VERSION ")"); gtk_signal_connect (GTK_OBJECT(main_window), "delete_event", GTK_SIGNAL_FUNC(gse_delete_main_window), NULL); gnome_app_create_menus (GNOME_APP(main_window), main_menu); gnome_app_create_toolbar (GNOME_APP (main_window), main_toolbar); gse_update_toolbar_style (); mwin_statusbar = gnome_appbar_new (TRUE, TRUE, GNOME_PREFERENCES_USER); gnome_app_set_statusbar (GNOME_APP(main_window), mwin_statusbar); gnome_app_install_menu_hints (GNOME_APP(main_window), main_menu); /* Start creating the different widgets, one function for each frame/box */ mwin_vbox_edit_entry = gse_create_vbox_edit_entry (); mwin_vbox_bottom_left = gse_create_vbox_bottom_left (); /* Now, lets pack the stuff into place */ mwin_vbox_main = gtk_vbox_new (FALSE, 5); mwin_hbox= gtk_hbox_new (FALSE, 5); /* The clist which contains the subtitles */ for (i = 0; i < 4; i++) tmp_titles[i] = _(mwin_clist_titles[i]); mwin_clist = gtk_clist_new_with_titles (4, tmp_titles); gtk_clist_set_selection_mode (GTK_CLIST (mwin_clist), GTK_SELECTION_BROWSE); mwin_scrollwin = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (mwin_scrollwin), mwin_clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mwin_scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_signal_connect (GTK_OBJECT (mwin_clist), "select_row", GTK_SIGNAL_FUNC (gse_cb_clist_select_row), NULL); gtk_signal_connect (GTK_OBJECT (mwin_clist), "button-press-event", GTK_SIGNAL_FUNC (gse_cb_clist_mouse_press_event), NULL); gtk_signal_connect (GTK_OBJECT (mwin_clist), "key-press-event", GTK_SIGNAL_FUNC (gse_cb_clist_key_press_event), NULL); /* Setup drag'n'drop */ gtk_drag_dest_set (mwin_scrollwin, GTK_DEST_DEFAULT_ALL, target_table, GSE_DROP_TABLE_COUNT, GDK_ACTION_COPY | GDK_ACTION_MOVE); gtk_signal_connect (GTK_OBJECT (mwin_scrollwin), "drag_data_received", GTK_SIGNAL_FUNC (gse_cb_mwin_drop_recieved), NULL); /* Attach a popup menu to the clist */ clist_popup = gnome_popup_menu_new (clist_popup_menu); gnome_popup_menu_attach (clist_popup, mwin_clist, NULL); gtk_widget_show (mwin_clist); gtk_widget_show (mwin_scrollwin); gtk_box_pack_start (GTK_BOX (mwin_hbox), mwin_scrollwin, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (mwin_vbox_main), mwin_hbox, TRUE, TRUE, 0); mwin_hbox = gtk_hbox_new (TRUE, 5); gtk_box_pack_start (GTK_BOX (mwin_hbox), mwin_vbox_bottom_left, TRUE, TRUE, 5); gtk_box_pack_start (GTK_BOX (mwin_hbox), mwin_vbox_edit_entry, TRUE, TRUE, 5); gtk_box_pack_start (GTK_BOX (mwin_vbox_main), mwin_hbox, FALSE, FALSE, 0); gtk_widget_show (mwin_vbox_main); gtk_container_set_border_width (GTK_CONTAINER (mwin_vbox_main), 5); /* add those contents to the window */ gnome_app_set_contents(GNOME_APP(main_window), mwin_vbox_main); /* show all the widgets on the main window and the window itself */ gtk_widget_show_all (main_window); return 0; }