OSDN Git Service

LinGui: Add queue save/restore
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 6 Sep 2008 16:48:54 +0000 (16:48 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 6 Sep 2008 16:48:54 +0000 (16:48 +0000)
- 2 instances of libhb are used. One for queue activities and one for scanning
new sources prior to adding to the queue.
- Improve chapter entry usability. In addition to "return" advancing to the
next chapter for editing, up and down arrows will advance to prev/next and
put the cell in edit mode.
- Add an accelerator key to jump to the destination entry box.
- Fix a queue window resize problem.

git-svn-id: svn://localhost/HandBrake/trunk@1668 b64f7644-9d1e-0410-96f1-a4d463321fa5

17 files changed:
gtk/src/Makefile.am
gtk/src/callbacks.c
gtk/src/callbacks.h
gtk/src/ghb.ui
gtk/src/ghbcellrenderertext.c [new file with mode: 0644]
gtk/src/ghbcellrenderertext.h [new file with mode: 0644]
gtk/src/hb-backend.c
gtk/src/hb-backend.h
gtk/src/main.c
gtk/src/marshalers.c [new file with mode: 0644]
gtk/src/marshalers.h [new file with mode: 0644]
gtk/src/plist.c
gtk/src/plist.h
gtk/src/presets.c
gtk/src/presets.h
gtk/src/settings.c
gtk/src/settings.h

index 02eca57..2de9f74 100644 (file)
@@ -98,8 +98,12 @@ ghb_SOURCES = \
        hb-backend.h \
        renderer_button.h \
        renderer_button.c \
+       ghbcellrenderertext.c \
+       ghbcellrenderertext.h \
        ghb-dvd.c \
-       ghb-dvd.h 
+       ghb-dvd.h \
+       marshalers.c \
+       marshalers.h
 
 ghb_LDFLAGS = \
        -Wl,--export-dynamic
@@ -119,6 +123,8 @@ makewidgetdeps_LDADD = $(GHBTOOLS_LIBS)
 
 quotestring_SOURCES = preset_to_string.c
 
+callbacks.c: widget_deps.h widget_reverse_deps.h
+
 widget_deps.h: makewidgetdeps quotestring
        ./makewidgetdeps
        ./quotestring widget_deps widget_deps.h
@@ -127,12 +133,22 @@ widget_reverse_deps.h: makewidgetdeps quotestring
        ./makewidgetdeps
        ./quotestring widget_reverse_deps widget_reverse_deps.h
 
+presets.c: internal_defaults.h standard_presets.h
+
 internal_defaults.h: quotestring internal_defaults.xml
        ./quotestring internal_defaults.xml internal_defaults.h
 
 standard_presets.h: quotestring standard_presets.xml
        ./quotestring standard_presets.xml standard_presets.h
 
+ghbcellrenderertext.c: marshalers.h
+
+marshalers.h: marshalers.list
+       glib-genmarshal --prefix=ghb_marshal marshalers.list --header > marshalers.h
+
+marshalers.c: marshalers.list
+       glib-genmarshal --prefix=ghb_marshal marshalers.list --body > marshalers.c
+
 EXTRA_DIST = $(builder_DATA) $(icons) HandBrakeCLI
 
 uninstall-local:
index a051761..bd07e34 100644 (file)
@@ -21,6 +21,7 @@
 #include <sys/stat.h>
 #include <libhal-storage.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
 #include <glib/gstdio.h>
 #include <gio/gio.h>
 
@@ -31,6 +32,7 @@
 #include "plist.h"
 #include "hb-backend.h"
 #include "ghb-dvd.h"
+#include "ghbcellrenderertext.h"
 
 static void update_chapter_list(signal_user_data_t *ud);
 static void clear_audio_list(signal_user_data_t *ud);
@@ -261,7 +263,7 @@ expand_tilde(const gchar *path)
 void
 on_quit1_activate(GtkMenuItem *quit, signal_user_data_t *ud)
 {
-       gint state = ghb_get_state();
+       gint state = ghb_get_queue_state();
        g_debug("on_quit1_activate ()");
     if (state & GHB_STATE_WORKING)
     {
@@ -685,6 +687,43 @@ update_destination_extension(signal_user_data_t *ud)
        g_free(filename);
 }
 
+static void
+destination_select_title(GtkEntry *entry)
+{
+       const gchar *dest;
+       gint start, end;
+
+       dest = gtk_entry_get_text(entry);
+       for (end = strlen(dest)-1; end > 0; end--)
+       {
+               if (dest[end] == '.')
+               {
+                       break;
+               }
+       }
+       for (start = end; start >= 0; start--)
+       {
+               if (dest[start] == '/')
+               {
+                       start++;
+                       break;
+               }
+       }
+       if (start < end)
+       {
+               gtk_editable_select_region(GTK_EDITABLE(entry), start, end);
+       }
+}
+
+gboolean
+destination_grab_cb(
+       GtkEntry *entry, 
+       signal_user_data_t *ud)
+{
+       destination_select_title(entry);
+       return FALSE;
+}
+
 static gboolean update_default_destination = FALSE;
 
 void
@@ -757,7 +796,7 @@ window_destroy_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *
 gboolean
 window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *ud)
 {
-       gint state = ghb_get_state();
+       gint state = ghb_get_queue_state();
        g_debug("window_delete_event_cb ()");
     if (state & GHB_STATE_WORKING)
     {
@@ -2674,7 +2713,6 @@ static gboolean
 queue_add(signal_user_data_t *ud)
 {
        // Add settings to the queue
-       static gint unique_id = 0;
        GValue *settings;
        
        g_debug("queue_add ()");
@@ -2686,14 +2724,12 @@ queue_add(signal_user_data_t *ud)
                ud->queue = ghb_array_value_new(32);
        // Make a copy of current settings to be used for the new job
        settings = ghb_value_dup(ud->settings);
-       ghb_settings_set_int(settings, "job_unique_id", unique_id);
        ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING);
-
+       ghb_settings_set_int(settings, "job_unique_id", 0);
        ghb_array_append(ud->queue, settings);
        add_to_queue_list(ud, settings);
-       ghb_add_job (settings, unique_id);
+       ghb_save_queue(ud->queue);
 
-       unique_id++;
        return TRUE;
 }
 
@@ -2763,13 +2799,13 @@ queue_remove_clicked_cb(GtkWidget *widget, gchar *path, signal_user_data_t *ud)
                        {
                                return;
                        }
+                       unique_id = ghb_settings_get_int(settings, "job_unique_id");
+                       ghb_remove_job(unique_id);
                }
                // Remove the selected item
                gtk_tree_store_remove(GTK_TREE_STORE(store), &iter);
                // Remove the corresponding item from the queue list
-               unique_id = ghb_settings_get_int(settings, "job_unique_id");
                ghb_array_remove(ud->queue, row);
-               ghb_remove_job(unique_id);
        }
        else
        {       
@@ -2785,6 +2821,7 @@ find_queue_job(GValue *queue, gint unique_id, GValue **job)
        gint job_unique_id;
        
        *job = NULL;
+       g_debug("find_queue_job");
        count = ghb_array_len(queue);
        for (ii = 0; ii < count; ii++)
        {
@@ -2804,14 +2841,20 @@ queue_buttons_grey(signal_user_data_t *ud, gboolean working)
 {
        GtkWidget *widget;
        GtkAction *action;
-       gint titleindex = ghb_settings_get_int(ud->settings, "title");
-       gboolean title_ok = (titleindex >= 0);
+       gint queue_count;
+       gint titleindex;
+       gboolean title_ok;
+
+       queue_count = ghb_array_len(ud->queue);
+       titleindex = ghb_settings_get_int(ud->settings, "title");
+       title_ok = (titleindex >= 0);
+
        widget = GHB_WIDGET (ud->builder, "queue_start1");
-       gtk_widget_set_sensitive (widget, !working && title_ok);
+       gtk_widget_set_sensitive (widget, !working && (title_ok || queue_count));
        widget = GHB_WIDGET (ud->builder, "queue_start2");
-       gtk_widget_set_sensitive (widget, !working && title_ok);
+       gtk_widget_set_sensitive (widget, !working && (title_ok || queue_count));
        action = GHB_ACTION (ud->builder, "queue_start_menu");
-       gtk_action_set_sensitive (action, !working && title_ok);
+       gtk_action_set_sensitive (action, !working && (title_ok || queue_count));
        widget = GHB_WIDGET (ud->builder, "queue_pause1");
        gtk_widget_set_sensitive (widget, working);
        widget = GHB_WIDGET (ud->builder, "queue_pause2");
@@ -2827,6 +2870,97 @@ queue_buttons_grey(signal_user_data_t *ud, gboolean working)
 void queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud);
 
 static void
+submit_job(GValue *settings)
+{
+       static gint unique_id = 1;
+
+       g_debug("submit_job");
+       if (settings == NULL) return;
+       ghb_settings_set_int(settings, "job_unique_id", unique_id);
+       ghb_settings_set_int(settings, "job_status", GHB_QUEUE_RUNNING);
+       ghb_add_job (settings, unique_id);
+       ghb_start_queue();
+       unique_id++;
+}
+
+static void
+queue_scan(GValue *js)
+{
+       gchar *path;
+       gint titleindex;
+
+       path = ghb_settings_get_string( js, "source");
+       titleindex = ghb_settings_get_int(js, "title");
+       ghb_backend_queue_scan(path, titleindex+1);
+       g_free(path);
+}
+
+static GValue* 
+start_next_job(signal_user_data_t *ud, gboolean find_first)
+{
+       static gint current = 0;
+       gint count, ii, jj;
+       GValue *js;
+       gint status;
+
+       g_debug("start_next_job");
+       count = ghb_array_len(ud->queue);
+       if (find_first)
+       {       // Start the first pending item in the queue
+               current = 0;
+               for (ii = 0; ii < count; ii++)
+               {
+
+                       js = ghb_array_get_nth(ud->queue, ii);
+                       status = ghb_settings_get_int(js, "job_status");
+                       if (status == GHB_QUEUE_PENDING)
+                       {
+                               current = ii;
+                               queue_scan(js);
+                               return js;
+                       }
+               }
+               // Nothing pending
+               return NULL;
+       }
+       // Find the next pending item after the current running item
+       for (ii = 0; ii < count-1; ii++)
+       {
+               js = ghb_array_get_nth(ud->queue, ii);
+               status = ghb_settings_get_int(js, "job_status");
+               if (status == GHB_QUEUE_RUNNING)
+               {
+                       for (jj = ii+1; jj < count; jj++)
+                       {
+                               js = ghb_array_get_nth(ud->queue, jj);
+                               status = ghb_settings_get_int(js, "job_status");
+                               if (status == GHB_QUEUE_PENDING)
+                               {
+                                       current = jj;
+                                       queue_scan(js);
+                                       return js;
+                               }
+                       }
+               }
+       }
+       // No running item found? Maybe it was deleted
+       // Look for a pending item starting from the last index we started
+       for (ii = current; ii < count; ii++)
+       {
+               js = ghb_array_get_nth(ud->queue, ii);
+               status = ghb_settings_get_int(js, "job_status");
+               if (status == GHB_QUEUE_PENDING)
+               {
+                       current = ii;
+                       queue_scan(js);
+                       return js;
+               }
+       }
+       // Nothing found
+       return NULL;
+}
+
+static void
 ghb_backend_events(signal_user_data_t *ud)
 {
        ghb_status_t status;
@@ -2834,7 +2968,6 @@ ghb_backend_events(signal_user_data_t *ud)
        GtkProgressBar *progress;
        gint titleindex;
        GValue *js;
-       static gint current_id = -1;
        gint index;
        GtkTreeView *treeview;
        GtkTreeStore *store;
@@ -2845,6 +2978,8 @@ ghb_backend_events(signal_user_data_t *ud)
        ghb_track_status();
        ghb_get_status(&status);
        progress = GTK_PROGRESS_BAR(GHB_WIDGET (ud->builder, "progressbar"));
+       // First handle the status of title scans
+       // Then handle the status of the queue
        if (status.state & GHB_STATE_SCANNING)
        {
                status_str = g_strdup_printf ("Scanning title %d of %d...", 
@@ -2879,22 +3014,56 @@ ghb_backend_events(signal_user_data_t *ud)
                        gtk_progress_bar_set_text (progress, "No Source");
                }
                ghb_clear_state(GHB_STATE_SCANDONE);
-               queue_buttons_grey(ud, (0 != (status.state & GHB_STATE_WORKING)));
+               queue_buttons_grey(ud, (0 != (status.queue_state & GHB_STATE_WORKING)));
+       }
+       else if (status.queue_state & GHB_STATE_SCANNING)
+       {
+               status_str = g_strdup_printf ("Scanning ...");
+               gtk_progress_bar_set_text (progress, status_str);
+               g_free(status_str);
+               gtk_progress_bar_set_fraction (progress, 0);
        }
-       else if (status.state & GHB_STATE_PAUSED)
+       else if (status.queue_state & GHB_STATE_SCANDONE)
+       {
+               ghb_clear_queue_state(GHB_STATE_SCANDONE);
+               submit_job(ud->current_job);
+       }
+       else if (status.queue_state & GHB_STATE_PAUSED)
        {
                status_str = g_strdup_printf ("Paused"); 
                gtk_progress_bar_set_text (progress, status_str);
                g_free(status_str);
        }
-       else if (status.state & GHB_STATE_WORKING)
+       else if (status.queue_state & GHB_STATE_WORKING)
        {
+               gchar *task_str, *job_str;
+               gint qcount;
+
+               if (status.job_count > 1)
+               {
+                       task_str = g_strdup_printf("pass %d of %d, ", 
+                               status.job_cur, status.job_count);
+               }
+               else
+               {
+                       task_str = g_strdup("");
+               }
+               qcount = ghb_array_len(ud->queue);
+               if (qcount > 1)
+               {
+                       index = find_queue_job(ud->queue, status.unique_id, &js);
+                       job_str = g_strdup_printf("job %d of %d, ", index+1, qcount);
+               }
+               else
+               {
+                       job_str = g_strdup("");
+               }
                if(status.seconds > -1)
                {
                        status_str= g_strdup_printf(
-                               "Encoding: task %d of %d, %.2f %%"
+                               "Encoding: %s%s%.2f %%"
                                " (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)",
-                               status.job_cur, status.job_count, 
+                               job_str, task_str,
                                100.0 * status.progress,
                                status.rate_cur, status.rate_avg, status.hours, 
                                status.minutes, status.seconds );
@@ -2902,28 +3071,34 @@ ghb_backend_events(signal_user_data_t *ud)
                else
                {
                        status_str= g_strdup_printf(
-                               "Encoding: task %d of %d, %.2f %%",
-                               status.job_cur, status.job_count, 
+                               "Encoding: %s%s%.2f %%",
+                               job_str, task_str,
                                100.0 * status.progress );
                }
+               g_free(job_str);
+               g_free(task_str);
                gtk_progress_bar_set_text (progress, status_str);
                gtk_progress_bar_set_fraction (progress, status.progress);
                g_free(status_str);
        }
-       else if (status.state & GHB_STATE_WORKDONE)
+       else if (status.queue_state & GHB_STATE_WORKDONE)
        {
+               gint qstatus;
+
                work_started = FALSE;
                queue_buttons_grey(ud, FALSE);
-               index = find_queue_job(ud->queue, current_id, &js);
+               index = find_queue_job(ud->queue, status.unique_id, &js);
                treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
                store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
+               if (ud->cancel_encode)
+                       status.error = GHB_ERROR_CANCELED;
                switch( status.error )
                {
                        case GHB_ERROR_NONE:
                                gtk_progress_bar_set_text( progress, "Rip done!" );
+                               qstatus = GHB_QUEUE_DONE;
                                if (js != NULL)
                                {
-                                       ghb_settings_set_int(js, "job_status", GHB_QUEUE_DONE);
                                        gchar *path = g_strdup_printf ("%d", index);
                                        if (gtk_tree_model_get_iter_from_string(
                                                        GTK_TREE_MODEL(store), &iter, path))
@@ -2935,9 +3110,9 @@ ghb_backend_events(signal_user_data_t *ud)
                                break;
                        case GHB_ERROR_CANCELED:
                                gtk_progress_bar_set_text( progress, "Rip canceled." );
+                               qstatus = GHB_QUEUE_CANCELED;
                                if (js != NULL)
                                {
-                                       ghb_settings_set_int(js, "job_status", GHB_QUEUE_CANCELED);
                                        gchar *path = g_strdup_printf ("%d", index);
                                        if (gtk_tree_model_get_iter_from_string(
                                                        GTK_TREE_MODEL(store), &iter, path))
@@ -2949,9 +3124,9 @@ ghb_backend_events(signal_user_data_t *ud)
                                break;
                        default:
                                gtk_progress_bar_set_text( progress, "Rip failed.");
+                               qstatus = GHB_QUEUE_CANCELED;
                                if (js != NULL)
                                {
-                                       ghb_settings_set_int(js, "job_status", GHB_QUEUE_CANCELED);
                                        gchar *path = g_strdup_printf ("%d", index);
                                        if (gtk_tree_model_get_iter_from_string(
                                                        GTK_TREE_MODEL(store), &iter, path))
@@ -2961,49 +3136,29 @@ ghb_backend_events(signal_user_data_t *ud)
                                        g_free(path);
                                }
                }
-               current_id = -1;
                gtk_progress_bar_set_fraction (progress, 1.0);
-               ghb_clear_state(GHB_STATE_WORKDONE);
+               ghb_clear_queue_state(GHB_STATE_WORKDONE);
+               if (!ud->cancel_encode)
+                       ud->current_job = start_next_job(ud, FALSE);
+               else
+                       ud->current_job = NULL;
+               if (js)
+                       ghb_settings_set_int(js, "job_status", qstatus);
+               ghb_save_queue(ud->queue);
+               ud->cancel_encode = FALSE;
        }
-       else if (status.state & GHB_STATE_MUXING)
+       else if (status.queue_state & GHB_STATE_MUXING)
        {
                gtk_progress_bar_set_text(progress, "Muxing: this may take awhile...");
        }
-       if (status.state & GHB_STATE_WORKING)
+       if (status.queue_state & GHB_STATE_WORKING)
        {
                if (!work_started)
                {
                        work_started = TRUE;
                        queue_buttons_grey(ud, TRUE);
                }
-               if (status.unique_id != current_id)
-               {
-                       index = find_queue_job(ud->queue, current_id, &js);
-                       if (js != NULL)
-                       {
-                               ghb_settings_set_int(js, "job_status", GHB_QUEUE_DONE);
-                               treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list"));
-                               store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
-                               gchar *path = g_strdup_printf ("%d", index);
-                               if (gtk_tree_model_get_iter_from_string(
-                                               GTK_TREE_MODEL(store), &iter, path))
-                               {
-                                       gtk_tree_store_set(store, &iter, 0, "hb-complete", -1);
-                               }
-                               g_free(path);
-                       }
-
-                       index = find_queue_job(ud->queue, status.unique_id, &js);
-                       if (js != NULL)
-                       {
-                               ghb_settings_set_int(js, "job_status", GHB_QUEUE_RUNNING);
-                               current_id = status.unique_id;
-                       }
-               }
-               else
-               {
-                       index = find_queue_job(ud->queue, status.unique_id, &js);
-               }
+               index = find_queue_job(ud->queue, status.unique_id, &js);
                if (index >= 0)
                {
                        gchar working_icon[] = "hb-working0";
@@ -3293,38 +3448,32 @@ update_chapter_list(signal_user_data_t *ud)
        }
 }
 
-static GtkTreePath *nextPath = NULL;
-static gboolean chapter_selection_changed = FALSE;
+static gint chapter_edit_key = 0;
 
-static gboolean
-next_cell(signal_user_data_t *ud)
+gboolean
+chapter_keypress_cb(
+       GhbCellRendererText *cell,
+       GdkEventKey *event,
+       signal_user_data_t *ud)
 {
-       GtkTreeView *treeview;
-       GtkTreeViewColumn *column;
-
-       if (nextPath)
-       {
-               if (!chapter_selection_changed)
-               {
-                       treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
-                       column = gtk_tree_view_get_column(treeview, 1);
-                       gtk_tree_view_set_cursor(treeview, nextPath, column, TRUE);
-               }
-               gtk_tree_path_free(nextPath);
-               nextPath = NULL;
-       }
-       chapter_selection_changed = FALSE;
+       chapter_edit_key = event->keyval;
        return FALSE;
 }
 
 void
-chapter_edited_cb(GtkCellRendererText *cell, gchar *path, gchar *text, signal_user_data_t *ud)
+chapter_edited_cb(
+       GhbCellRendererText *cell, 
+       gchar *path, 
+       gchar *text, 
+       signal_user_data_t *ud)
 {
        GtkTreePath *treepath;
        GtkListStore *store;
        GtkTreeView *treeview;
        GtkTreeIter iter;
        gint index;
+       gint *pi;
+       gint row;
        
        g_debug("chapter_edited_cb ()");
        g_debug("path (%s)", path);
@@ -3332,8 +3481,9 @@ chapter_edited_cb(GtkCellRendererText *cell, gchar *path, gchar *text, signal_us
        treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "chapters_list"));
        store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
        treepath = gtk_tree_path_new_from_string (path);
+       pi = gtk_tree_path_get_indices(treepath);
+       row = pi[0];
        gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
-       gtk_tree_path_free (treepath);
        gtk_list_store_set(store, &iter, 
                1, text,
                2, TRUE,
@@ -3346,29 +3496,54 @@ chapter_edited_cb(GtkCellRendererText *cell, gchar *path, gchar *text, signal_us
        chapters = ghb_settings_get_value(ud->settings, "chapter_list");
        chapter = ghb_array_get_nth(chapters, index-1);
        g_value_set_string(chapter, text);
-       if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
+       if ((chapter_edit_key == GDK_Return || chapter_edit_key == GDK_Down) &&
+               gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter))
        {
-               nextPath = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
-               chapter_selection_changed = FALSE;
+               GtkTreeViewColumn *column;
+
+               gtk_tree_path_next(treepath);
                // When a cell has been edited, I want to advance to the
                // next cell and start editing it automaitcally.
                // Unfortunately, we may not be in a state here where
                // editing is allowed.  This happens when the user selects
                // a new cell with the mouse instead of just hitting enter.
                // Some kind of Gtk quirk.  widget_editable==NULL assertion.
-               // Editing is enabled again once the current event has been
+               // Editing is enabled again once the selection event has been
                // processed.  So I'm queueing up a callback to be called
                // when things go idle.  There, I will advance to the next
                // cell and initiate editing.
-               g_idle_add((GSourceFunc)next_cell, ud);
+               //
+               // Now, you might be asking why I don't catch the keypress
+               // event and determine what action to take based on that.
+               // The Gtk developers in their infinite wisdom have made the 
+               // actual GtkEdit widget being used a private member of
+               // GtkCellRendererText, so it can not be accessed to hang a
+               // signal handler off of.  And they also do not propagate the
+               // keypress signals in any other way.  So that information is lost.
+               //g_idle_add((GSourceFunc)next_cell, ud);
+               //
+               // Keeping the above comment for posterity.
+               // I got industrious and made my own CellTextRendererText that
+               // passes on the key-press-event. So now I have much better
+               // control of this.
+               column = gtk_tree_view_get_column(treeview, 1);
+               gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
+       }
+       else if (chapter_edit_key == GDK_Up && row > 0)
+       {
+               GtkTreeViewColumn *column;
+               gtk_tree_path_prev(treepath);
+               column = gtk_tree_view_get_column(treeview, 1);
+               gtk_tree_view_set_cursor(treeview, treepath, column, TRUE);
        }
+       gtk_tree_path_free (treepath);
 }
 
 void
 chapter_list_selection_changed_cb(GtkTreeSelection *selection, signal_user_data_t *ud)
 {
        g_debug("chapter_list_selection_changed_cb ()");
-       chapter_selection_changed = TRUE;
+       //chapter_selection_changed = TRUE;
 }
 
 void
@@ -3427,6 +3602,7 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
        gboolean running = FALSE;
        gint count, ii;
        gint status;
+       gint state;
 
        count = ghb_array_len(ud->queue);
        for (ii = 0; ii < count; ii++)
@@ -3447,12 +3623,18 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
                if (!queue_add(ud))
                        return;
        }
-       ghb_start_queue();
+       state = ghb_get_queue_state();
+       if (state == GHB_STATE_IDLE)
+       {
+               // Add the first pending queue item and start
+               ud->current_job = start_next_job(ud, TRUE);
+       }
 }
 
 void
 queue_stop_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud)
 {
+       ud->cancel_encode = TRUE;
        cancel_encode(NULL);
 }
 
@@ -3880,3 +4062,68 @@ easter_egg_cb(
        return FALSE;
 }
 
+gboolean
+ghb_reload_queue(signal_user_data_t *ud)
+{
+       GValue *queue;
+       gint unfinished = 0;
+       gint count, ii;
+       gint status;
+       GValue *settings;
+       gchar *message;
+
+       g_debug("ghb_reload_queue");
+       queue = ghb_load_queue();
+       // Look for unfinished entries
+       count = ghb_array_len(queue);
+       for (ii = 0; ii < count; ii++)
+       {
+               settings = ghb_array_get_nth(queue, ii);
+               status = ghb_settings_get_int(settings, "job_status");
+               if (status != GHB_QUEUE_DONE && status != GHB_QUEUE_CANCELED)
+               {
+                       unfinished++;
+               }
+       }
+       if (unfinished)
+       {
+               message = g_strdup_printf(
+                                       "You have %d unfinished jobs in a saved queue.\n\n"
+                                       "Would you like to reload them?",
+                                       unfinished);
+               if (ghb_message_dialog(GTK_MESSAGE_QUESTION, message, "No", "Yes"))
+               {
+                       GtkWidget *widget = GHB_WIDGET (ud->builder, "queue_window");
+                       gtk_widget_show (widget);
+
+                       ud->queue = queue;
+                       // First get rid of any old items we don't want
+                       for (ii = count-1; ii >= 0; ii--)
+                       {
+                               settings = ghb_array_get_nth(queue, ii);
+                               status = ghb_settings_get_int(settings, "job_status");
+                               if (status == GHB_QUEUE_DONE || status == GHB_QUEUE_CANCELED)
+                               {
+                                       ghb_array_remove(queue, ii);
+                               }
+                       }
+                       count = ghb_array_len(queue);
+                       for (ii = 0; ii < count; ii++)
+                       {
+                               settings = ghb_array_get_nth(queue, ii);
+                               ghb_settings_set_int(settings, "job_unique_id", 0);
+                               ghb_settings_set_int(settings, "job_status", GHB_QUEUE_PENDING);
+                               add_to_queue_list(ud, settings);
+                       }
+                       queue_buttons_grey(ud, FALSE);
+               }
+               else
+               {
+                       ghb_value_free(queue);
+                       ghb_remove_queue_file();
+               }
+               g_free(message);
+       }
+       return FALSE;
+}
+
index 652c6ae..6bb8d3a 100644 (file)
@@ -42,6 +42,7 @@ gboolean ghb_message_dialog(
        GtkMessageType type, const gchar *message, 
        const gchar *no, const gchar *yes);
 void ghb_init_dep_map();
+gboolean ghb_reload_queue(signal_user_data_t *ud);
 
 #endif // _CALLBACKS_H_
 
index 9377dc0..8f24a88 100644 (file)
                                     <property name="tooltip-text" translatable="yes">Destination path with file name for output.</property>
                                     <property name="width_chars">41</property>
                                     <signal handler="destination_entry_changed_cb" name="changed"/>
+                                    <signal handler="destination_grab_cb" name="grab-focus" after="yes"/>
+                                    <accelerator key="d" signal="grab-focus" modifiers="GDK_MOD1_MASK"/>
                                   </object>
                                   <packing>
                                     <property name="position">1</property>
                     <child type="label">
                       <object class="GtkLabel" id="label11">
                         <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Destination&lt;/b&gt;</property>
+                        <property name="label" translatable="yes">&lt;b&gt;&lt;u&gt;D&lt;/u&gt;estination&lt;/b&gt;</property>
                         <property name="use_markup">True</property>
                       </object>
                     </child>
@@ -3130,6 +3132,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                             <property name="headers_clickable">True</property>
                             <property name="rules_hint">True</property>
+                            <property name="enable-search">False</property>
                           </object>
                         </child>
                       </object>
@@ -3891,6 +3894,7 @@ this setting.</property>
           </object>
           <packing>
             <property name="position">1</property>
+            <property name="expand">False</property>
           </packing>
         </child>
         <child>
@@ -3914,6 +3918,7 @@ this setting.</property>
           </object>
           <packing>
             <property name="position">2</property>
+            <property name="expand">True</property>
           </packing>
         </child>
         <child>
diff --git a/gtk/src/ghbcellrenderertext.c b/gtk/src/ghbcellrenderertext.c
new file mode 100644 (file)
index 0000000..849cdd2
--- /dev/null
@@ -0,0 +1,1972 @@
+/* gtkcellrenderertext.c
+ * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <gtk/gtkmarshal.h>
+//#include <gtk/gtkeditable.h>
+//#include <gtk/gtkentry.h>
+//#include <gtk/gtkintl.h>
+//#include <gtk/gtkprivate.h>
+//#include <gtk/gtktreeprivate.h>
+//#include <gtk/gtkalias.h>
+
+#include "marshalers.h"
+#include "ghbcellrenderertext.h"
+
+#ifdef ENABLE_NLS
+#define P_(String) dgettext(GETTEXT_PACKAGE "-properties",String)
+#else
+#define P_(String) (String)
+#endif
+
+#define I_(string) g_intern_static_string (string)
+
+#define GTK_PARAM_READABLE G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
+#define GTK_PARAM_WRITABLE G_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
+#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
+
+
+
+static void ghb_cell_renderer_text_finalize   (GObject                  *object);
+
+static void ghb_cell_renderer_text_get_property  (GObject                  *object,
+                                                 guint                     param_id,
+                                                 GValue                   *value,
+                                                 GParamSpec               *pspec);
+static void ghb_cell_renderer_text_set_property  (GObject                  *object,
+                                                 guint                     param_id,
+                                                 const GValue             *value,
+                                                 GParamSpec               *pspec);
+static void ghb_cell_renderer_text_get_size   (GtkCellRenderer          *cell,
+                                              GtkWidget                *widget,
+                                              GdkRectangle             *cell_area,
+                                              gint                     *x_offset,
+                                              gint                     *y_offset,
+                                              gint                     *width,
+                                              gint                     *height);
+static void ghb_cell_renderer_text_render     (GtkCellRenderer          *cell,
+                                              GdkWindow                *window,
+                                              GtkWidget                *widget,
+                                              GdkRectangle             *background_area,
+                                              GdkRectangle             *cell_area,
+                                              GdkRectangle             *expose_area,
+                                              GtkCellRendererState      flags);
+
+static GtkCellEditable *ghb_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
+                                                             GdkEvent             *event,
+                                                             GtkWidget            *widget,
+                                                             const gchar          *path,
+                                                             GdkRectangle         *background_area,
+                                                             GdkRectangle         *cell_area,
+                                                             GtkCellRendererState  flags);
+
+enum {
+  EDITED,
+  KEYPRESS,
+  LAST_SIGNAL
+};
+
+enum {
+  PROP_0,
+
+  PROP_TEXT,
+  PROP_MARKUP,
+  PROP_ATTRIBUTES,
+  PROP_SINGLE_PARAGRAPH_MODE,
+  PROP_WIDTH_CHARS,
+  PROP_WRAP_WIDTH,
+  PROP_ALIGN,
+  
+  /* Style args */
+  PROP_BACKGROUND,
+  PROP_FOREGROUND,
+  PROP_BACKGROUND_GDK,
+  PROP_FOREGROUND_GDK,
+  PROP_FONT,
+  PROP_FONT_DESC,
+  PROP_FAMILY,
+  PROP_STYLE,
+  PROP_VARIANT,
+  PROP_WEIGHT,
+  PROP_STRETCH,
+  PROP_SIZE,
+  PROP_SIZE_POINTS,
+  PROP_SCALE,
+  PROP_EDITABLE,
+  PROP_STRIKETHROUGH,
+  PROP_UNDERLINE,
+  PROP_RISE,
+  PROP_LANGUAGE,
+  PROP_ELLIPSIZE,
+  PROP_WRAP_MODE,
+  
+  /* Whether-a-style-arg-is-set args */
+  PROP_BACKGROUND_SET,
+  PROP_FOREGROUND_SET,
+  PROP_FAMILY_SET,
+  PROP_STYLE_SET,
+  PROP_VARIANT_SET,
+  PROP_WEIGHT_SET,
+  PROP_STRETCH_SET,
+  PROP_SIZE_SET,
+  PROP_SCALE_SET,
+  PROP_EDITABLE_SET,
+  PROP_STRIKETHROUGH_SET,
+  PROP_UNDERLINE_SET,
+  PROP_RISE_SET,
+  PROP_LANGUAGE_SET,
+  PROP_ELLIPSIZE_SET,
+  PROP_ALIGN_SET
+};
+
+static guint text_cell_renderer_signals [LAST_SIGNAL];
+
+#define GHB_CELL_RENDERER_TEXT_PATH "gtk-cell-renderer-text-path"
+
+#define GHB_CELL_RENDERER_TEXT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GHB_TYPE_CELL_RENDERER_TEXT, GhbCellRendererTextPrivate))
+
+typedef struct _GhbCellRendererTextPrivate GhbCellRendererTextPrivate;
+struct _GhbCellRendererTextPrivate
+{
+  guint single_paragraph : 1;
+  guint language_set : 1;
+  guint markup_set : 1;
+  guint ellipsize_set : 1;
+  guint align_set : 1;
+  
+  gulong focus_out_id;
+  PangoLanguage *language;
+  PangoEllipsizeMode ellipsize;
+  PangoWrapMode wrap_mode;
+  PangoAlignment align;
+  
+  gulong populate_popup_id;
+  gulong entry_menu_popdown_timeout;
+  gboolean in_entry_menu;
+  
+  gint width_chars;
+  gint wrap_width;
+  
+  GtkWidget *entry;
+};
+
+G_DEFINE_TYPE (GhbCellRendererText, ghb_cell_renderer_text, GTK_TYPE_CELL_RENDERER)
+
+static void
+ghb_cell_renderer_text_init (GhbCellRendererText *celltext)
+{
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (celltext);
+
+  GTK_CELL_RENDERER (celltext)->xalign = 0.0;
+  GTK_CELL_RENDERER (celltext)->yalign = 0.5;
+  GTK_CELL_RENDERER (celltext)->xpad = 2;
+  GTK_CELL_RENDERER (celltext)->ypad = 2;
+  celltext->font_scale = 1.0;
+  celltext->fixed_height_rows = -1;
+  celltext->font = pango_font_description_new ();
+
+  priv->width_chars = -1;
+  priv->wrap_width = -1;
+  priv->wrap_mode = PANGO_WRAP_CHAR;
+  priv->align = PANGO_ALIGN_LEFT;
+  priv->align_set = FALSE;
+}
+
+static void
+ghb_cell_renderer_text_class_init (GhbCellRendererTextClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+
+  object_class->finalize = ghb_cell_renderer_text_finalize;
+  
+  object_class->get_property = ghb_cell_renderer_text_get_property;
+  object_class->set_property = ghb_cell_renderer_text_set_property;
+
+  cell_class->get_size = ghb_cell_renderer_text_get_size;
+  cell_class->render = ghb_cell_renderer_text_render;
+  cell_class->start_editing = ghb_cell_renderer_text_start_editing;
+
+  g_object_class_install_property (object_class,
+                                   PROP_TEXT,
+                                   g_param_spec_string ("text",
+                                                        P_("Text"),
+                                                        P_("Text to render"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+  
+  g_object_class_install_property (object_class,
+                                   PROP_MARKUP,
+                                   g_param_spec_string ("markup",
+                                                        P_("Markup"),
+                                                        P_("Marked up text to render"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  g_object_class_install_property (object_class,
+                                  PROP_ATTRIBUTES,
+                                  g_param_spec_boxed ("attributes",
+                                                      P_("Attributes"),
+                                                      P_("A list of style attributes to apply to the text of the renderer"),
+                                                      PANGO_TYPE_ATTR_LIST,
+                                                      GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_SINGLE_PARAGRAPH_MODE,
+                                   g_param_spec_boolean ("single-paragraph-mode",
+                                                         P_("Single Paragraph Mode"),
+                                                         P_("Whether or not to keep all text in a single paragraph"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  
+  g_object_class_install_property (object_class,
+                                   PROP_BACKGROUND,
+                                   g_param_spec_string ("background",
+                                                        P_("Background color name"),
+                                                        P_("Background color as a string"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_BACKGROUND_GDK,
+                                   g_param_spec_boxed ("background-gdk",
+                                                       P_("Background color"),
+                                                       P_("Background color as a GdkColor"),
+                                                       GDK_TYPE_COLOR,
+                                                       GTK_PARAM_READWRITE));  
+
+  g_object_class_install_property (object_class,
+                                   PROP_FOREGROUND,
+                                   g_param_spec_string ("foreground",
+                                                        P_("Foreground color name"),
+                                                        P_("Foreground color as a string"),
+                                                        NULL,
+                                                        GTK_PARAM_WRITABLE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_FOREGROUND_GDK,
+                                   g_param_spec_boxed ("foreground-gdk",
+                                                       P_("Foreground color"),
+                                                       P_("Foreground color as a GdkColor"),
+                                                       GDK_TYPE_COLOR,
+                                                       GTK_PARAM_READWRITE));
+
+
+  g_object_class_install_property (object_class,
+                                   PROP_EDITABLE,
+                                   g_param_spec_boolean ("editable",
+                                                         P_("Editable"),
+                                                         P_("Whether the text can be modified by the user"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_FONT,
+                                   g_param_spec_string ("font",
+                                                        P_("Font"),
+                                                        P_("Font description as a string, e.g. \"Sans Italic 12\""),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_FONT_DESC,
+                                   g_param_spec_boxed ("font-desc",
+                                                       P_("Font"),
+                                                       P_("Font description as a PangoFontDescription struct"),
+                                                       PANGO_TYPE_FONT_DESCRIPTION,
+                                                       GTK_PARAM_READWRITE));
+
+  
+  g_object_class_install_property (object_class,
+                                   PROP_FAMILY,
+                                   g_param_spec_string ("family",
+                                                        P_("Font family"),
+                                                        P_("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_STYLE,
+                                   g_param_spec_enum ("style",
+                                                      P_("Font style"),
+                                                      P_("Font style"),
+                                                      PANGO_TYPE_STYLE,
+                                                      PANGO_STYLE_NORMAL,
+                                                      GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_VARIANT,
+                                   g_param_spec_enum ("variant",
+                                                     P_("Font variant"),
+                                                     P_("Font variant"),
+                                                      PANGO_TYPE_VARIANT,
+                                                      PANGO_VARIANT_NORMAL,
+                                                      GTK_PARAM_READWRITE));
+  
+  g_object_class_install_property (object_class,
+                                   PROP_WEIGHT,
+                                   g_param_spec_int ("weight",
+                                                     P_("Font weight"),
+                                                     P_("Font weight"),
+                                                     0,
+                                                     G_MAXINT,
+                                                     PANGO_WEIGHT_NORMAL,
+                                                     GTK_PARAM_READWRITE));
+
+   g_object_class_install_property (object_class,
+                                   PROP_STRETCH,
+                                   g_param_spec_enum ("stretch",
+                                                      P_("Font stretch"),
+                                                      P_("Font stretch"),
+                                                      PANGO_TYPE_STRETCH,
+                                                      PANGO_STRETCH_NORMAL,
+                                                      GTK_PARAM_READWRITE));
+  
+  g_object_class_install_property (object_class,
+                                   PROP_SIZE,
+                                   g_param_spec_int ("size",
+                                                     P_("Font size"),
+                                                     P_("Font size"),
+                                                     0,
+                                                     G_MAXINT,
+                                                     0,
+                                                     GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_SIZE_POINTS,
+                                   g_param_spec_double ("size-points",
+                                                        P_("Font points"),
+                                                        P_("Font size in points"),
+                                                        0.0,
+                                                        G_MAXDOUBLE,
+                                                        0.0,
+                                                        GTK_PARAM_READWRITE));  
+
+  g_object_class_install_property (object_class,
+                                   PROP_SCALE,
+                                   g_param_spec_double ("scale",
+                                                        P_("Font scale"),
+                                                        P_("Font scaling factor"),
+                                                        0.0,
+                                                        G_MAXDOUBLE,
+                                                        1.0,
+                                                        GTK_PARAM_READWRITE));
+  
+  g_object_class_install_property (object_class,
+                                   PROP_RISE,
+                                   g_param_spec_int ("rise",
+                                                     P_("Rise"),
+                                                     P_("Offset of text above the baseline "
+                                                       "(below the baseline if rise is negative)"),
+                                                     -G_MAXINT,
+                                                     G_MAXINT,
+                                                     0,
+                                                     GTK_PARAM_READWRITE));
+
+
+  g_object_class_install_property (object_class,
+                                   PROP_STRIKETHROUGH,
+                                   g_param_spec_boolean ("strikethrough",
+                                                         P_("Strikethrough"),
+                                                         P_("Whether to strike through the text"),
+                                                         FALSE,
+                                                         GTK_PARAM_READWRITE));
+  
+  g_object_class_install_property (object_class,
+                                   PROP_UNDERLINE,
+                                   g_param_spec_enum ("underline",
+                                                      P_("Underline"),
+                                                      P_("Style of underline for this text"),
+                                                      PANGO_TYPE_UNDERLINE,
+                                                      PANGO_UNDERLINE_NONE,
+                                                      GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_LANGUAGE,
+                                   g_param_spec_string ("language",
+                                                        P_("Language"),
+                                                        P_("The language this text is in, as an ISO code. "
+                                                          "Pango can use this as a hint when rendering the text. "
+                                                          "If you don't understand this parameter, you probably don't need it"),
+                                                        NULL,
+                                                        GTK_PARAM_READWRITE));
+
+
+  /**
+   * GhbCellRendererText:ellipsize:
+   *
+   * Specifies the preferred place to ellipsize the string, if the cell renderer 
+   * does not have enough room to display the entire string. Setting it to 
+   * %PANGO_ELLIPSIZE_NONE turns off ellipsizing. See the wrap-width property
+   * for another way of making the text fit into a given width.
+   *
+   * Since: 2.6
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_ELLIPSIZE,
+                                   g_param_spec_enum ("ellipsize",
+                                                     P_("Ellipsize"),
+                                                     P_("The preferred place to ellipsize the string, "
+                                                        "if the cell renderer does not have enough room "
+                                                        "to display the entire string"),
+                                                     PANGO_TYPE_ELLIPSIZE_MODE,
+                                                     PANGO_ELLIPSIZE_NONE,
+                                                     GTK_PARAM_READWRITE));
+
+  /**
+   * GhbCellRendererText:width-chars:
+   * 
+   * The desired width of the cell, in characters. If this property is set to
+   * -1, the width will be calculated automatically, otherwise the cell will
+   * request either 3 characters or the property value, whichever is greater.
+   * 
+   * Since: 2.6
+   **/
+  g_object_class_install_property (object_class,
+                                   PROP_WIDTH_CHARS,
+                                   g_param_spec_int ("width-chars",
+                                                     P_("Width In Characters"),
+                                                     P_("The desired width of the label, in characters"),
+                                                     -1,
+                                                     G_MAXINT,
+                                                     -1,
+                                                     GTK_PARAM_READWRITE));
+  
+  /**
+   * GhbCellRendererText:wrap-mode:
+   *
+   * Specifies how to break the string into multiple lines, if the cell 
+   * renderer does not have enough room to display the entire string. 
+   * This property has no effect unless the wrap-width property is set.
+   *
+   * Since: 2.8
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_WRAP_MODE,
+                                   g_param_spec_enum ("wrap-mode",
+                                                     P_("Wrap mode"),
+                                                     P_("How to break the string into multiple lines, "
+                                                        "if the cell renderer does not have enough room "
+                                                        "to display the entire string"),
+                                                     PANGO_TYPE_WRAP_MODE,
+                                                     PANGO_WRAP_CHAR,
+                                                     GTK_PARAM_READWRITE));
+
+  /**
+   * GhbCellRendererText:wrap-width:
+   *
+   * Specifies the width at which the text is wrapped. The wrap-mode property can 
+   * be used to influence at what character positions the line breaks can be placed.
+   * Setting wrap-width to -1 turns wrapping off.
+   *
+   * Since: 2.8
+   */
+  g_object_class_install_property (object_class,
+                                  PROP_WRAP_WIDTH,
+                                  g_param_spec_int ("wrap-width",
+                                                    P_("Wrap width"),
+                                                    P_("The width at which the text is wrapped"),
+                                                    -1,
+                                                    G_MAXINT,
+                                                    -1,
+                                                    GTK_PARAM_READWRITE));
+
+  /**
+   * GhbCellRendererText:alignment:
+   *
+   * Specifies how to align the lines of text with respect to each other. 
+   *
+   * Note that this property describes how to align the lines of text in 
+   * case there are several of them. The "xalign" property of #GtkCellRenderer, 
+   * on the other hand, sets the horizontal alignment of the whole text.
+   *
+   * Since: 2.10
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_ALIGN,
+                                   g_param_spec_enum ("alignment",
+                                                     P_("Alignment"),
+                                                     P_("How to align the lines"),
+                                                     PANGO_TYPE_ALIGNMENT,
+                                                     PANGO_ALIGN_LEFT,
+                                                     GTK_PARAM_READWRITE));
+  
+  /* Style props are set or not */
+
+#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
+
+  ADD_SET_PROP ("background-set", PROP_BACKGROUND_SET,
+                P_("Background set"),
+                P_("Whether this tag affects the background color"));
+
+  ADD_SET_PROP ("foreground-set", PROP_FOREGROUND_SET,
+                P_("Foreground set"),
+                P_("Whether this tag affects the foreground color"));
+  
+  ADD_SET_PROP ("editable-set", PROP_EDITABLE_SET,
+                P_("Editability set"),
+                P_("Whether this tag affects text editability"));
+
+  ADD_SET_PROP ("family-set", PROP_FAMILY_SET,
+                P_("Font family set"),
+                P_("Whether this tag affects the font family"));  
+
+  ADD_SET_PROP ("style-set", PROP_STYLE_SET,
+                P_("Font style set"),
+                P_("Whether this tag affects the font style"));
+
+  ADD_SET_PROP ("variant-set", PROP_VARIANT_SET,
+                P_("Font variant set"),
+                P_("Whether this tag affects the font variant"));
+
+  ADD_SET_PROP ("weight-set", PROP_WEIGHT_SET,
+                P_("Font weight set"),
+                P_("Whether this tag affects the font weight"));
+
+  ADD_SET_PROP ("stretch-set", PROP_STRETCH_SET,
+                P_("Font stretch set"),
+                P_("Whether this tag affects the font stretch"));
+
+  ADD_SET_PROP ("size-set", PROP_SIZE_SET,
+                P_("Font size set"),
+                P_("Whether this tag affects the font size"));
+
+  ADD_SET_PROP ("scale-set", PROP_SCALE_SET,
+                P_("Font scale set"),
+                P_("Whether this tag scales the font size by a factor"));
+  
+  ADD_SET_PROP ("rise-set", PROP_RISE_SET,
+                P_("Rise set"),
+                P_("Whether this tag affects the rise"));
+
+  ADD_SET_PROP ("strikethrough-set", PROP_STRIKETHROUGH_SET,
+                P_("Strikethrough set"),
+                P_("Whether this tag affects strikethrough"));
+
+  ADD_SET_PROP ("underline-set", PROP_UNDERLINE_SET,
+                P_("Underline set"),
+                P_("Whether this tag affects underlining"));
+
+  ADD_SET_PROP ("language-set", PROP_LANGUAGE_SET,
+                P_("Language set"),
+                P_("Whether this tag affects the language the text is rendered as"));
+
+  ADD_SET_PROP ("ellipsize-set", PROP_ELLIPSIZE_SET,
+                P_("Ellipsize set"),
+                P_("Whether this tag affects the ellipsize mode"));
+
+  ADD_SET_PROP ("align-set", PROP_ALIGN_SET,
+                P_("Align set"),
+                P_("Whether this tag affects the alignment mode"));
+
+  /**
+   * GhbCellRendererText::edited
+   * @renderer: the object which received the signal
+   * @path: the path identifying the edited cell
+   * @new_text: the new text
+   *
+   * This signal is emitted after @renderer has been edited.
+   *
+   * It is the responsibility of the application to update the model
+   * and store @new_text at the position indicated by @path.
+   */
+  text_cell_renderer_signals [EDITED] =
+    g_signal_new (I_("edited"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GhbCellRendererTextClass, edited),
+                 NULL, NULL,
+                 ghb_marshal_VOID__STRING_STRING,
+                 G_TYPE_NONE, 2,
+                 G_TYPE_STRING,
+                 G_TYPE_STRING);
+
+  text_cell_renderer_signals [KEYPRESS] =
+    g_signal_new (I_("key-press-event"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GhbCellRendererTextClass, keypress),
+                 NULL, NULL,
+                 ghb_marshal_BOOLEAN__BOXED,
+                 G_TYPE_BOOLEAN, 1,
+                 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+  g_type_class_add_private (object_class, sizeof (GhbCellRendererTextPrivate));
+}
+
+static void
+ghb_cell_renderer_text_finalize (GObject *object)
+{
+  GhbCellRendererText *celltext = GHB_CELL_RENDERER_TEXT (object);
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (object);
+
+  pango_font_description_free (celltext->font);
+
+  g_free (celltext->text);
+
+  if (celltext->extra_attrs)
+    pango_attr_list_unref (celltext->extra_attrs);
+
+  if (priv->language)
+    g_object_unref (priv->language);
+
+  (* G_OBJECT_CLASS (ghb_cell_renderer_text_parent_class)->finalize) (object);
+}
+
+static PangoFontMask
+get_property_font_set_mask (guint prop_id)
+{
+  switch (prop_id)
+    {
+    case PROP_FAMILY_SET:
+      return PANGO_FONT_MASK_FAMILY;
+    case PROP_STYLE_SET:
+      return PANGO_FONT_MASK_STYLE;
+    case PROP_VARIANT_SET:
+      return PANGO_FONT_MASK_VARIANT;
+    case PROP_WEIGHT_SET:
+      return PANGO_FONT_MASK_WEIGHT;
+    case PROP_STRETCH_SET:
+      return PANGO_FONT_MASK_STRETCH;
+    case PROP_SIZE_SET:
+      return PANGO_FONT_MASK_SIZE;
+    }
+
+  return 0;
+}
+
+static void
+ghb_cell_renderer_text_get_property (GObject        *object,
+                                    guint           param_id,
+                                    GValue         *value,
+                                    GParamSpec     *pspec)
+{
+  GhbCellRendererText *celltext = GHB_CELL_RENDERER_TEXT (object);
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (object);
+
+  switch (param_id)
+    {
+    case PROP_TEXT:
+      g_value_set_string (value, celltext->text);
+      break;
+
+    case PROP_ATTRIBUTES:
+      g_value_set_boxed (value, celltext->extra_attrs);
+      break;
+
+    case PROP_SINGLE_PARAGRAPH_MODE:
+      g_value_set_boolean (value, priv->single_paragraph);
+      break;
+
+    case PROP_BACKGROUND_GDK:
+      {
+        GdkColor color;
+        
+        color.red = celltext->background.red;
+        color.green = celltext->background.green;
+        color.blue = celltext->background.blue;
+        
+        g_value_set_boxed (value, &color);
+      }
+      break;
+
+    case PROP_FOREGROUND_GDK:
+      {
+        GdkColor color;
+        
+        color.red = celltext->foreground.red;
+        color.green = celltext->foreground.green;
+        color.blue = celltext->foreground.blue;
+        
+        g_value_set_boxed (value, &color);
+      }
+      break;
+
+    case PROP_FONT:
+        g_value_take_string (value, pango_font_description_to_string (celltext->font));
+      break;
+      
+    case PROP_FONT_DESC:
+      g_value_set_boxed (value, celltext->font);
+      break;
+
+    case PROP_FAMILY:
+      g_value_set_string (value, pango_font_description_get_family (celltext->font));
+      break;
+
+    case PROP_STYLE:
+      g_value_set_enum (value, pango_font_description_get_style (celltext->font));
+      break;
+
+    case PROP_VARIANT:
+      g_value_set_enum (value, pango_font_description_get_variant (celltext->font));
+      break;
+
+    case PROP_WEIGHT:
+      g_value_set_int (value, pango_font_description_get_weight (celltext->font));
+      break;
+
+    case PROP_STRETCH:
+      g_value_set_enum (value, pango_font_description_get_stretch (celltext->font));
+      break;
+
+    case PROP_SIZE:
+      g_value_set_int (value, pango_font_description_get_size (celltext->font));
+      break;
+
+    case PROP_SIZE_POINTS:
+      g_value_set_double (value, ((double)pango_font_description_get_size (celltext->font)) / (double)PANGO_SCALE);
+      break;
+
+    case PROP_SCALE:
+      g_value_set_double (value, celltext->font_scale);
+      break;
+      
+    case PROP_EDITABLE:
+      g_value_set_boolean (value, celltext->editable);
+      break;
+
+    case PROP_STRIKETHROUGH:
+      g_value_set_boolean (value, celltext->strikethrough);
+      break;
+
+    case PROP_UNDERLINE:
+      g_value_set_enum (value, celltext->underline_style);
+      break;
+
+    case PROP_RISE:
+      g_value_set_int (value, celltext->rise);
+      break;  
+
+    case PROP_LANGUAGE:
+      g_value_set_static_string (value, pango_language_to_string (priv->language));
+      break;
+
+    case PROP_ELLIPSIZE:
+      g_value_set_enum (value, priv->ellipsize);
+      break;
+      
+    case PROP_WRAP_MODE:
+      g_value_set_enum (value, priv->wrap_mode);
+      break;
+
+    case PROP_WRAP_WIDTH:
+      g_value_set_int (value, priv->wrap_width);
+      break;
+      
+    case PROP_ALIGN:
+      g_value_set_enum (value, priv->align);
+      break;
+
+    case PROP_BACKGROUND_SET:
+      g_value_set_boolean (value, celltext->background_set);
+      break;
+
+    case PROP_FOREGROUND_SET:
+      g_value_set_boolean (value, celltext->foreground_set);
+      break;
+
+    case PROP_FAMILY_SET:
+    case PROP_STYLE_SET:
+    case PROP_VARIANT_SET:
+    case PROP_WEIGHT_SET:
+    case PROP_STRETCH_SET:
+    case PROP_SIZE_SET:
+      {
+       PangoFontMask mask = get_property_font_set_mask (param_id);
+       g_value_set_boolean (value, (pango_font_description_get_set_fields (celltext->font) & mask) != 0);
+       
+       break;
+      }
+
+    case PROP_SCALE_SET:
+      g_value_set_boolean (value, celltext->scale_set);
+      break;
+      
+    case PROP_EDITABLE_SET:
+      g_value_set_boolean (value, celltext->editable_set);
+      break;
+
+    case PROP_STRIKETHROUGH_SET:
+      g_value_set_boolean (value, celltext->strikethrough_set);
+      break;
+
+    case PROP_UNDERLINE_SET:
+      g_value_set_boolean (value, celltext->underline_set);
+      break;
+
+    case  PROP_RISE_SET:
+      g_value_set_boolean (value, celltext->rise_set);
+      break;
+
+    case PROP_LANGUAGE_SET:
+      g_value_set_boolean (value, priv->language_set);
+      break;
+
+    case PROP_ELLIPSIZE_SET:
+      g_value_set_boolean (value, priv->ellipsize_set);
+      break;
+
+    case PROP_ALIGN_SET:
+      g_value_set_boolean (value, priv->align_set);
+      break;
+      
+    case PROP_WIDTH_CHARS:
+      g_value_set_int (value, priv->width_chars);
+      break;  
+
+    case PROP_BACKGROUND:
+    case PROP_FOREGROUND:
+    case PROP_MARKUP:
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+
+static void
+set_bg_color (GhbCellRendererText *celltext,
+              GdkColor            *color)
+{
+  if (color)
+    {
+      if (!celltext->background_set)
+        {
+          celltext->background_set = TRUE;
+          g_object_notify (G_OBJECT (celltext), "background-set");
+        }
+      
+      celltext->background.red = color->red;
+      celltext->background.green = color->green;
+      celltext->background.blue = color->blue;
+    }
+  else
+    {
+      if (celltext->background_set)
+        {
+          celltext->background_set = FALSE;
+          g_object_notify (G_OBJECT (celltext), "background-set");
+        }
+    }
+}
+
+
+static void
+set_fg_color (GhbCellRendererText *celltext,
+              GdkColor            *color)
+{
+  if (color)
+    {
+      if (!celltext->foreground_set)
+        {
+          celltext->foreground_set = TRUE;
+          g_object_notify (G_OBJECT (celltext), "foreground-set");
+        }
+      
+      celltext->foreground.red = color->red;
+      celltext->foreground.green = color->green;
+      celltext->foreground.blue = color->blue;
+    }
+  else
+    {
+      if (celltext->foreground_set)
+        {
+          celltext->foreground_set = FALSE;
+          g_object_notify (G_OBJECT (celltext), "foreground-set");
+        }
+    }
+}
+
+static PangoFontMask
+set_font_desc_fields (PangoFontDescription *desc,
+                     PangoFontMask         to_set)
+{
+  PangoFontMask changed_mask = 0;
+  
+  if (to_set & PANGO_FONT_MASK_FAMILY)
+    {
+      const char *family = pango_font_description_get_family (desc);
+      if (!family)
+       {
+         family = "sans";
+         changed_mask |= PANGO_FONT_MASK_FAMILY;
+       }
+
+      pango_font_description_set_family (desc, family);
+    }
+  if (to_set & PANGO_FONT_MASK_STYLE)
+    pango_font_description_set_style (desc, pango_font_description_get_style (desc));
+  if (to_set & PANGO_FONT_MASK_VARIANT)
+    pango_font_description_set_variant (desc, pango_font_description_get_variant (desc));
+  if (to_set & PANGO_FONT_MASK_WEIGHT)
+    pango_font_description_set_weight (desc, pango_font_description_get_weight (desc));
+  if (to_set & PANGO_FONT_MASK_STRETCH)
+    pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc));
+  if (to_set & PANGO_FONT_MASK_SIZE)
+    {
+      gint size = pango_font_description_get_size (desc);
+      if (size <= 0)
+       {
+         size = 10 * PANGO_SCALE;
+         changed_mask |= PANGO_FONT_MASK_SIZE;
+       }
+      
+      pango_font_description_set_size (desc, size);
+    }
+
+  return changed_mask;
+}
+
+static void
+notify_set_changed (GObject       *object,
+                   PangoFontMask  changed_mask)
+{
+  if (changed_mask & PANGO_FONT_MASK_FAMILY)
+    g_object_notify (object, "family-set");
+  if (changed_mask & PANGO_FONT_MASK_STYLE)
+    g_object_notify (object, "style-set");
+  if (changed_mask & PANGO_FONT_MASK_VARIANT)
+    g_object_notify (object, "variant-set");
+  if (changed_mask & PANGO_FONT_MASK_WEIGHT)
+    g_object_notify (object, "weight-set");
+  if (changed_mask & PANGO_FONT_MASK_STRETCH)
+    g_object_notify (object, "stretch-set");
+  if (changed_mask & PANGO_FONT_MASK_SIZE)
+    g_object_notify (object, "size-set");
+}
+
+static void
+notify_fields_changed (GObject       *object,
+                      PangoFontMask  changed_mask)
+{
+  if (changed_mask & PANGO_FONT_MASK_FAMILY)
+    g_object_notify (object, "family");
+  if (changed_mask & PANGO_FONT_MASK_STYLE)
+    g_object_notify (object, "style");
+  if (changed_mask & PANGO_FONT_MASK_VARIANT)
+    g_object_notify (object, "variant");
+  if (changed_mask & PANGO_FONT_MASK_WEIGHT)
+    g_object_notify (object, "weight");
+  if (changed_mask & PANGO_FONT_MASK_STRETCH)
+    g_object_notify (object, "stretch");
+  if (changed_mask & PANGO_FONT_MASK_SIZE)
+    g_object_notify (object, "size");
+}
+
+static void
+set_font_description (GhbCellRendererText  *celltext,
+                      PangoFontDescription *font_desc)
+{
+  GObject *object = G_OBJECT (celltext);
+  PangoFontDescription *new_font_desc;
+  PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
+  
+  if (font_desc)
+    new_font_desc = pango_font_description_copy (font_desc);
+  else
+    new_font_desc = pango_font_description_new ();
+
+  old_mask = pango_font_description_get_set_fields (celltext->font);
+  new_mask = pango_font_description_get_set_fields (new_font_desc);
+
+  changed_mask = old_mask | new_mask;
+  set_changed_mask = old_mask ^ new_mask;
+
+  pango_font_description_free (celltext->font);
+  celltext->font = new_font_desc;
+  
+  g_object_freeze_notify (object);
+
+  g_object_notify (object, "font-desc");
+  g_object_notify (object, "font");
+  
+  if (changed_mask & PANGO_FONT_MASK_FAMILY)
+    g_object_notify (object, "family");
+  if (changed_mask & PANGO_FONT_MASK_STYLE)
+    g_object_notify (object, "style");
+  if (changed_mask & PANGO_FONT_MASK_VARIANT)
+    g_object_notify (object, "variant");
+  if (changed_mask & PANGO_FONT_MASK_WEIGHT)
+    g_object_notify (object, "weight");
+  if (changed_mask & PANGO_FONT_MASK_STRETCH)
+    g_object_notify (object, "stretch");
+  if (changed_mask & PANGO_FONT_MASK_SIZE)
+    {
+      g_object_notify (object, "size");
+      g_object_notify (object, "size-points");
+    }
+
+  notify_set_changed (object, set_changed_mask);
+  
+  g_object_thaw_notify (object);
+}
+
+static void
+ghb_cell_renderer_text_set_property (GObject      *object,
+                                    guint         param_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+  GhbCellRendererText *celltext = GHB_CELL_RENDERER_TEXT (object);
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (object);
+
+  switch (param_id)
+    {
+    case PROP_TEXT:
+      g_free (celltext->text);
+
+      if (priv->markup_set)
+        {
+          if (celltext->extra_attrs)
+            pango_attr_list_unref (celltext->extra_attrs);
+          celltext->extra_attrs = NULL;
+          priv->markup_set = FALSE;
+        }
+
+      celltext->text = g_strdup (g_value_get_string (value));
+      g_object_notify (object, "text");
+      break;
+
+    case PROP_ATTRIBUTES:
+      if (celltext->extra_attrs)
+       pango_attr_list_unref (celltext->extra_attrs);
+
+      celltext->extra_attrs = g_value_get_boxed (value);
+      if (celltext->extra_attrs)
+        pango_attr_list_ref (celltext->extra_attrs);
+      break;
+    case PROP_MARKUP:
+      {
+       const gchar *str;
+       gchar *text = NULL;
+       GError *error = NULL;
+       PangoAttrList *attrs = NULL;
+
+       str = g_value_get_string (value);
+       if (str && !pango_parse_markup (str,
+                                       -1,
+                                       0,
+                                       &attrs,
+                                       &text,
+                                       NULL,
+                                       &error))
+         {
+           g_warning ("Failed to set text from markup due to error parsing markup: %s",
+                      error->message);
+           g_error_free (error);
+           return;
+         }
+
+       g_free (celltext->text);
+
+       if (celltext->extra_attrs)
+         pango_attr_list_unref (celltext->extra_attrs);
+
+       celltext->text = text;
+       celltext->extra_attrs = attrs;
+        priv->markup_set = TRUE;
+      }
+      break;
+
+    case PROP_SINGLE_PARAGRAPH_MODE:
+      priv->single_paragraph = g_value_get_boolean (value);
+      break;
+      
+    case PROP_BACKGROUND:
+      {
+        GdkColor color;
+
+        if (!g_value_get_string (value))
+          set_bg_color (celltext, NULL);       /* reset to background_set to FALSE */
+        else if (gdk_color_parse (g_value_get_string (value), &color))
+          set_bg_color (celltext, &color);
+        else
+          g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+        g_object_notify (object, "background-gdk");
+      }
+      break;
+      
+    case PROP_FOREGROUND:
+      {
+        GdkColor color;
+
+        if (!g_value_get_string (value))
+          set_fg_color (celltext, NULL);       /* reset to foreground_set to FALSE */
+        else if (gdk_color_parse (g_value_get_string (value), &color))
+          set_fg_color (celltext, &color);
+        else
+          g_warning ("Don't know color `%s'", g_value_get_string (value));
+
+        g_object_notify (object, "foreground-gdk");
+      }
+      break;
+
+    case PROP_BACKGROUND_GDK:
+      /* This notifies the GObject itself. */
+      set_bg_color (celltext, g_value_get_boxed (value));
+      break;
+
+    case PROP_FOREGROUND_GDK:
+      /* This notifies the GObject itself. */
+      set_fg_color (celltext, g_value_get_boxed (value));
+      break;
+
+    case PROP_FONT:
+      {
+        PangoFontDescription *font_desc = NULL;
+        const gchar *name;
+
+        name = g_value_get_string (value);
+
+        if (name)
+          font_desc = pango_font_description_from_string (name);
+
+        set_font_description (celltext, font_desc);
+
+       pango_font_description_free (font_desc);
+        
+       if (celltext->fixed_height_rows != -1)
+         celltext->calc_fixed_height = TRUE;
+      }
+      break;
+
+    case PROP_FONT_DESC:
+      set_font_description (celltext, g_value_get_boxed (value));
+      
+      if (celltext->fixed_height_rows != -1)
+       celltext->calc_fixed_height = TRUE;
+      break;
+
+    case PROP_FAMILY:
+    case PROP_STYLE:
+    case PROP_VARIANT:
+    case PROP_WEIGHT:
+    case PROP_STRETCH:
+    case PROP_SIZE:
+    case PROP_SIZE_POINTS:
+      {
+       PangoFontMask old_set_mask = pango_font_description_get_set_fields (celltext->font);
+       
+       switch (param_id)
+         {
+         case PROP_FAMILY:
+           pango_font_description_set_family (celltext->font,
+                                              g_value_get_string (value));
+           break;
+         case PROP_STYLE:
+           pango_font_description_set_style (celltext->font,
+                                             g_value_get_enum (value));
+           break;
+         case PROP_VARIANT:
+           pango_font_description_set_variant (celltext->font,
+                                               g_value_get_enum (value));
+           break;
+         case PROP_WEIGHT:
+           pango_font_description_set_weight (celltext->font,
+                                              g_value_get_int (value));
+           break;
+         case PROP_STRETCH:
+           pango_font_description_set_stretch (celltext->font,
+                                               g_value_get_enum (value));
+           break;
+         case PROP_SIZE:
+           pango_font_description_set_size (celltext->font,
+                                            g_value_get_int (value));
+           g_object_notify (object, "size-points");
+           break;
+         case PROP_SIZE_POINTS:
+           pango_font_description_set_size (celltext->font,
+                                            g_value_get_double (value) * PANGO_SCALE);
+           g_object_notify (object, "size");
+           break;
+         }
+       
+       if (celltext->fixed_height_rows != -1)
+         celltext->calc_fixed_height = TRUE;
+       
+       notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (celltext->font));
+       g_object_notify (object, "font-desc");
+       g_object_notify (object, "font");
+
+       break;
+      }
+      
+    case PROP_SCALE:
+      celltext->font_scale = g_value_get_double (value);
+      celltext->scale_set = TRUE;
+      if (celltext->fixed_height_rows != -1)
+       celltext->calc_fixed_height = TRUE;
+      g_object_notify (object, "scale-set");
+      break;
+      
+    case PROP_EDITABLE:
+      celltext->editable = g_value_get_boolean (value);
+      celltext->editable_set = TRUE;
+      if (celltext->editable)
+        GTK_CELL_RENDERER (celltext)->mode = GTK_CELL_RENDERER_MODE_EDITABLE;
+      else
+        GTK_CELL_RENDERER (celltext)->mode = GTK_CELL_RENDERER_MODE_INERT;
+      g_object_notify (object, "editable-set");
+      break;
+
+    case PROP_STRIKETHROUGH:
+      celltext->strikethrough = g_value_get_boolean (value);
+      celltext->strikethrough_set = TRUE;
+      g_object_notify (object, "strikethrough-set");
+      break;
+
+    case PROP_UNDERLINE:
+      celltext->underline_style = g_value_get_enum (value);
+      celltext->underline_set = TRUE;
+      g_object_notify (object, "underline-set");
+            
+      break;
+
+    case PROP_RISE:
+      celltext->rise = g_value_get_int (value);
+      celltext->rise_set = TRUE;
+      g_object_notify (object, "rise-set");
+      if (celltext->fixed_height_rows != -1)
+       celltext->calc_fixed_height = TRUE;
+      break;  
+
+    case PROP_LANGUAGE:
+      priv->language_set = TRUE;
+      if (priv->language)
+        g_object_unref (priv->language);
+      priv->language = pango_language_from_string (g_value_get_string (value));
+      g_object_notify (object, "language-set");
+      break;
+
+    case PROP_ELLIPSIZE:
+      priv->ellipsize = g_value_get_enum (value);
+      priv->ellipsize_set = TRUE;
+      g_object_notify (object, "ellipsize-set");
+      break;
+      
+    case PROP_WRAP_MODE:
+      priv->wrap_mode = g_value_get_enum (value);
+      break;
+      
+    case PROP_WRAP_WIDTH:
+      priv->wrap_width = g_value_get_int (value);
+      break;
+            
+    case PROP_WIDTH_CHARS:
+      priv->width_chars = g_value_get_int (value);
+      break;  
+
+    case PROP_ALIGN:
+      priv->align = g_value_get_enum (value);
+      priv->align_set = TRUE;
+      g_object_notify (object, "align-set");
+      break;
+
+    case PROP_BACKGROUND_SET:
+      celltext->background_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_FOREGROUND_SET:
+      celltext->foreground_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_FAMILY_SET:
+    case PROP_STYLE_SET:
+    case PROP_VARIANT_SET:
+    case PROP_WEIGHT_SET:
+    case PROP_STRETCH_SET:
+    case PROP_SIZE_SET:
+      if (!g_value_get_boolean (value))
+       {
+         pango_font_description_unset_fields (celltext->font,
+                                              get_property_font_set_mask (param_id));
+       }
+      else
+       {
+         PangoFontMask changed_mask;
+         
+         changed_mask = set_font_desc_fields (celltext->font,
+                                              get_property_font_set_mask (param_id));
+         notify_fields_changed (G_OBJECT (celltext), changed_mask);
+       }
+      break;
+
+    case PROP_SCALE_SET:
+      celltext->scale_set = g_value_get_boolean (value);
+      break;
+      
+    case PROP_EDITABLE_SET:
+      celltext->editable_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_STRIKETHROUGH_SET:
+      celltext->strikethrough_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_UNDERLINE_SET:
+      celltext->underline_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_RISE_SET:
+      celltext->rise_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_LANGUAGE_SET:
+      priv->language_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_ELLIPSIZE_SET:
+      priv->ellipsize_set = g_value_get_boolean (value);
+      break;
+
+    case PROP_ALIGN_SET:
+      priv->align_set = g_value_get_boolean (value);
+      break;
+      
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+/**
+ * ghb_cell_renderer_text_new:
+ * 
+ * Creates a new #GhbCellRendererText. Adjust how text is drawn using
+ * object properties. Object properties can be
+ * set globally (with g_object_set()). Also, with #GtkTreeViewColumn,
+ * you can bind a property to a value in a #GtkTreeModel. For example,
+ * you can bind the "text" property on the cell renderer to a string
+ * value in the model, thus rendering a different string in each row
+ * of the #GtkTreeView
+ * 
+ * Return value: the new cell renderer
+ **/
+GtkCellRenderer *
+ghb_cell_renderer_text_new (void)
+{
+  return g_object_new (GHB_TYPE_CELL_RENDERER_TEXT, NULL);
+}
+
+static void
+add_attr (PangoAttrList  *attr_list,
+          PangoAttribute *attr)
+{
+  attr->start_index = 0;
+  attr->end_index = G_MAXINT;
+  
+  pango_attr_list_insert (attr_list, attr);
+}
+
+static PangoLayout*
+get_layout (GhbCellRendererText *celltext,
+            GtkWidget           *widget,
+            gboolean             will_render,
+            GtkCellRendererState flags)
+{
+  PangoAttrList *attr_list;
+  PangoLayout *layout;
+  PangoUnderline uline;
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (celltext);
+  
+  layout = gtk_widget_create_pango_layout (widget, celltext->text);
+
+  if (celltext->extra_attrs)
+    attr_list = pango_attr_list_copy (celltext->extra_attrs);
+  else
+    attr_list = pango_attr_list_new ();
+
+  pango_layout_set_single_paragraph_mode (layout, priv->single_paragraph);
+
+  if (will_render)
+    {
+      /* Add options that affect appearance but not size */
+      
+      /* note that background doesn't go here, since it affects
+       * background_area not the PangoLayout area
+       */
+      
+      if (celltext->foreground_set
+         && (flags & GTK_CELL_RENDERER_SELECTED) == 0)
+        {
+          PangoColor color;
+
+          color = celltext->foreground;
+          
+          add_attr (attr_list,
+                    pango_attr_foreground_new (color.red, color.green, color.blue));
+        }
+
+      if (celltext->strikethrough_set)
+        add_attr (attr_list,
+                  pango_attr_strikethrough_new (celltext->strikethrough));
+    }
+
+  add_attr (attr_list, pango_attr_font_desc_new (celltext->font));
+
+  if (celltext->scale_set &&
+      celltext->font_scale != 1.0)
+    add_attr (attr_list, pango_attr_scale_new (celltext->font_scale));
+  
+  if (celltext->underline_set)
+    uline = celltext->underline_style;
+  else
+    uline = PANGO_UNDERLINE_NONE;
+
+  if (priv->language_set)
+    add_attr (attr_list, pango_attr_language_new (priv->language));
+  
+  if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT)
+    {
+      switch (uline)
+        {
+        case PANGO_UNDERLINE_NONE:
+          uline = PANGO_UNDERLINE_SINGLE;
+          break;
+
+        case PANGO_UNDERLINE_SINGLE:
+          uline = PANGO_UNDERLINE_DOUBLE;
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  if (uline != PANGO_UNDERLINE_NONE)
+    add_attr (attr_list, pango_attr_underline_new (celltext->underline_style));
+
+  if (celltext->rise_set)
+    add_attr (attr_list, pango_attr_rise_new (celltext->rise));
+
+  if (priv->ellipsize_set)
+    pango_layout_set_ellipsize (layout, priv->ellipsize);
+  else
+    pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE);
+
+  if (priv->wrap_width != -1)
+    {
+      pango_layout_set_width (layout, priv->wrap_width * PANGO_SCALE);
+      pango_layout_set_wrap (layout, priv->wrap_mode);
+    }
+  else
+    {
+      pango_layout_set_width (layout, -1);
+      pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
+    }
+
+  if (priv->align_set)
+    pango_layout_set_alignment (layout, priv->align);
+  else
+    {
+      PangoAlignment align;
+
+      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+       align = PANGO_ALIGN_RIGHT;
+      else
+       align = PANGO_ALIGN_LEFT;
+
+      pango_layout_set_alignment (layout, align);
+    }
+
+  pango_layout_set_attributes (layout, attr_list);
+
+  pango_attr_list_unref (attr_list);
+  
+  return layout;
+}
+
+static void
+get_size (GtkCellRenderer *cell,
+         GtkWidget       *widget,
+         GdkRectangle    *cell_area,
+         PangoLayout     *layout,
+         gint            *x_offset,
+         gint            *y_offset,
+         gint            *width,
+         gint            *height)
+{
+  GhbCellRendererText *celltext = (GhbCellRendererText *) cell;
+  PangoRectangle rect;
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (cell);
+
+  if (celltext->calc_fixed_height)
+    {
+      PangoContext *context;
+      PangoFontMetrics *metrics;
+      PangoFontDescription *font_desc;
+      gint row_height;
+
+      font_desc = pango_font_description_copy_static (widget->style->font_desc);
+      pango_font_description_merge_static (font_desc, celltext->font, TRUE);
+
+      if (celltext->scale_set)
+       pango_font_description_set_size (font_desc,
+                                        celltext->font_scale * pango_font_description_get_size (font_desc));
+
+      context = gtk_widget_get_pango_context (widget);
+
+      metrics = pango_context_get_metrics (context,
+                                          font_desc,
+                                          pango_context_get_language (context));
+      row_height = (pango_font_metrics_get_ascent (metrics) +
+                   pango_font_metrics_get_descent (metrics));
+      pango_font_metrics_unref (metrics);
+
+      pango_font_description_free (font_desc);
+
+      gtk_cell_renderer_set_fixed_size (cell,
+                                       cell->width, 2*cell->ypad +
+                                       celltext->fixed_height_rows * PANGO_PIXELS (row_height));
+      
+      if (height)
+       {
+         *height = cell->height;
+         height = NULL;
+       }
+      celltext->calc_fixed_height = FALSE;
+      if (width == NULL)
+       return;
+    }
+  
+  if (layout)
+    g_object_ref (layout);
+  else
+    layout = get_layout (celltext, widget, FALSE, 0);
+
+  pango_layout_get_extents (layout, NULL, &rect);
+  pango_extents_to_pixels (&rect, NULL);
+
+  if (height)
+    *height = cell->ypad * 2 + rect.height;
+
+  /* The minimum size for ellipsized labels is ~ 3 chars */
+  if (width)
+    {
+      if (priv->ellipsize || priv->width_chars > 0)
+       {
+         PangoContext *context;
+         PangoFontMetrics *metrics;
+         gint char_width;
+
+         context = pango_layout_get_context (layout);
+         metrics = pango_context_get_metrics (context, widget->style->font_desc, pango_context_get_language (context));
+
+         char_width = pango_font_metrics_get_approximate_char_width (metrics);
+         pango_font_metrics_unref (metrics);
+         
+         *width = cell->xpad * 2 + (PANGO_PIXELS (char_width) * MAX (priv->width_chars, 3));
+       }
+      else
+       {
+         *width = cell->xpad * 2 + rect.x + rect.width;
+       }         
+    }
+
+  if (cell_area)
+    {
+      if (x_offset)
+       {
+         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+           *x_offset = (1.0 - cell->xalign) * (cell_area->width - (rect.x + rect.width + (2 * cell->xpad)));
+         else 
+           *x_offset = cell->xalign * (cell_area->width - (rect.x + rect.width + (2 * cell->xpad)));
+
+         if ((priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE) || priv->wrap_width != -1)
+           *x_offset = MAX(*x_offset, 0);
+       }
+      if (y_offset)
+       {
+         *y_offset = cell->yalign * (cell_area->height - (rect.height + (2 * cell->ypad)));
+         *y_offset = MAX (*y_offset, 0);
+       }
+    }
+  else
+    {
+      if (x_offset) *x_offset = 0;
+      if (y_offset) *y_offset = 0;
+    }
+
+  g_object_unref (layout);
+}
+
+
+static void
+ghb_cell_renderer_text_get_size (GtkCellRenderer *cell,
+                                GtkWidget       *widget,
+                                GdkRectangle    *cell_area,
+                                gint            *x_offset,
+                                gint            *y_offset,
+                                gint            *width,
+                                gint            *height)
+{
+  get_size (cell, widget, cell_area, NULL,
+           x_offset, y_offset, width, height);
+}
+
+static void
+ghb_cell_renderer_text_render (GtkCellRenderer      *cell,
+                              GdkDrawable          *window,
+                              GtkWidget            *widget,
+                              GdkRectangle         *background_area,
+                              GdkRectangle         *cell_area,
+                              GdkRectangle         *expose_area,
+                              GtkCellRendererState  flags)
+
+{
+  GhbCellRendererText *celltext = (GhbCellRendererText *) cell;
+  PangoLayout *layout;
+  GtkStateType state;
+  gint x_offset;
+  gint y_offset;
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (cell);
+
+  layout = get_layout (celltext, widget, TRUE, flags);
+  get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, NULL, NULL);
+
+  if (!cell->sensitive) 
+    {
+      state = GTK_STATE_INSENSITIVE;
+    }
+  else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
+    {
+      if (GTK_WIDGET_HAS_FOCUS (widget))
+       state = GTK_STATE_SELECTED;
+      else
+       state = GTK_STATE_ACTIVE;
+    }
+  else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT &&
+          GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT)
+    {
+      state = GTK_STATE_PRELIGHT;
+    }
+  else
+    {
+      if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE)
+       state = GTK_STATE_INSENSITIVE;
+      else
+       state = GTK_STATE_NORMAL;
+    }
+
+  if (celltext->background_set && 
+      (flags & GTK_CELL_RENDERER_SELECTED) == 0)
+    {
+      cairo_t *cr = gdk_cairo_create (window);
+
+      if (expose_area)
+       {
+         gdk_cairo_rectangle (cr, expose_area);
+         cairo_clip (cr);
+       }
+
+      gdk_cairo_rectangle (cr, background_area);
+      cairo_set_source_rgb (cr,
+                           celltext->background.red / 65535.,
+                           celltext->background.green / 65535.,
+                           celltext->background.blue / 65535.);
+      cairo_fill (cr);
+      
+      cairo_destroy (cr);
+    }
+
+  if (priv->ellipsize_set && priv->ellipsize != PANGO_ELLIPSIZE_NONE)
+    pango_layout_set_width (layout, 
+                           (cell_area->width - x_offset - 2 * cell->xpad) * PANGO_SCALE);
+  else if (priv->wrap_width == -1)
+    pango_layout_set_width (layout, -1);
+
+  gtk_paint_layout (widget->style,
+                    window,
+                    state,
+                   TRUE,
+                    expose_area,
+                    widget,
+                    "cellrenderertext",
+                    cell_area->x + x_offset + cell->xpad,
+                    cell_area->y + y_offset + cell->ypad,
+                    layout);
+
+  g_object_unref (layout);
+}
+
+static gboolean
+ghb_cell_renderer_text_keypress(
+       GtkCellEditable *entry,
+       GdkEventKey *event,
+       gpointer data)
+{
+       gboolean result;
+       g_signal_emit(
+               data, text_cell_renderer_signals[KEYPRESS], 0, event, &result);
+       return result;
+}
+
+static void
+ghb_cell_renderer_text_editing_done (GtkCellEditable *entry,
+                                    gpointer         data)
+{
+  const gchar *path;
+  const gchar *new_text;
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (data);
+
+  priv->entry = NULL;
+
+  if (priv->focus_out_id > 0)
+    {
+      g_signal_handler_disconnect (entry, priv->focus_out_id);
+      priv->focus_out_id = 0;
+    }
+
+  if (priv->populate_popup_id > 0)
+    {
+      g_signal_handler_disconnect (entry, priv->populate_popup_id);
+      priv->populate_popup_id = 0;
+    }
+
+  if (priv->entry_menu_popdown_timeout)
+    {
+      g_source_remove (priv->entry_menu_popdown_timeout);
+      priv->entry_menu_popdown_timeout = 0;
+    }
+
+  gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (data), 
+                                 GTK_ENTRY (entry)->editing_canceled);
+  if (GTK_ENTRY (entry)->editing_canceled)
+    return;
+
+  path = g_object_get_data (G_OBJECT (entry), GHB_CELL_RENDERER_TEXT_PATH);
+  new_text = gtk_entry_get_text (GTK_ENTRY (entry));
+
+  g_signal_emit (data, text_cell_renderer_signals[EDITED], 0, path, new_text);
+}
+
+static gboolean
+popdown_timeout (gpointer data)
+{
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (data);
+
+  priv->entry_menu_popdown_timeout = 0;
+
+  if (!GTK_WIDGET_HAS_FOCUS (priv->entry))
+    ghb_cell_renderer_text_editing_done (GTK_CELL_EDITABLE (priv->entry), data);
+
+  return FALSE;
+}
+
+static void
+ghb_cell_renderer_text_popup_unmap (GtkMenu *menu,
+                                    gpointer data)
+{
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (data);
+
+  priv->in_entry_menu = FALSE;
+
+  if (priv->entry_menu_popdown_timeout)
+    return;
+
+  priv->entry_menu_popdown_timeout = gdk_threads_add_timeout (500, popdown_timeout,
+                                                    data);
+}
+
+static void
+ghb_cell_renderer_text_populate_popup (GtkEntry *entry,
+                                       GtkMenu  *menu,
+                                       gpointer  data)
+{
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (data);
+
+  if (priv->entry_menu_popdown_timeout)
+    {
+      g_source_remove (priv->entry_menu_popdown_timeout);
+      priv->entry_menu_popdown_timeout = 0;
+    }
+
+  priv->in_entry_menu = TRUE;
+
+  g_signal_connect (menu, "unmap",
+                    G_CALLBACK (ghb_cell_renderer_text_popup_unmap), data);
+}
+
+static gboolean
+ghb_cell_renderer_text_focus_out_event (GtkWidget *entry,
+                                       GdkEvent  *event,
+                                       gpointer   data)
+{
+  GhbCellRendererTextPrivate *priv;
+
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (data);
+
+  if (priv->in_entry_menu)
+    return FALSE;
+
+  GTK_ENTRY (entry)->editing_canceled = TRUE;
+  gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (entry));
+  gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (entry));
+
+  /* entry needs focus-out-event */
+  return FALSE;
+}
+
+static GtkCellEditable *
+ghb_cell_renderer_text_start_editing (GtkCellRenderer      *cell,
+                                     GdkEvent             *event,
+                                     GtkWidget            *widget,
+                                     const gchar          *path,
+                                     GdkRectangle         *background_area,
+                                     GdkRectangle         *cell_area,
+                                     GtkCellRendererState  flags)
+{
+  GtkRequisition requisition;
+  GhbCellRendererText *celltext;
+  GhbCellRendererTextPrivate *priv;
+
+  celltext = GHB_CELL_RENDERER_TEXT (cell);
+  priv = GHB_CELL_RENDERER_TEXT_GET_PRIVATE (cell);
+
+  /* If the cell isn't editable we return NULL. */
+  if (celltext->editable == FALSE)
+    return NULL;
+
+  priv->entry = g_object_new (GTK_TYPE_ENTRY,
+                             "has-frame", FALSE,
+                             "xalign", cell->xalign,
+                             NULL);
+
+  if (celltext->text)
+    gtk_entry_set_text (GTK_ENTRY (priv->entry), celltext->text);
+  g_object_set_data_full (G_OBJECT (priv->entry), I_(GHB_CELL_RENDERER_TEXT_PATH), g_strdup (path), g_free);
+  
+  gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
+  
+  gtk_widget_size_request (priv->entry, &requisition);
+  if (requisition.height < cell_area->height)
+    {
+      GtkBorder *style_border;
+      GtkBorder border;
+
+      gtk_widget_style_get (priv->entry,
+                           "inner-border", &style_border,
+                           NULL);
+
+      if (style_border)
+        {
+         border = *style_border;
+         g_boxed_free (GTK_TYPE_BORDER, style_border);
+       }
+      else
+        {
+         /* Since boxed style properties can't have default values ... */
+         border.left = 2;
+         border.right = 2;
+       }
+
+      border.top = (cell_area->height - requisition.height) / 2;
+      border.bottom = (cell_area->height - requisition.height) / 2;
+      gtk_entry_set_inner_border (GTK_ENTRY (priv->entry), &border);
+    }
+
+  priv->in_entry_menu = FALSE;
+  if (priv->entry_menu_popdown_timeout)
+    {
+      g_source_remove (priv->entry_menu_popdown_timeout);
+      priv->entry_menu_popdown_timeout = 0;
+    }
+
+  g_signal_connect (priv->entry,
+                   "key-press-event",
+                   G_CALLBACK (ghb_cell_renderer_text_keypress),
+                   celltext);
+  g_signal_connect (priv->entry,
+                   "editing_done",
+                   G_CALLBACK (ghb_cell_renderer_text_editing_done),
+                   celltext);
+  priv->focus_out_id = g_signal_connect_after (priv->entry, "focus_out_event",
+                                              G_CALLBACK (ghb_cell_renderer_text_focus_out_event),
+                                              celltext);
+  priv->populate_popup_id =
+    g_signal_connect (priv->entry, "populate_popup",
+                      G_CALLBACK (ghb_cell_renderer_text_populate_popup),
+                      celltext);
+  gtk_widget_show (priv->entry);
+
+  return GTK_CELL_EDITABLE (priv->entry);
+}
+
+/**
+ * ghb_cell_renderer_text_set_fixed_height_from_font:
+ * @renderer: A #GhbCellRendererText
+ * @number_of_rows: Number of rows of text each cell renderer is allocated, or -1
+ * 
+ * Sets the height of a renderer to explicitly be determined by the "font" and
+ * "y_pad" property set on it.  Further changes in these properties do not
+ * affect the height, so they must be accompanied by a subsequent call to this
+ * function.  Using this function is unflexible, and should really only be used
+ * if calculating the size of a cell is too slow (ie, a massive number of cells
+ * displayed).  If @number_of_rows is -1, then the fixed height is unset, and
+ * the height is determined by the properties again.
+ **/
+void
+ghb_cell_renderer_text_set_fixed_height_from_font (GhbCellRendererText *renderer,
+                                                  gint                 number_of_rows)
+{
+  g_return_if_fail (GHB_IS_CELL_RENDERER_TEXT (renderer));
+  g_return_if_fail (number_of_rows == -1 || number_of_rows > 0);
+
+  if (number_of_rows == -1)
+    {
+      gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (renderer),
+                                       GTK_CELL_RENDERER (renderer)->width,
+                                       -1);
+    }
+  else
+    {
+      renderer->fixed_height_rows = number_of_rows;
+      renderer->calc_fixed_height = TRUE;
+    }
+}
+
diff --git a/gtk/src/ghbcellrenderertext.h b/gtk/src/ghbcellrenderertext.h
new file mode 100644 (file)
index 0000000..0e12ba1
--- /dev/null
@@ -0,0 +1,105 @@
+/* gtkcellrenderertext.h
+ * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GHB_CELL_RENDERER_TEXT_H__
+#define __GHB_CELL_RENDERER_TEXT_H__
+
+#include <pango/pango.h>
+#include <gtk/gtkcellrenderer.h>
+
+
+G_BEGIN_DECLS
+
+
+#define GHB_TYPE_CELL_RENDERER_TEXT            (ghb_cell_renderer_text_get_type ())
+#define GHB_CELL_RENDERER_TEXT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GHB_TYPE_CELL_RENDERER_TEXT, GhbCellRendererText))
+#define GHB_CELL_RENDERER_TEXT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GHB_TYPE_CELL_RENDERER_TEXT, GhbCellRendererTextClass))
+#define GHB_IS_CELL_RENDERER_TEXT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GHB_TYPE_CELL_RENDERER_TEXT))
+#define GHB_IS_CELL_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GHB_TYPE_CELL_RENDERER_TEXT))
+#define GHB_CELL_RENDERER_TEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GHB_TYPE_CELL_RENDERER_TEXT, GhbCellRendererTextClass))
+
+typedef struct _GhbCellRendererText      GhbCellRendererText;
+typedef struct _GhbCellRendererTextClass GhbCellRendererTextClass;
+
+struct _GhbCellRendererText
+{
+  GtkCellRenderer parent;
+
+  /*< private >*/
+  gchar *text;
+  PangoFontDescription *font;
+  gdouble font_scale;
+  PangoColor foreground;
+  PangoColor background;
+  
+  PangoAttrList *extra_attrs;
+
+  PangoUnderline underline_style;
+
+  gint rise;
+  gint fixed_height_rows;
+
+  guint strikethrough : 1;
+
+  guint editable  : 1;
+
+  guint scale_set : 1;
+  
+  guint foreground_set : 1;
+  guint background_set : 1;
+  
+  guint underline_set : 1;
+
+  guint rise_set : 1;
+  
+  guint strikethrough_set : 1;
+
+  guint editable_set : 1;
+  guint calc_fixed_height : 1;
+};
+
+struct _GhbCellRendererTextClass
+{
+  GtkCellRendererClass parent_class;
+
+  void (* edited) (GhbCellRendererText *cell_renderer_text,
+                  const gchar         *path,
+                  const gchar         *new_text);
+
+  gboolean (* keypress) (GhbCellRendererText *cell_renderer_text,
+                  GdkEventKey *event);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+GType            ghb_cell_renderer_text_get_type (void) G_GNUC_CONST;
+GtkCellRenderer *ghb_cell_renderer_text_new      (void);
+
+void             ghb_cell_renderer_text_set_fixed_height_from_font (GhbCellRendererText *renderer,
+                                                                   gint                 number_of_rows);
+
+
+G_END_DECLS
+
+
+#endif /* __GHB_CELL_RENDERER_TEXT_H__ */
index 7edeb4c..eb60ad9 100644 (file)
@@ -46,7 +46,6 @@ typedef struct
 {
        gint count;
        options_map_t *map;
-       gint *grey_options;
 } combo_opts_t;
 
 static options_map_t d_container_opts[] =
@@ -445,21 +444,120 @@ ghb_vquality_range(signal_user_data_t *ud, gint *min, gint *max)
 }
 
 gint
+ghb_lookup_vrate(const GValue *vrate)
+{
+       gint ii;
+       gchar *str;
+       gint result = 0;
+
+       str = ghb_value_string(vrate);
+       for (ii = 0; ii < hb_video_rates_count; ii++)
+       {
+               if (strcmp(hb_video_rates[ii].string, str) == 0)
+               {
+                       result = hb_video_rates[ii].rate;
+               }
+       }
+       g_free(str);
+       // Default to "same as source"
+       return result;
+}
+
+gint
+ghb_lookup_vcodec(const GValue *vcodec)
+{
+       gint ii;
+       gchar *str;
+       gint result = HB_VCODEC_FFMPEG;
+
+       str = ghb_value_string(vcodec);
+       for (ii = 0; ii < vcodec_opts.count; ii++)
+       {
+               if (strcmp(vcodec_opts.map[ii].shortOpt, str) == 0)
+               {
+                       result = vcodec_opts.map[ii].ivalue;
+               }
+       }
+       g_free(str);
+       return result;
+}
+
+gint
+ghb_lookup_denoise(const GValue *denoise)
+{
+       gint ii;
+       gchar *str;
+       gint result = -1;
+
+       str = ghb_value_string(denoise);
+       for (ii = 0; ii < denoise_opts.count; ii++)
+       {
+               if (strcmp(denoise_opts.map[ii].shortOpt, str) == 0)
+               {
+                       result = denoise_opts.map[ii].ivalue;
+               }
+       }
+       g_free(str);
+       // Custom
+       return result;
+}
+
+gint
+ghb_lookup_deint(const GValue *deint)
+{
+       gint ii;
+       gchar *str;
+       gint result = -1;
+
+       str = ghb_value_string(deint);
+       for (ii = 0; ii < deint_opts.count; ii++)
+       {
+               if (strcmp(deint_opts.map[ii].shortOpt, str) == 0)
+               {
+                       result = deint_opts.map[ii].ivalue;
+               }
+       }
+       g_free(str);
+       // Custom
+       return result;
+}
+
+gint
+ghb_lookup_mux(const GValue *mux)
+{
+       gint ii;
+       gchar *str;
+       gint result = HB_MUX_MKV;
+
+       str = ghb_value_string(mux);
+       for (ii = 0; ii < container_opts.count; ii++)
+       {
+               if (strcmp(container_opts.map[ii].shortOpt, str) == 0)
+               {
+                       result = container_opts.map[ii].ivalue;
+               }
+       }
+       g_free(str);
+       return result;
+}
+
+gint
 ghb_lookup_acodec(const GValue *acodec)
 {
        gint ii;
        gchar *str;
+       gint result = HB_ACODEC_FAAC;
 
        str = ghb_value_string(acodec);
        for (ii = 0; ii < acodec_opts.count; ii++)
        {
                if (strcmp(acodec_opts.map[ii].shortOpt, str) == 0)
                {
-                       return acodec_opts.map[ii].ivalue;
+                       result = acodec_opts.map[ii].ivalue;
                }
        }
        g_free(str);
-       return HB_ACODEC_FAAC;
+       return result;
 }
 
 gint
@@ -467,17 +565,19 @@ ghb_lookup_mix(const GValue *mix)
 {
        gint ii;
        gchar *str;
+       gint result = HB_AMIXDOWN_DOLBYPLII;
+
 
        str = ghb_value_string(mix);
        for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
        {
                if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
                {
-                       return hb_audio_mixdowns[ii].amixdown;
+                       result = hb_audio_mixdowns[ii].amixdown;
                }
        }
        g_free(str);
-       return HB_AMIXDOWN_DOLBYPLII;
+       return result;
 }
 
 #if 0
@@ -569,7 +669,8 @@ get_amix_value(gint val)
 }
 
 // Handle for libhb.  Gets set by ghb_backend_init()
-static hb_handle_t * h = NULL;
+static hb_handle_t * h_scan = NULL;
+static hb_handle_t * h_queue = NULL;
 
 extern void hb_get_tempory_directory(hb_handle_t *h, char path[512]);
 
@@ -578,7 +679,7 @@ ghb_hb_cleanup(gboolean partial)
 {
        char dir[512];
 
-       hb_get_tempory_directory(h, dir);
+       hb_get_tempory_directory(h_scan, dir);
        del_tree(dir, !partial);
 }
 
@@ -589,8 +690,8 @@ get_hb_audio(gint titleindex, gint track)
        hb_title_t * title;
     hb_audio_config_t *audio = NULL;
        
-    if (h == NULL) return NULL;
-       list = hb_get_titles( h );
+    if (h_scan == NULL) return NULL;
+       list = hb_get_titles( h_scan );
        if( !hb_list_count( list ) )
        {
                /* No valid title, stop right there */
@@ -1066,9 +1167,9 @@ title_opts_set(GtkBuilder *builder, const gchar *name)
        g_debug("title_opts_set ()\n");
        store = get_combo_box_store(builder, name);
        gtk_list_store_clear(store);
-       if (h != NULL)
+       if (h_scan != NULL)
        {
-               list = hb_get_titles( h );
+               list = hb_get_titles( h_scan );
                count = hb_list_count( list );
                if (count > 100) count = 100;
        }
@@ -1170,9 +1271,9 @@ audio_track_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
        g_debug("audio_track_opts_set ()\n");
        store = get_combo_box_store(builder, name);
        gtk_list_store_clear(store);
-       if (h != NULL)
+       if (h_scan != NULL)
        {
-               list = hb_get_titles( h );
+               list = hb_get_titles( h_scan );
            title = (hb_title_t*)hb_list_item( list, titleindex );
                if (title != NULL)
                {
@@ -1221,9 +1322,9 @@ subtitle_opts_set(GtkBuilder *builder, const gchar *name, gint titleindex)
        g_debug("subtitle_opts_set ()\n");
        store = get_combo_box_store(builder, name);
        gtk_list_store_clear(store);
-       if (h != NULL)
+       if (h_scan != NULL)
        {
-               list = hb_get_titles( h );
+               list = hb_get_titles( h_scan );
            title = (hb_title_t*)hb_list_item( list, titleindex );
                if (title != NULL)
                {
@@ -1287,8 +1388,8 @@ ghb_longest_title()
        gint titleindex = 0;
        
        g_debug("ghb_longest_title ()\n");
-       if (h == NULL) return 0;
-       list = hb_get_titles( h );
+       if (h_scan == NULL) return 0;
+       list = hb_get_titles( h_scan );
        count = hb_list_count( list );
        if (count > 100) count = 100;
        for (ii = 0; ii < count; ii++)
@@ -1315,9 +1416,9 @@ ghb_find_audio_track(gint titleindex, const gchar *lang, gint index)
        gint match = 0;
        
        g_debug("find_audio_track ()\n");
-       if (h != NULL)
+       if (h_scan != NULL)
        {
-               list = hb_get_titles( h );
+               list = hb_get_titles( h_scan );
            title = (hb_title_t*)hb_list_item( list, titleindex );
                if (title != NULL)
                {
@@ -1495,8 +1596,8 @@ ghb_get_chapters(gint titleindex)
        GValue *chapters = NULL;
        
        g_debug("ghb_get_chapters (title = %d)\n", titleindex);
-       if (h == NULL) return NULL;
-       list = hb_get_titles( h );
+       if (h_scan == NULL) return NULL;
+       list = hb_get_titles( h_scan );
     title = (hb_title_t*)hb_list_item( list, titleindex );
        if (title == NULL) return NULL;
        count = hb_list_count( title->list_chapter );
@@ -1561,7 +1662,8 @@ void
 ghb_backend_init(GtkBuilder *builder, gint debug, gint update)
 {
     /* Init libhb */
-    h = hb_init( debug, update );
+    h_scan = hb_init( debug, update );
+    h_queue = hb_init( debug, 0 );
        // Set up the list model for the combos
        init_ui_combo_boxes(builder);
        // Populate all the combos
@@ -1571,7 +1673,7 @@ ghb_backend_init(GtkBuilder *builder, gint debug, gint update)
 void
 ghb_backend_scan(const gchar *path, gint titleindex)
 {
-    hb_scan( h, path, titleindex );
+    hb_scan( h_scan, path, titleindex );
        hb_status.state |= GHB_STATE_SCANNING;
        // initialize count and cur to something that won't cause FPE
        // when computing progress
@@ -1579,12 +1681,26 @@ ghb_backend_scan(const gchar *path, gint titleindex)
        hb_status.title_cur = 0;
 }
 
+void
+ghb_backend_queue_scan(const gchar *path, gint titleindex)
+{
+       g_debug("ghb_backend_queue_scan()");
+    hb_scan( h_queue, path, titleindex );
+       hb_status.queue_state |= GHB_STATE_SCANNING;
+}
+
 gint
 ghb_get_state()
 {
        return hb_status.state;
 }
 
+gint
+ghb_get_queue_state()
+{
+       return hb_status.queue_state;
+}
+
 void
 ghb_clear_state(gint state)
 {
@@ -1592,12 +1708,24 @@ ghb_clear_state(gint state)
 }
 
 void
+ghb_clear_queue_state(gint state)
+{
+       hb_status.queue_state &= ~state;
+}
+
+void
 ghb_set_state(gint state)
 {
        hb_status.state |= state;
 }
 
 void
+ghb_set_queue_state(gint state)
+{
+       hb_status.queue_state |= state;
+}
+
+void
 ghb_get_status(ghb_status_t *status)
 {
        memcpy(status, &hb_status, sizeof(ghb_status_t));
@@ -1607,24 +1735,12 @@ void
 ghb_track_status()
 {
     hb_state_t s;
-       static gint scan_complete_count = 0;
-       gint scans;
+    hb_state_t s_queue;
 
-       if (h == NULL) return;
-    hb_get_state( h, &s );
-       scans = hb_get_scancount(h);
-       if (scans > scan_complete_count)
-       {
-               hb_status.state &= ~GHB_STATE_SCANNING;
-               hb_status.state |= GHB_STATE_SCANDONE;
-               scan_complete_count = hb_get_scancount(h);
-       }
+       if (h_scan == NULL) return;
+    hb_get_state( h_scan, &s );
        switch( s.state )
     {
-        case HB_STATE_IDLE:
-            /* Nothing to do */
-            break;
-
 #define p s.param.scanning
         case HB_STATE_SCANNING:
                {
@@ -1640,10 +1756,25 @@ ghb_track_status()
                        hb_status.state |= GHB_STATE_SCANDONE;
         } break;
 
-#define p s.param.working
+    }
+    hb_get_state( h_queue, &s_queue );
+       switch( s_queue.state )
+    {
+        case HB_STATE_SCANNING:
+               {
+                       hb_status.queue_state |= GHB_STATE_SCANNING;
+               } break;
+
+        case HB_STATE_SCANDONE:
+        {
+                       hb_status.queue_state &= ~GHB_STATE_SCANNING;
+                       hb_status.queue_state |= GHB_STATE_SCANDONE;
+        } break;
+
+#define p s_queue.param.working
         case HB_STATE_WORKING:
-                       hb_status.state |= GHB_STATE_WORKING;
-                       hb_status.state &= ~GHB_STATE_PAUSED;
+                       hb_status.queue_state |= GHB_STATE_WORKING;
+                       hb_status.queue_state &= ~GHB_STATE_PAUSED;
                        hb_status.job_cur = p.job_cur;
                        hb_status.job_count = p.job_count;
                        hb_status.progress = p.progress;
@@ -1657,25 +1788,23 @@ ghb_track_status()
 #undef p
 
         case HB_STATE_PAUSED:
-                       hb_status.state |= GHB_STATE_PAUSED;
+                       hb_status.queue_state |= GHB_STATE_PAUSED;
             break;
                                
-#define p s.param.muxing
         case HB_STATE_MUXING:
         {
-                       hb_status.state |= GHB_STATE_MUXING;
+                       hb_status.queue_state |= GHB_STATE_MUXING;
         } break;
-#undef p
 
-#define p s.param.workdone
+#define p s_queue.param.workdone
         case HB_STATE_WORKDONE:
                {
             hb_job_t *job;
 
-                       hb_status.state |= GHB_STATE_WORKDONE;
-                       hb_status.state &= ~GHB_STATE_MUXING;
-                       hb_status.state &= ~GHB_STATE_PAUSED;
-                       hb_status.state &= ~GHB_STATE_WORKING;
+                       hb_status.queue_state |= GHB_STATE_WORKDONE;
+                       hb_status.queue_state &= ~GHB_STATE_MUXING;
+                       hb_status.queue_state &= ~GHB_STATE_PAUSED;
+                       hb_status.queue_state &= ~GHB_STATE_WORKING;
                        switch (p.error)
                        {
                        case HB_ERROR_NONE:
@@ -1691,8 +1820,8 @@ ghb_track_status()
                        // When a job is stopped, libhb removes it from the job list,
                        // but does not remove other jobs that may be associated with it.
                        // Associated jobs are taged in the sequence id.
-            while (((job = hb_job(h, 0)) != NULL) && ((job->sequence_id >> 24) != 0) 
-                hb_rem( h, job );
+            while ((job = hb_job(h_queue, 0)) != NULL
+                hb_rem( h_queue, job );
                } break;
 #undef p
     }
@@ -1704,8 +1833,8 @@ ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex)
        hb_list_t  * list;
        hb_title_t * title;
        
-    if (h == NULL) return FALSE;
-       list = hb_get_titles( h );
+    if (h_scan == NULL) return FALSE;
+       list = hb_get_titles( h_scan );
        if( !hb_list_count( list ) )
        {
                /* No valid title, stop right there */
@@ -1784,8 +1913,8 @@ ghb_set_scale(signal_user_data_t *ud, gint mode)
        
        g_debug("ghb_set_scale ()\n");
 
-       if (h == NULL) return;
-       list = hb_get_titles( h );
+       if (h_scan == NULL) return;
+       list = hb_get_titles( h_scan );
        if( !hb_list_count( list ) )
        {
                /* No valid title, stop right there */
@@ -2015,8 +2144,8 @@ ghb_calculate_target_bitrate(GValue *settings, gint titleindex)
        hb_job_t   * job;
        gint size;
 
-       if (h == NULL) return 2000;
-       list = hb_get_titles( h );
+       if (h_scan == NULL) return 2000;
+       list = hb_get_titles( h_scan );
     title = hb_list_item( list, titleindex );
        if (title == NULL) return 2000;
        job   = title->job;
@@ -2070,26 +2199,28 @@ gboolean
 ghb_validate_filter_string(const gchar *str, gint max_fields)
 {
        gint fields = 0;
-       gboolean in_field = FALSE;
+       gchar *end;
+       gdouble val;
+
        if (str == NULL || *str == 0) return TRUE;
        while (*str)
        {
-               if (*str >= '0' && *str <= '9')
-               {
-                       if (!in_field)
-                       {
-                               fields++;
-                               // negative max_fields means infinate
-                               if (max_fields >= 0 && fields > max_fields) return FALSE;
-                               in_field = TRUE;
-                       }
+               val = g_strtod(str, &end);
+               if (str != end)
+               { // Found a numeric value
+                       fields++;
+                       // negative max_fields means infinate
+                       if (max_fields >= 0 && fields > max_fields) return FALSE;
+                       if (*end == 0)
+                               return TRUE;
+                       if (*end != ':')
+                               return FALSE;
+                       str = end + 1;
                }
-               else if (!in_field) return FALSE;
-               else if (*str != ':') return FALSE;
-               else in_field = FALSE;
-               str++;
+               else
+                       return FALSE;
        }
-       return TRUE;
+       return FALSE;
 }
 
 gboolean
@@ -2136,7 +2267,7 @@ ghb_validate_filters(signal_user_data_t *ud)
                index = ghb_settings_get_combo_index(ud->settings, "tweak_deinterlace");
                if (index < 0)
                {
-                       str = ghb_settings_get_combo_string(ud->settings, "tweak_deinterlace");
+                       str = ghb_settings_get_string(ud->settings, "tweak_deinterlace");
                        if (!ghb_validate_filter_string(str, 4))
                        {
                                message = g_strdup_printf(
@@ -2167,7 +2298,7 @@ ghb_validate_filters(signal_user_data_t *ud)
                index = ghb_settings_get_combo_index(ud->settings, "tweak_denoise");
                if (index < 0)
                {
-                       str = ghb_settings_get_combo_string(ud->settings, "tweak_denoise");
+                       str = ghb_settings_get_string(ud->settings, "tweak_denoise");
                        if (!ghb_validate_filter_string(str, 4))
                        {
                                message = g_strdup_printf(
@@ -2284,8 +2415,8 @@ ghb_validate_audio(signal_user_data_t *ud)
        gchar *message;
        GValue *value;
 
-       if (h == NULL) return FALSE;
-       list = hb_get_titles( h );
+       if (h_scan == NULL) return FALSE;
+       list = hb_get_titles( h_scan );
        if( !hb_list_count( list ) )
        {
                /* No valid title, stop right there */
@@ -2542,8 +2673,8 @@ ghb_add_job(GValue *js, gint unique_id)
        gchar *dest_str = NULL;
 
        g_debug("ghb_add_job()\n");
-       if (h == NULL) return;
-       list = hb_get_titles( h );
+       if (h_queue == NULL) return;
+       list = hb_get_titles( h_queue );
        if( !hb_list_count( list ) )
        {
                /* No valid title, stop right there */
@@ -2551,7 +2682,10 @@ ghb_add_job(GValue *js, gint unique_id)
                return;
        }
 
-       gint titleindex = ghb_settings_get_int(js, "title");
+       // Since I'm doing a scan of the single title I want just prior 
+       // to adding the job, there is only the one title to choose from.
+       //gint titleindex = ghb_settings_get_int(js, "title");
+    gint titleindex = 0;
     title = hb_list_item( list, titleindex );
        if (title == NULL) return;
 
@@ -2560,7 +2694,7 @@ ghb_add_job(GValue *js, gint unique_id)
        if (job == NULL) return;
 
        tweaks = ghb_settings_get_int(js, "allow_tweaks");
-       job->mux = ghb_settings_get_int(js, "container");
+       job->mux = ghb_lookup_mux(ghb_settings_get_value(js, "container"));
        if (job->mux == HB_MUX_MP4)
        {
                job->largeFileSize = ghb_settings_get_boolean(js, "large_mp4");
@@ -2616,10 +2750,10 @@ ghb_add_job(GValue *js, gint unique_id)
 
        
        gboolean decomb = ghb_settings_get_boolean(js, "decomb");
-       gint deint = ghb_settings_get_int(
-                                       js, tweaks ? "tweak_deinterlace":"deinterlace");
+       gint deint = ghb_lookup_deint(
+               ghb_settings_get_value(js, tweaks ? "tweak_deinterlace":"deinterlace"));
        if (!decomb)
-               job->deinterlace = (deint == 0) ? 0 : 1;
+               job->deinterlace = (deint != 0) ? 1 : 0;
        else
                job->deinterlace = 0;
     job->grayscale   = ghb_settings_get_boolean(js, "grayscale");
@@ -2677,7 +2811,10 @@ ghb_add_job(GValue *js, gint unique_id)
        }
        if( job->deinterlace )
        {
-               deint_str = ghb_settings_get_combo_string(js, 
+               if (deint > 0)
+                       deint_str = g_strdup(deint_opts.map[deint].svalue);
+               else
+                       deint_str = ghb_settings_get_string(js, 
                                        tweaks ? "tweak_deinterlace" : "deinterlace");
                hb_filter_deinterlace.settings = deint_str;
                hb_list_add( job->filters, &hb_filter_deinterlace );
@@ -2695,19 +2832,22 @@ ghb_add_job(GValue *js, gint unique_id)
                }
                hb_list_add( job->filters, &hb_filter_deblock );
        }
-       gint denoise = ghb_settings_get_int(
-                                               js, tweaks ? "tweak_denoise" : "denoise");
+       gint denoise = ghb_lookup_denoise(
+               ghb_settings_get_value(js, tweaks ? "tweak_denoise" : "denoise"));
        if( denoise != 0 )
        {
-               denoise_str = (gchar*)ghb_settings_get_combo_string(
-                       js, tweaks ? "tweak_denoise" : "denoise");
+               if (denoise > 0)
+                       denoise_str = g_strdup(denoise_opts.map[denoise].svalue);
+               else
+                       denoise_str = (gchar*)ghb_settings_get_string(
+                               js, tweaks ? "tweak_denoise" : "denoise");
                hb_filter_denoise.settings = denoise_str;
-               hb_list_add( job->filters, &hb_filter_deblock );
+               hb_list_add( job->filters, &hb_filter_denoise );
        }
        job->width = ghb_settings_get_int(js, "scale_width");
        job->height = ghb_settings_get_int(js, "scale_height");
 
-       job->vcodec = ghb_settings_get_int(js, "video_codec");
+       job->vcodec = ghb_lookup_vcodec(ghb_settings_get_value(js, "video_codec"));
        if ((job->mux == HB_MUX_MP4 || job->mux == HB_MUX_AVI) && 
                (job->vcodec == HB_VCODEC_THEORA))
        {
@@ -2762,7 +2902,7 @@ ghb_add_job(GValue *js, gint unique_id)
                job->vfr = FALSE;
        }
 
-       gint vrate = ghb_settings_get_int(js, "framerate");
+       gint vrate = ghb_lookup_vrate(ghb_settings_get_value(js, "framerate"));
        if( vrate == 0 || job->vfr )
        {
                job->vrate = title->rate;
@@ -2801,7 +2941,8 @@ ghb_add_job(GValue *js, gint unique_id)
                asettings = ghb_array_get_nth(audio_list, ii);
                audio.in.track = ghb_settings_get_int(asettings, "audio_track");
                audio.out.track = tcount;
-               audio.out.codec = ghb_settings_get_int(asettings, "audio_codec");
+               audio.out.codec = ghb_lookup_acodec(
+                       ghb_settings_get_value(asettings, "audio_codec"));
         taudio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, audio.in.track );
                if ((taudio->in.codec != HB_ACODEC_AC3) && (audio.out.codec == HB_ACODEC_AC3))
                {
@@ -2845,11 +2986,13 @@ ghb_add_job(GValue *js, gint unique_id)
                }
                else
                {
-                       audio.out.mixdown = ghb_settings_get_int (asettings, "audio_mix");
+                       audio.out.mixdown = ghb_lookup_mix(
+                               ghb_settings_get_value (asettings, "audio_mix"));
                        // Make sure the mixdown is valid and pick a new one if not.
-                       audio.out.mixdown = ghb_get_best_mix(titleindex, audio.in.track, audio.out.codec, 
-                                                                                               audio.out.mixdown);
-                       audio.out.bitrate = ghb_settings_get_int(asettings, "audio_bitrate") / 1000;
+                       audio.out.mixdown = ghb_get_best_mix(titleindex, 
+                               audio.in.track, audio.out.codec, audio.out.mixdown);
+                       audio.out.bitrate = 
+                               ghb_settings_get_int(asettings, "audio_bitrate") / 1000;
                        gint srate = ghb_settings_get_int(asettings, "audio_rate");
                        if (srate == 0) // 0 is same as source
                                audio.out.samplerate = taudio->in.samplerate;
@@ -2892,6 +3035,28 @@ ghb_add_job(GValue *js, gint unique_id)
                job->x264opts =  NULL;
        }
        gint subtitle = ghb_settings_get_int(js, "subtitle_lang");
+       gchar *slang = ghb_settings_get_string(js, "subtitle_lang");
+       subtitle = -2; // default to none
+       if (strcmp(slang, "auto") == 0)
+       {
+               subtitle = -1;
+       }
+       else
+       {
+               gint scount;
+       hb_subtitle_t * subt;
+
+               scount = hb_list_count(title->list_subtitle);
+               for (ii = 0; ii < scount; ii++)
+               {
+               subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, ii);
+                       if (strcmp(slang, subt->iso639_2) == 0)
+                       {
+                               subtitle = ii;
+                               break;
+                       }
+               }
+       }
        gboolean forced_subtitles = ghb_settings_get_boolean(js, "forced_subtitles");
        job->subtitle_force = forced_subtitles;
        if (subtitle >= 0)
@@ -2920,7 +3085,7 @@ ghb_add_job(GValue *js, gint unique_id)
                 * Add the pre-scan job
                 */
                job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
-               hb_add( h, job );
+               hb_add( h_queue, job );
                //if (job->x264opts != NULL)
                //      g_free(job->x264opts);
 
@@ -2973,7 +3138,7 @@ ghb_add_job(GValue *js, gint unique_id)
                        job->x264opts = x264opts;
                }
                job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
-               hb_add( h, job );
+               hb_add( h_queue, job );
                //if (job->x264opts != NULL)
                //      g_free(job->x264opts);
 
@@ -2988,7 +3153,7 @@ ghb_add_job(GValue *js, gint unique_id)
                job->indepth_scan = 0;
                job->x264opts = x264opts2;
                job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
-               hb_add( h, job );
+               hb_add( h_queue, job );
                //if (job->x264opts != NULL)
                //      g_free(job->x264opts);
        }
@@ -2997,7 +3162,7 @@ ghb_add_job(GValue *js, gint unique_id)
                job->indepth_scan = 0;
                job->pass = 0;
                job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24);
-               hb_add( h, job );
+               hb_add( h_queue, job );
                //if (job->x264opts != NULL)
                //      g_free(job->x264opts);
        }
@@ -3018,39 +3183,39 @@ ghb_remove_job(gint unique_id)
        // Multiples passes all get the same id
        // remove them all.
        // Go backwards through list, so reordering doesn't screw me.
-       ii = hb_count(h) - 1;
-    while ((job = hb_job(h, ii--)) != NULL)
+       ii = hb_count(h_queue) - 1;
+    while ((job = hb_job(h_queue, ii--)) != NULL)
     {
         if ((job->sequence_id & 0xFFFFFF) == unique_id)
-                       hb_rem(h, job);
+                       hb_rem(h_queue, job);
     }
 }
 
 void
 ghb_start_queue()
 {
-       hb_start( h );
+       hb_start( h_queue );
 }
 
 void
 ghb_stop_queue()
 {
-       hb_stop( h );
+       hb_stop( h_queue );
 }
 
 void
 ghb_pause_queue()
 {
     hb_state_t s;
-    hb_get_state2( h, &s );
+    hb_get_state2( h_queue, &s );
 
     if( s.state == HB_STATE_PAUSED )
     {
-        hb_resume( h );
+        hb_resume( h_queue );
     }
     else
     {
-        hb_pause( h );
+        hb_pause( h_queue );
     }
 }
 
@@ -3064,7 +3229,7 @@ ghb_get_preview_image(
        hb_title_t *title;
        hb_list_t  *list;
        
-       list = hb_get_titles( h );
+       list = hb_get_titles( h_scan );
        if( !hb_list_count( list ) )
        {
                /* No valid title, stop right there */
@@ -3144,7 +3309,7 @@ ghb_get_preview_image(
                bufferSize = newSize;
                buffer     = (guint8*) g_realloc( buffer, bufferSize );
        }
-       hb_get_preview( h, title, index, buffer );
+       hb_get_preview( h_scan, title, index, buffer );
 
        // Create an GdkPixbuf and copy the libhb image into it, converting it from
        // libhb's format something suitable. Along the way, we'll strip off the
index 3e171f1..19ba420 100644 (file)
@@ -29,6 +29,7 @@ enum
 typedef struct ghb_status_s
 {
        gint state;
+       gint queue_state;
 
        // SCANNING
        gint title_count;
@@ -90,10 +91,14 @@ void ghb_pause_queue(void);
 
 gint ghb_get_state(void);
 void ghb_clear_state(gint state);
+void ghb_clear_queue_state(gint state);
+
 void ghb_set_state(gint state);
+gint ghb_get_queue_state();
 void ghb_get_status(ghb_status_t *status);
 void ghb_track_status(void);
 void ghb_backend_scan(const gchar *path, gint titleindex);
+void ghb_backend_queue_scan(const gchar *path, gint titleindex);
 gboolean ghb_get_title_info(ghb_title_info_t *tinfo, gint titleindex);
 void ghb_set_scale(signal_user_data_t *ud, gint mode);
 GValue* ghb_get_chapters(gint titleindex);
index cc5c20a..6cf76ae 100644 (file)
@@ -38,6 +38,7 @@
 #include "renderer_button.h"
 #include "hb-backend.h"
 #include "ghb-dvd.h"
+#include "ghbcellrenderertext.h"
 
 
 /*
@@ -219,6 +220,7 @@ change_font(GtkWidget *widget, gpointer data)
 
 extern void chapter_list_selection_changed_cb(void);
 extern void chapter_edited_cb(void);
+extern void chapter_keypress_cb(void);
 
 // Create and bind the tree model to the tree view for the chapter list
 // Also, connect up the signal that lets us know the selection has changed
@@ -237,17 +239,18 @@ bind_chapter_tree_model (signal_user_data_t *ud)
        treestore = gtk_list_store_new(3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_BOOLEAN);
        gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(treestore));
 
-       cell = gtk_cell_renderer_text_new();
+       cell = ghb_cell_renderer_text_new();
        column = gtk_tree_view_column_new_with_attributes(
                                                                        _("Chapter No."), cell, "text", 0, NULL);
     gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column));
 
-       cell = gtk_cell_renderer_text_new();
+       cell = ghb_cell_renderer_text_new();
        column = gtk_tree_view_column_new_with_attributes(
                                        _("Chapter Title"), cell, "text", 1, "editable", 2, NULL);
     gtk_tree_view_append_column(treeview, GTK_TREE_VIEW_COLUMN(column));
-       g_signal_connect(cell, "edited", chapter_edited_cb, ud);
 
+       g_signal_connect(cell, "key-press-event", chapter_keypress_cb, ud);
+       g_signal_connect(cell, "edited", chapter_edited_cb, ud);
        g_signal_connect(selection, "changed", chapter_list_selection_changed_cb, ud);
        g_debug("Done\n");
 }
@@ -504,9 +507,11 @@ main (int argc, char *argv[])
        
        ud = g_malloc(sizeof(signal_user_data_t));
        ud->debug = FALSE;
+       ud->cancel_encode = FALSE;
        g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, debug_log_handler, ud);
        ud->settings = ghb_settings_new();
        ud->queue = NULL;
+       ud->current_job = NULL;
        ud->current_dvd_device = NULL;
        // Redirect stderr to the activity window
        IoRedirect(ud);
@@ -600,6 +605,8 @@ main (int argc, char *argv[])
                // Source overridden from command line option
                ghb_settings_set_string(ud->settings, "source", dvd_device);
        }
+       // Reload and check status of the last saved queue
+       g_idle_add((GSourceFunc)ghb_reload_queue, ud);
        // Start timer for monitoring libhb status, 500ms
        g_timeout_add (500, ghb_timer_cb, (gpointer)ud);
        // Everything should be go-to-go.  Lets rock!
diff --git a/gtk/src/marshalers.c b/gtk/src/marshalers.c
new file mode 100644 (file)
index 0000000..0f234ec
--- /dev/null
@@ -0,0 +1,125 @@
+
+#include       <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:STRING,STRING (marshalers.list:1) */
+void
+ghb_marshal_VOID__STRING_STRING (GClosure     *closure,
+                                 GValue       *return_value G_GNUC_UNUSED,
+                                 guint         n_param_values,
+                                 const GValue *param_values,
+                                 gpointer      invocation_hint G_GNUC_UNUSED,
+                                 gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__STRING_STRING) (gpointer     data1,
+                                                    gpointer     arg_1,
+                                                    gpointer     arg_2,
+                                                    gpointer     data2);
+  register GMarshalFunc_VOID__STRING_STRING callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_string (param_values + 1),
+            g_marshal_value_peek_string (param_values + 2),
+            data2);
+}
+
+/* BOOLEAN:BOXED (marshalers.list:2) */
+void
+ghb_marshal_BOOLEAN__BOXED (GClosure     *closure,
+                            GValue       *return_value G_GNUC_UNUSED,
+                            guint         n_param_values,
+                            const GValue *param_values,
+                            gpointer      invocation_hint G_GNUC_UNUSED,
+                            gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED) (gpointer     data1,
+                                                   gpointer     arg_1,
+                                                   gpointer     data2);
+  register GMarshalFunc_BOOLEAN__BOXED callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 2);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__BOXED) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_boxed (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
diff --git a/gtk/src/marshalers.h b/gtk/src/marshalers.h
new file mode 100644 (file)
index 0000000..1034f92
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef __ghb_marshal_MARSHAL_H__
+#define __ghb_marshal_MARSHAL_H__
+
+#include       <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:STRING,STRING (marshalers.list:1) */
+extern void ghb_marshal_VOID__STRING_STRING (GClosure     *closure,
+                                             GValue       *return_value,
+                                             guint         n_param_values,
+                                             const GValue *param_values,
+                                             gpointer      invocation_hint,
+                                             gpointer      marshal_data);
+
+/* BOOLEAN:BOXED (marshalers.list:2) */
+extern void ghb_marshal_BOOLEAN__BOXED (GClosure     *closure,
+                                        GValue       *return_value,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint,
+                                        gpointer      marshal_data);
+
+G_END_DECLS
+
+#endif /* __ghb_marshal_MARSHAL_H__ */
+
index da7bc55..93178b3 100644 (file)
@@ -382,14 +382,12 @@ ghb_plist_parse(const gchar *buf, gssize len)
 }
 
 GValue*
-ghb_plist_parse_file(const gchar *filename)
+ghb_plist_parse_file(FILE *fd)
 {
-       FILE *fd;
        gchar *buffer;
        size_t size;
        GValue *gval;
 
-       fd = fopen(filename, "r");
        if (fd == NULL)
                return NULL;
        fseek(fd, 0, SEEK_END);
@@ -577,11 +575,13 @@ main(gint argc, gchar *argv[])
 
        g_type_init();
 
-       gval = ghb_plist_parse_file(argv[1]);
+       file = g_fopen(argv[1], "r");
+       gval = ghb_plist_parse_file(file);
        if (argc > 2)
                ghb_plist_write_file(argv[2], gval);
        else
                ghb_plist_write(stdout, gval);
+       if (file) fclose (file);
        return 0;
 }
 #endif
index 8b24988..4ea0678 100644 (file)
@@ -6,7 +6,7 @@
 #include <glib-object.h>
 
 GValue* ghb_plist_parse(const gchar *buf, gssize len);
-GValue* ghb_plist_parse_file(const gchar *filename);
+GValue* ghb_plist_parse_file(FILE *fd);
 void ghb_plist_write(FILE *file, GValue *gval);
 void ghb_plist_write_file(const gchar *filename, GValue *gval);
 
index 75ef745..8f032d8 100644 (file)
@@ -372,6 +372,40 @@ store_plist(GValue *plist, const gchar *name)
        fclose(file);
 }
 
+static GValue*
+load_plist(const gchar *name)
+{
+       const gchar *dir;
+       gchar *config;
+       FILE *file;
+       GValue *plist = NULL;
+
+       dir = g_get_user_config_dir();
+       config = g_strdup_printf ("%s/ghb/%s", dir, name);
+       if (g_file_test(config, G_FILE_TEST_IS_REGULAR))
+       {
+               file = g_fopen(config, "r");
+               plist = ghb_plist_parse_file(file);
+       }
+       g_free(config);
+       return plist;
+}
+
+static void
+remove_plist(const gchar *name)
+{
+       const gchar *dir;
+       gchar *config;
+
+       dir = g_get_user_config_dir();
+       config = g_strdup_printf ("%s/ghb/%s", dir, name);
+       if (g_file_test(config, G_FILE_TEST_IS_REGULAR))
+       {
+               g_unlink(config);
+       }
+       g_free(config);
+}
+
 static gboolean prefs_initializing = FALSE;
 
 void
@@ -535,28 +569,15 @@ ghb_settings_init(signal_user_data_t *ud)
 void
 ghb_prefs_load(signal_user_data_t *ud)
 {
-       const gchar *dir;
-       gchar *config;
        GValue *dict, *internal;
        GHashTableIter iter;
        gchar *key;
        GValue *gval;
        
        g_debug("ghb_prefs_load");
-       dir = g_get_user_config_dir();
-       config = g_strdup_printf ("%s/ghb/preferences", dir);
-       if (g_file_test(config, G_FILE_TEST_IS_REGULAR))
-       {
-               prefsPlist = ghb_plist_parse_file(config);
-               if (prefsPlist == NULL)
-                       prefsPlist = ghb_dict_value_new();
-       }
-       else
-       {
-               // Make an empty plist
+       prefsPlist = load_plist("preferences");
+       if (prefsPlist == NULL)
                prefsPlist = ghb_dict_value_new();
-       }
-       g_free(config);
        dict = plist_get_dict(prefsPlist, "Preferences");
        internal = plist_get_dict(internalPlist, "Preferences");
     if (dict == NULL && internal)
@@ -575,7 +596,6 @@ ghb_prefs_load(signal_user_data_t *ud)
                        g_strdup("destination_dir"), ghb_value_dup(ghb_string_value(dir)));
                store_plist(prefsPlist, "preferences");
     }
-
 }
 
 void
@@ -619,29 +639,33 @@ presets_store()
 }
 
 void
-ghb_presets_load()
+ghb_save_queue(GValue *queue)
 {
-       const gchar *dir;
-       gchar *config;
+       store_plist(queue, "queue");
+}
 
-       dir = g_get_user_config_dir();
-       config = g_strdup_printf ("%s/ghb/presets", dir);
-       if (g_file_test(config, G_FILE_TEST_IS_REGULAR))
-       {
-               presetsPlist = ghb_plist_parse_file(config);
-               if (presetsPlist == NULL)
-               {
-                       presetsPlist = ghb_plist_parse(
-                               standardPresets, sizeof(standardPresets)-1);
-                       presets_store();
-               }
-       }
-       else
+GValue*
+ghb_load_queue()
+{
+       return load_plist("queue");
+}
+
+void
+ghb_remove_queue_file()
+{
+       remove_plist("queue");
+}
+
+void
+ghb_presets_load()
+{
+       presetsPlist = load_plist("presets");
+       if (presetsPlist == NULL)
        {
                presetsPlist = ghb_plist_parse(
                        standardPresets, sizeof(standardPresets)-1);
+               presets_store();
        }
-       g_free(config);
 }
 
 void
index 44f9cdd..b216c55 100644 (file)
@@ -33,5 +33,8 @@ void ghb_prefs_to_ui(signal_user_data_t *ud);
 void ghb_prefs_save(GValue *settings);
 void ghb_pref_save(GValue *settings, const gchar *key);
 void ghb_set_preset_default(GValue *settings);
+void ghb_save_queue(GValue *queue);
+GValue* ghb_load_queue();
+void ghb_remove_queue_file(void);;
 
 #endif // _GHB_PRESETS_H_
index 4f2cacb..1fad691 100644 (file)
@@ -193,19 +193,6 @@ ghb_settings_get_combo_option(GValue *settings, const gchar *key)
        return g_strdup(cd->option);
 }
 
-gchar*
-ghb_settings_get_combo_string(GValue *settings, const gchar *key)
-{
-       const GValue* value;
-       value = ghb_settings_get_value(settings, key);
-       if (value == NULL) return g_strdup("");
-       ghb_combodata_t *cd;
-       if (G_VALUE_TYPE(value) != ghb_combodata_get_type())
-               return g_strdup("");
-       cd = g_value_get_boxed(value);
-       return g_strdup(cd->svalue);
-}
-
 // Map widget names to setting keys
 // Widgets that map to settings have names
 // of this format: s_<setting key>
index 99d8e68..cc89f1f 100644 (file)
@@ -44,9 +44,11 @@ typedef struct
        gchar *current_dvd_device;
        gboolean debug;
        gboolean dont_clear_presets;
+       gboolean cancel_encode;
        GtkBuilder *builder;
        GValue *settings;
        GValue *queue;
+       GValue *current_job;
        GIOChannel *activity_log;
 } signal_user_data_t;
 
@@ -83,7 +85,6 @@ gdouble ghb_settings_get_double(GValue *settings, const gchar *key);
 gchar* ghb_settings_get_string(GValue *settings, const gchar *key);
 gint ghb_settings_get_combo_index(GValue *settings, const gchar *key);
 gchar* ghb_settings_get_combo_option(GValue *settings, const gchar *name);
-gchar* ghb_settings_get_combo_string(GValue *settings, const gchar *key);
 
 GValue* ghb_widget_value(GtkWidget *widget);
 gchar* ghb_widget_string(GtkWidget *widget);