アイコンビュー



アイコンビューウィジェットを使って、サンプルを作ってみる。

#include <gtk/gtk.h>

enum
{
  COLUMN_NAME,
  COLUMN_PIXBUF,
  N_COLUMNS
};

static void add_data(GtkIconView *iconview)
{
  GdkPixbuf *folder_pixbuf;
  GdkPixbuf *file_pixbuf;
  GtkListStore *store;
  GtkTreeIter iter;

  file_pixbuf = gdk_pixbuf_new_from_file("./file.png", NULL);
  folder_pixbuf = gdk_pixbuf_new_from_file("./folder.png", NULL);

  store = GTK_LIST_STORE(gtk_icon_view_get_model(iconview));

  gtk_list_store_clear(store);

  //データの追加
  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, COLUMN_NAME, "folder.png", COLUMN_PIXBUF, folder_pixbuf, -1);
  g_object_unref(folder_pixbuf);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, COLUMN_NAME, "file.png", COLUMN_PIXBUF, file_pixbuf, -1);
  g_object_unref(file_pixbuf);
}

static GtkWidget* create_icon_view_widget(void)
{
  GtkWidget *iconview;
  GtkListStore *store;

  //モデルの作成
  store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF);
  //アイコンビューの作成
  iconview = gtk_icon_view_new_with_model(GTK_TREE_MODEL(store));
  g_object_unref(store);

  return iconview;
}

static void cb_item_activated(GtkIconView *iconview, GtkTreePath *treepath, gpointer user_data)
{
  GtkListStore *store;
  GtkTreeIter iter;
  gchar *name;

  store = GTK_LIST_STORE(gtk_icon_view_get_model(iconview));
  //クリックされたアイテムに対するGtkTreeIterの値を取得
  gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
  gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, COLUMN_NAME, &name, -1);
  g_print( "item '%s' is clicked.\n", name);
  g_free(name);
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *scroll_window;
  GtkWidget *iconview;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "IconView");
  gtk_widget_set_size_request(window, 500, 300);
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  scroll_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), GTK_SHADOW_ETCHED_IN);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_container_add(GTK_CONTAINER(window), scroll_window);

  iconview = create_icon_view_widget();
  //表示項目のラベル設定
  gtk_icon_view_set_text_column(GTK_ICON_VIEW(iconview), COLUMN_NAME);
  //表示項目の画像設定
  gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(iconview), COLUMN_PIXBUF);
  //アイテムの幅を設定
  gtk_icon_view_set_item_width(GTK_ICON_VIEW(iconview), 128);
  //表示されているアイテムがダブルクリックされた時に発生するシグナル
  g_signal_connect(G_OBJECT(iconview), "item-activated", G_CALLBACK(cb_item_activated), NULL);

  gtk_container_add(GTK_CONTAINER(scroll_window), iconview);

  add_data(GTK_ICON_VIEW(iconview));

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

アイコンをダブルクリックすると、標準出力に表示されるように処理した。

ダブルクリック以外にも、シグナルを発生させる条件が有る。

シグナルシグナル発生条件
item-activated表示されているアイテムをダブルクリック
select-all表示されているアイテムが全て選択状態
unselect表示されているアイテムが全て非選択状態


ファイルブラウザ


アイコンビューを使って、ファイルブラウザを作成してみる。

#include <gtk/gtk.h>

enum
{
  COLUMN_PATH,
  COLUMN_DISPLAY_NAME,
  COLUMN_PIXBUF,
  COLUMN_IS_DIRECTORY,
  N_COLUMNS
};

static gchar *currentdir = NULL;

static void cb_quit(GtkWidget *widget, gpointer user_data)
{
  g_free( currentdir );
  gtk_main_quit;
}

