zoukankan      html  css  js  c++  java
  • 一个非常出色的gtk例子

     

    2007-06-10 22:09:41

    #include <config.h>

    #include <string.h>
    #include <glib/gi18n.h>
    #include <gtk/gtk.h>

    #include <gtkimageview/gtkimageview.h>
    #include <gtkimageview/gtkimagescrollwin.h>

    #include <gio/gfile.h>

    #include "katachi-fullscreen.h"
    #include "katachi-image-cache.h"
    #include "katachi-image-store.h"
    #include "thumbnailer.h"
    #include "shared.h"

    GdkPixbuf *generic_thumb;

    static int load_depth; /* Used to know when to restore the cursor */
    static GdkCursor *busy_cursor;

    static GtkTreeModel *file_store;

    static GtkWidget *window;
    static GtkWidget *file_list, *preview;


    static void
    got_pixbuf (GFile *file, GdkPixbuf *pixbuf, gpointer user_data)
    {
    gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (preview), pixbuf);

    /* The image view takes it's own reference, so unref our copy */
    g_object_unref (pixbuf);

    if (--load_depth == 0)
    gdk_window_set_cursor (window->window, NULL);
    }

    /*
    * GtkIconView selection changed. Cancels an existing loader, and starts a new
    * one.
    */
    static void
    on_selection_changed (GtkIconView *view, gpointer user_data)
    {
    GtkTreeModel *model;
    GList *list;
    GtkTreeIter iter;
    GFile *file;

    model = gtk_icon_view_get_model (view);

    list = gtk_icon_view_get_selected_items (view);
    if (list == NULL) {
    gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (preview), NULL);
    return;
    }

    if (g_list_length (list) > 1) {
    gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (preview), NULL);
    goto done;
    }

    gtk_tree_model_get_iter (model, &iter, list->data);

    gtk_tree_model_get (model, &iter, COL_FILE, &file, -1);
    if (!file) {
    gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (preview), NULL);
    goto done;
    }

    gdk_window_set_cursor (window->window, busy_cursor);
    load_depth++;

    katachi_image_cache_get_pixbuf (preview, file, TRUE, got_pixbuf, NULL);

    g_object_unref (file);

    done:
    g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
    g_list_free (list);
    }

    /*
    * Callback from rows being inserted, to generate a thumbnail.
    */
    static void
    on_row_inserted (GtkTreeModel *model,
    GtkTreePath *tree_path, GtkTreeIter *iter,
    gpointer user_data)
    {
    ThumbnailData *data;

    data = g_slice_new0 (ThumbnailData);

    gtk_tree_model_get (model, iter, COL_FILE, &data->file, -1);
    if (data->file == NULL)
    return;

    data->iter = *iter;

    thumbnailer_push (data);
    }

    /*
    * Callback from the UI manager with the GtkMenu widget. Pack and add this to
    * the container.
    */
    static void
    ui_add_widget (GtkUIManager *ui, GtkWidget *widget, GtkContainer *container)
    {
    gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
    gtk_widget_show (widget);
    }

    static void
    on_open_location_action (GtkAction *action, gpointer user_data)
    {
    GtkWidget *dialog;

    /* TODO: have to use a specific backend because gnome-vfs and gvfs conflict */
    dialog = gtk_file_chooser_dialog_new (_("Select Directory"), GTK_WINDOW (window),
    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
    NULL);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
    char *filename;

    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));

    katachi_image_store_populate (KATACHI_IMAGE_STORE (file_store),
    g_file_get_for_path (filename));

    g_free (filename);
    }

    gtk_widget_destroy (dialog);
    }

    static void
    on_delete_action (GtkAction *action, gpointer user_data)
    {
    GtkWidget *dialog;
    GList *iters, *l;
    int count;

    iters = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (file_list));

    count = g_list_length (iters);
    dialog = gtk_message_dialog_new (GTK_WINDOW (window),
    0, GTK_MESSAGE_QUESTION,
    GTK_BUTTONS_NONE,
    ngettext ("Are you sure you want to delete this file?",
    "Are you sure you want to delete these %d files?",
    count),
    count);

    gtk_dialog_add_buttons (GTK_DIALOG (dialog),
    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
    NULL);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
    gtk_icon_view_unselect_all (GTK_ICON_VIEW (file_list));

    for (l = iters; l; l = l->next) {
    GtkTreeIter iter;
    GError *error = NULL;
    GFile *file = NULL;

    gtk_tree_model_get_iter (file_store, &iter, l->data);

    gtk_tree_model_get (file_store, &iter, COL_FILE, &file, -1);
    if (!file)
    continue;

    if (g_file_delete (file, NULL, &error)) {
    /* TODO: remove from the model now instead of waiting for the notification */
    } else {
    g_warning ("Cannot delete file: %s", error->message);
    g_error_free (error);
    error = NULL;
    }

    g_object_unref (file);
    }
    }

    gtk_widget_destroy (dialog);
    g_list_foreach (iters, (GFunc)gtk_tree_path_free, NULL);
    g_list_free (iters);
    }

    static void
    on_fullscreen_action (GtkAction *action, gpointer user_data)
    {
    GtkWidget *fullscreen;
    GList *paths;

    paths = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (file_list));

    if (g_list_length (paths) == 1) {
    fullscreen = katachi_fullscreen_new (KATACHI_IMAGE_STORE (file_store));
    katachi_fullscreen_set_path (KATACHI_FULLSCREEN (fullscreen), paths->data);
    gtk_widget_show (fullscreen);
    }

    g_list_foreach (paths, (GFunc)gtk_tree_path_free, NULL);
    g_list_free (paths);
    }

    /*
    * Callback from the About action.
    */
    static void
    on_about_action (GtkAction *action, gpointer user_data)
    {
    const char* authors[] = {
    "Ross Burton <ross@openedhand.com>", NULL,
    };
    const char *license = {
    N_(
    "Tasks is free software; you can redistribute it and/or modify "
    "it under the terms of the GNU General Public License as published by "
    "the Free Software Foundation; either version 2 of the License, or "
    "(at your option) any later version.\n\n"
    "Tasks 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 General Public License for more details.\n\n"
    "You should have received a copy of the GNU General Public License "
    "along with Tasks; if not, write to the Free Software Foundation, Inc., "
    "51 Franklin St, Fifth Floor, Boston, MA 0110-1301, USA"
    )
    };

    gtk_show_about_dialog (GTK_WINDOW (window),
    "name", _("Katachi Image Viewer"),
    "version", VERSION,
    "logo-icon-name", "katachi",
    "copyright", "Copyright \302\251 2007 Ross Burton",
    "authors", authors,
    "license", license,
    "wrap-license", TRUE,
    "website", "http://burtonini.com/",
    NULL);
    }

    static const GtkActionEntry actions[] =
    {
    /* Action name, stock ID, label, accelerator, tooltip, callback */
    { "FileMenu", NULL, N_("_File") },
    { "OpenLocation", NULL, N_("Open _Location..."), NULL, NULL, G_CALLBACK (on_open_location_action) },
    { "Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, G_CALLBACK (gtk_main_quit) },
    { "EditMenu", NULL, N_("_Edit") },
    { "Delete", GTK_STOCK_DELETE, NULL, "<Shift>Delete", NULL, G_CALLBACK (on_delete_action) },
    { "ViewMenu", NULL, N_("_View") },
    /* TODO: disable Fullscreen if more than one selected items */
    { "Fullscreen", GTK_STOCK_FULLSCREEN, NULL, "F11", NULL, G_CALLBACK (on_fullscreen_action) },
    { "HelpMenu", NULL, N_("_Help") },
    { "About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK (on_about_action) },
    };

    int
    main (int argc, char **argv)
    {
    GError *error = NULL;
    GtkWidget *top_box, *box, *scrolled, *image_scroll;
    GtkActionGroup *action_group;
    GtkUIManager *ui_manager;

    g_thread_init (NULL);
    g_set_application_name (_("Katachi"));
    gtk_init (&argc, &argv);

    load_depth = 0;

    busy_cursor = gdk_cursor_new_from_name (gdk_display_get_default (),
    "left_ptr_watch");

    generic_thumb = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
    "image-x-generic", 64, 0, NULL);

    katachi_image_cache_init ();
    file_store = katachi_image_store_new ();

    thumbnailer_init (KATACHI_IMAGE_STORE (file_store));
    g_signal_connect_after (file_store, "row-inserted", G_CALLBACK (on_row_inserted), NULL);

    /* This starts an async operation, and will unref the path when done */
    if (argc > 1) {
    katachi_image_store_populate (KATACHI_IMAGE_STORE (file_store),
    g_file_get_for_commandline_arg (argv[1]));
    } else {
    katachi_image_store_populate (KATACHI_IMAGE_STORE (file_store),
    g_file_get_for_path ("/home/ross/Pictures/Photos/Incoming/"));
    }

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
    gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);

    top_box = gtk_vbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (window), top_box);

    action_group = gtk_action_group_new ("Actions");
    gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
    gtk_action_group_add_actions (action_group, actions, G_N_ELEMENTS (actions), NULL);

    ui_manager = gtk_ui_manager_new ();
    gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);

    gtk_ui_manager_add_ui_from_file (ui_manager, PKGDATADIR "/katachi-ui.xml", &error);
    if (error) {
    g_warning ("Cannot load UI: %s", error->message);
    g_error_free (error);
    error = NULL;
    }

    /* Bind the accelerators */
    gtk_window_add_accel_group (GTK_WINDOW (window), gtk_ui_manager_get_accel_group (ui_manager));
    g_signal_connect (ui_manager, "add-widget", G_CALLBACK (ui_add_widget), top_box);

    /* Do this so that the menu is packed now instead of in the idle loop */
    gtk_ui_manager_ensure_update (ui_manager);

    box = gtk_hbox_new (FALSE, 0);
    gtk_container_add (GTK_CONTAINER (top_box), box);

    scrolled = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
    GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
    gtk_box_pack_start (GTK_BOX (box), scrolled, FALSE, TRUE, 0);

    /* TODO: make a widget out of this */
    file_list = gtk_icon_view_new_with_model (file_store);
    /* TODO: add my own renderers so that I can use icon names and magically
    handle theme changes? */
    g_object_set (file_list,
    "selection-mode", GTK_SELECTION_MULTIPLE,
    "columns", 1,
    "pixbuf-column", COL_THUMB,
    NULL);
    /* TODO: get these numbers from the widget */
    gtk_widget_set_size_request (file_list, 128 + 6 + 6, -1);
    g_signal_connect (file_list, "selection-changed", G_CALLBACK (on_selection_changed), NULL);
    gtk_container_add (GTK_CONTAINER (scrolled), file_list);

    preview = gtk_image_view_new ();
    image_scroll = gtk_image_scroll_win_new (GTK_IMAGE_VIEW (preview));
    gtk_box_pack_start (GTK_BOX (box), image_scroll, TRUE, TRUE, 0);

    gtk_widget_show_all (window);
    gtk_main ();

    return 0;

    }


    from http://burtonini.com/bzr/
  • 相关阅读:
    User Profile Synchronization Service–Hangs on Starting (I fixed it!) 用户配置文件同步服务卡在“正在启动”状态
    User Profile Synchronization Service Gets Stuck on Starting 用户配置文件同步服务卡在“启动中”的解决方案
    User Profile Service Stuck on Starting --用户配置文件停在“启动中”
    SP2010开发和VS2010专家"食谱"--第七章节--使用客户端对象模型(5)--Using a Silverlight Object Model
    SP2010开发和VS2010专家"食谱"--第七章节--使用客户端对象模型(4)--Using JavaScript Object Model
    SP2010开发和VS2010专家"食谱"--第七章节--使用客户端对象模型(3)--Calling Object Model asynchronously
    SP2010开发和VS2010专家"食谱"--第七章节--使用客户端对象模型(2)--Handling exceptions
    SP2010开发和VS2010专家"食谱"--第七章节--使用客户端对象模型(1)--Creating a list using a Managed OM
    “尝尝鲜”的学习方法(点到为止)
    辩证的看问题,更好的理解问题
  • 原文地址:https://www.cnblogs.com/cy163/p/787072.html
Copyright © 2011-2022 走看看