非常简单的GtkTextView用例的问题

时间:2014-10-22 07:15:07

标签: c gtk glade

我有一个用glade设计的Gtk + 3.0用户界面,并在C中用两个列表视图实现(作为GtkTreeView实现)。当我在第二个列表视图中单击一个项目时,我希望在多行文本视图中显示该条目的详细信息。除了使用GtkTextView之外,没有其他选择,即使我需要不到GtkTextView提供的1%(我甚至不需要编辑)。 但是,在我的UI上使用GtkTextView元素时,程序会在列表中的第一次单击时崩溃。当我从代码中删除GtkTextView的更新时,我可以永久地使用UI来玩,不会崩溃。 以下是更新文本视图的代码:

// get stuff from list store

gtk_tree_model_get_iter (GTK_TREE_MODEL (liststore), &iter, tree_path);
gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
                  ITEM_NAME, &itemName,
                  ITEM_DESC, &itemDesc,
                  ITEM_LINK, &itemLink, -1);
// fill a couple of one line GtkEntry first
// ...
// fill the text view
txtBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (txtDesc));
gtk_text_buffer_set_text (txtBuffer, itemDesc, -1);

我检查过itemDesc是否为非NULL。我用valgrind对此进行了分析,有趣的是没有检测到明显的内存处理错误但堆栈溢出!我没有使用递归...无论如何,这里是valgrind的输出:

==4879== Stack overflow in thread 1: can't grow stack to 0xffe801ff8
==4879== 
==4879== Process terminating with default action of signal 11 (SIGSEGV)
==4879==  Access not within mapped region at address 0xFFE801FF8
==4879==    at 0x5B36564: g_hash_table_lookup (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4000.0)
==4879==  If you believe this happened as a result of a stack
==4879==  overflow in your program's main thread (unlikely but
==4879==  possible), you can try to increase the size of the
==4879==  main thread stack using the --main-stacksize= flag.
==4879==  The main thread stack size used in this run was 8388608.
==4879== 
==4879== HEAP SUMMARY:
==4879==     in use at exit: 3,946,706 bytes in 45,434 blocks
==4879==   total heap usage: 326,942 allocs, 281,508 frees, 25,249,132 bytes allocated
==4879== 
==4879== LEAK SUMMARY:
==4879==    definitely lost: 3,664 bytes in 32 blocks
==4879==    indirectly lost: 12,977 bytes in 542 blocks
==4879==      possibly lost: 165,544 bytes in 1,342 blocks
==4879==    still reachable: 3,594,265 bytes in 42,477 blocks
==4879==         suppressed: 0 bytes in 0 blocks
==4879== Rerun with --leak-check=full to see details of leaked memory
==4879== 
==4879== For counts of detected and suppressed errors, rerun with: -v
==4879== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

任何想法都表示赞赏。这是C代码。

#include <gtk/gtk.h>
#include <string.h>
#include <glib.h>
#include <libxml/parser.h>
#include <sqlite3.h>

#include "kpodcast.h"
#include "global.h"

GtkBuilder *builder;

enum {
    PODCAST_NAME = 0,
    NCOLUMNS
};

enum {
    ITEM_NAME = 0,
    ITEM_DATE = 1,
    ITEM_DESC = 2,
    PODCAST_IDX = 3,
    ITEM_LINK = 4,
    NCOLUMNS2
};

extern GList        * all_podcasts;
extern GTimeZone    * gTimeZone;
extern sqlite3      * db;

void kleine_callback (GtkWidget *w, gpointer d)
{
    GtkWidget *dialog;
    dialog = gtk_message_dialog_new (NULL,
    GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Hallo, Welt!");
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);
}