static void add_data(GtkIconView *iconview)
{
  GdkPixbuf *folder_pixbuf;
  GdkPixbuf *file_pixbuf;
  GtkListStore *store;
  GDir *dir;
  const gchar *name;
  GtkTreeIter iter;
  gchar *path;
  gchar *display_name;
  gboolean is_dir;

  file_pixbuf = gdk_pixbuf_new_from_file("./file.png", NULL);
  folder_pixbuf = gdk_pixbuf_new_from_file("./folder.png", NULL);

  store = GTK_LIST_STORE(gtk_icon_view_get_model(iconview));

  gtk_list_store_clear(store);

  dir = g_dir_open(currentdir, 0, NULL);
  if( !dir ){
    return;
  }

  while( name = g_dir_read_name(dir) ){
    if( name[0] != '.' ){
      path = g_build_filename(currentdir, name, NULL);
      is_dir = g_file_test(path, G_FILE_TEST_IS_DIR);
      display_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL);

      gtk_list_store_append(store, &iter);
      gtk_list_store_set(store, &iter,
        COLUMN_PATH, path,
        COLUMN_DISPLAY_NAME, display_name,
        COLUMN_IS_DIRECTORY, is_dir,
        COLUMN_PIXBUF, (is_dir) ? folder_pixbuf : file_pixbuf, -1);
      g_free( path );
      g_free( display_name );
    }
  }
  g_dir_close(dir);

  if( g_utf8_collate(currentdir, "/") != 0 ){
    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter,
      COLUMN_PATH, g_path_get_dirname(currentdir),
      COLUMN_DISPLAY_NAME, "..",
      COLUMN_IS_DIRECTORY, TRUE,
      COLUMN_PIXBUF, folder_pixbuf, -1);
  }
  g_object_unref(folder_pixbuf);
  g_object_unref(file_pixbuf);
}

static gint sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
  gboolean is_dir_a, is_dir_b;
  gchar *name_a, *name_b;
  int result;

  gtk_tree_model_get(model, a,
    COLUMN_IS_DIRECTORY, &is_dir_a,
    COLUMN_DISPLAY_NAME, &name_a, -1);
  gtk_tree_model_get(model, b,
    COLUMN_IS_DIRECTORY, &is_dir_b,
    COLUMN_DISPLAY_NAME, &name_b, -1);
  if( !is_dir_a && is_dir_b ){
    result = 1;
  }
  else if(is_dir_a && !is_dir_b){
    result = -1;
  }
  else{
    result = g_utf8_collate(name_a, name_b);
  }
  return result;
}

static GtkWidget* create_icon_view_widget(void)
{
  GtkWidget *iconview;
  GtkListStore *store;

  currentdir = g_get_current_dir();
  store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
  //標準ソート関数の設定
  gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), sort_func, NULL, NULL);
  //ソートに使用する項目の設定
  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);

  iconview = gtk_icon_view_new_with_model(GTK_TREE_MODEL(store));
  g_object_unref(store);

  return iconview;
}

static void cb_item_activated(GtkIconView *iconview, GtkTreePath *treepath, gpointer user_data)
{
  GtkListStore *store;
  GtkTreeIter iter;
  gchar *path;
  gboolean is_dir;

  store = GTK_LIST_STORE(gtk_icon_view_get_model(iconview));
  gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, treepath);
  gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
    COLUMN_PATH, &path,
    COLUMN_IS_DIRECTORY, &is_dir, -1);
  if( is_dir ){
    g_free( currentdir );
    currentdir = g_strdup(path);
    add_data(iconview);
  }
  g_free( path );
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *scroll_window;
  GtkWidget *iconview;

  gtk_init(&argc,&argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "FileBrowse");
  gtk_widget_set_size_request(window, 500, 300);
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(cb_quit), NULL);

  scroll_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), GTK_SHADOW_ETCHED_IN);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_container_add(GTK_CONTAINER(window), scroll_window);

  iconview = create_icon_view_widget();
  gtk_icon_view_set_text_column(GTK_ICON_VIEW(iconview), COLUMN_DISPLAY_NAME);
  gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(iconview), 80);
  g_signal_connect(G_OBJECT(iconview), "item-activated", G_CALLBACK(cb_item_activated), NULL);

  gtk_icon_view_set_margin(GTK_ICON_VIEW(iconview), 16);
  gtk_icon_view_set_item_width(GTK_ICON_VIEW(iconview), 80);
  gtk_icon_view_set_spacing(GTK_ICON_VIEW(iconview), 16);
  gtk_icon_view_set_column_spacing(GTK_ICON_VIEW(iconview), 32);
  gtk_icon_view_set_row_spacing(GTK_ICON_VIEW(iconview), 32);

  gtk_container_add(GTK_CONTAINER(scroll_window), iconview);

  add_data(GTK_ICON_VIEW(iconview));

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

一応ファイルブラウザにはなったけれど、アイコン表示ができず、 またプログラムの終了もうまくいかない。また課題が残った。

アイコンとラベルのサイズと位置設定は、上図の通り。


前章  | 目次 |  次章



トップ



/