void
on_item_selection_change (GtkTreeSelection * widget, gpointer user_data)
{
    GList        * selection  = gtk_tree_selection_get_selected_rows (widget, NULL);
    GtkTreePath  * tree_path  = NULL;
    GtkLabel     * txtDesc    = NULL;
    GtkEntry     * txtLink    = NULL;
    GtkTextBuffer* txtBuffer  = NULL;
    GtkEntry     * txtName    = NULL;
    GtkListStore * liststore  = NULL;
    char         * message    = NULL;
    GtkTreeIter    iter;
    gchar        * itemName   = NULL;
    gchar        * itemDesc   = NULL;
    gchar        * itemLink   = NULL;
    GtkStatusbar * status_bar = GTK_WIDGET (gtk_builder_get_object (builder, "status_bar"));

    txtName = GTK_WIDGET (gtk_builder_get_object (builder, "txtItemName"));
    txtDesc = GTK_WIDGET (gtk_builder_get_object (builder, "txtItemDesc"));
    txtLink = GTK_WIDGET (gtk_builder_get_object (builder, "txtItemLink"));

    if (selection != NULL) {
        tree_path = (GtkTreePath *) selection->data;
        int depth = gtk_tree_path_get_depth (tree_path);
        int * idx = gtk_tree_path_get_indices (tree_path);
        liststore = GTK_LIST_STORE (gtk_builder_get_object (builder,  "liststore_podcast_items"));

        gtk_tree_model_get_iter (GTK_TREE_MODEL (liststore), &iter, tree_path);
        gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter,
                            ITEM_NAME, &itemName,
                            ITEM_DESC, &itemDesc,
                            ITEM_LINK, &itemLink, -1);

        // set item name
        gtk_entry_set_text (txtName, itemName);
        //gtk_label_set_text (txtDesc, itemDesc);
        // set item description

        txtBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (txtDesc));
        gtk_text_buffer_set_text (txtBuffer, itemDesc, -1);
        // set item link
        gtk_entry_set_text(txtLink, itemLink);


        FREE_POINTER1 (itemName);
        FREE_POINTER1 (itemDesc);
        FREE_POINTER1 (itemLink);
    }
    else {
        gtk_entry_set_text (txtName, "");
        gtk_entry_set_text (txtLink, "");
        /*
        txtBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (txtDesc));
        gtk_text_buffer_set_text (txtBuffer, "", -1);
        */
        gtk_label_set_text (txtDesc, itemDesc);
    }
}

void
on_podcast_selection_change (GtkTreeSelection *widget, gpointer user_data)
{
    GList        * selection  = gtk_tree_selection_get_selected_rows (widget, NULL);
    GtkTreePath  * tree_path  = NULL;
    char         * message    = NULL;
    GtkStatusbar * status_bar = GTK_WIDGET (gtk_builder_get_object (builder, "status_bar"));
    guint          context    = gtk_statusbar_get_context_id (status_bar, "some_context_id");
    kpodcastPtr    podcast    = NULL;
    GtkListStore * liststore  = NULL;
    GtkTreeIter    iter;
    guint          item_list_length = 0, jj=0;

    if (selection) {
        tree_path = (GtkTreePath *) selection->data;
        int depth = gtk_tree_path_get_depth (tree_path);

        if (depth == 1) { // replace by assert (depth = 1)
            //set GtkTreeIter to index
            // Add Name and Description to the UI
            //
            int * idx = gtk_tree_path_get_indices (tree_path);
            podcast = (kpodcastPtr) g_list_nth_data (all_podcasts, *idx);
            /*
            gtk_entry_set_text(txtName, podcast->name);
            txtBuffer = gtk_text_buffer_new (NULL);
            gtk_text_buffer_set_text (txtBuffer, podcast->desc, -1);
            gtk_text_view_set_buffer(txtDesc, txtBuffer);
            */

            //
            // Get list store
            //
            liststore = GTK_LIST_STORE (gtk_builder_get_object (builder,  "liststore_podcast_items"));
            gtk_list_store_clear (liststore);

            //
            // Add all podcasts
            //
            item_list_length = g_list_length (podcast->items);
            for (jj=0; jj<item_list_length; jj++) {
                kpodcastItemPtr item = (kpodcastItemPtr) g_list_nth_data (podcast->items, jj);
                GDateTime * gDate = NULL;
                char * date;
                gDate = g_date_time_new_from_unix_local (item->pubDate);
                date = g_date_time_format (gDate, "%Y-%m-%d");
                gtk_list_store_append(liststore, &iter);
                gtk_list_store_set (liststore, &iter,
                                      ITEM_NAME, item->name,
                                      ITEM_DATE, date,
                                      ITEM_DESC, item->desc,
                                      PODCAST_IDX, *idx,
                                      ITEM_LINK, item->link,
                                      -1);
                g_date_time_unref (gDate);
            }

        }
    }
    else {
        message = g_strdup ("Treepath is NULL.");
        gtk_statusbar_push (status_bar, context, message);
        //g_printf ("statusbar push returned %d.\n", rc);
        g_free (message);
    }
    g_list_free_full (selection, (GDestroyNotify) gtk_tree_path_free);
}

void
on_action_add_podcast (GtkWidget * widget, gpointer user_data)
{
    GtkStatusbar * status_bar = GTK_WIDGET (gtk_builder_get_object (builder, "status_bar"));
    if (status_bar == NULL)
        printf ("No status bar.\n");
    else {
        guint context = gtk_statusbar_get_context_id (status_bar, "somectxt");
        char  * message = g_strdup ("add_podcast clicked.");
        guint   rc      = gtk_statusbar_push (status_bar, context, message);
        g_free (message);
    }
}

void
on_action_click_download (GtkWidget * widget, gpointer user_data)
{
    GtkStatusbar * status_bar = GTK_WIDGET (gtk_builder_get_object (builder, "status_bar"));
    if (status_bar == NULL)
        printf ("No status bar.\n");
    else {
        guint context = gtk_statusbar_get_context_id (status_bar, "somectxt");
        char  * message = g_strdup ("podcast download clicked.");
        guint   rc      = gtk_statusbar_push (status_bar, context, message);
        g_free (message);
    }
}

void on_button_test_clicked (GtkWidget * w, gpointer d)
{
    g_print ("on button test clicked!");
}

void quit (GtkWidget * w, gpointer d)
{
    gtk_main_quit ();
}

#ifdef GTKUI
int main (int argc, char *argv[])
#else
int main_ (int argc, char *argv[])
#endif
{
    GError          * error = NULL;
    GtkWidget       * window;
    GtkListStore    * liststore_podcast;
    GtkTreeIter       iter;

    //
    // init the podcast stuff
    //

    // db
    if (!init_db ()) {
        printf ("DB could not be initialized: %s.", sqlite3_errmsg (db));
        return 0;
    }

    // timezone
    gTimeZone = g_time_zone_new_local ();

    // init podcasts
    if (!init_podcasts ()) {
        printf ("Podcasts could not be initialized, leaving.");
        return 0;
    }

    //
    // do the GTK+ stuff
    //
    gtk_init (&argc, &argv);
    builder = gtk_builder_new ();
    if (!gtk_builder_add_from_file (builder, "kaixN.glade", &error)) {
        g_warning ("%s", error->message);
        g_free (error);
        return 1;
    }
    liststore_podcast = GTK_LIST_STORE (gtk_builder_get_object (builder,  "liststore_podcasts"));
    if (liststore_podcast) {
        int ll = g_list_length (all_podcasts);
        if (ll == 0) {
            printf ("Podcast list is empty.\n");
        }
        else {
            int idx = 0;
            for (idx = 0; idx < ll; idx++) {
                kpodcastPtr podcast = (kpodcastPtr) g_list_nth_data (all_podcasts, idx);
                /* Append an empty row to the list store. Iter will point to the new row */
                gtk_list_store_append(liststore_podcast, &iter);
                gtk_list_store_set (liststore_podcast, &iter,
                                      PODCAST_NAME, podcast->name,
                                      -1);
            }
        }
    }
    else {
        g_print ("Couldn't get liststore_podcasts.\n");
    }
    window = GTK_WIDGET(gtk_builder_get_object (builder,  "main_window"));
    gtk_builder_connect_signals (builder, NULL);
    gtk_widget_show_all (window);
    gtk_main ();
    return 0;
}

非常感谢 启

0 个答案:

没有答案