簡単なサンプル


エントリに文字列を入力すると、候補を表示させるプログラムを作成してみる。

#include <gtk/gtk.h>

enum
{
  COLUMN_COMPLETION_TEXT,
  N_COLUMNS
};

static GtkEntryCompletion* create_completion_widget(void)
{
  GtkEntryCompletion *completion;
  GtkListStore *store;
  GtkTreeIter iter;

  //エントリ補完ウィジェットの作成
  completion = gtk_entry_completion_new();
  //モデルの作成
  store = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING);
  //作成したモデルを登録
  gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store));
  g_object_unref(store);
  gtk_entry_completion_set_text_column(completion, 0);

  //補完用の文字列を登録
  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, COLUMN_COMPLETION_TEXT, "a", -1);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, COLUMN_COMPLETION_TEXT, "ai", -1);

  gtk_list_store_append(store, &iter);
  gtk_list_store_set(store, &iter, COLUMN_COMPLETION_TEXT, "aiu", -1);

  return completion;
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *entry;
  GtkEntryCompletion *completion;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "EntryCompletion");
  gtk_widget_set_size_request(window, 320, -1);
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  entry = gtk_entry_new();
  gtk_container_add(GTK_CONTAINER(window), entry);

  completion = create_completion_widget();
  gtk_entry_set_completion(GTK_ENTRY(entry), completion);
  g_object_unref(completion);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

エントリにaと入力すると、候補のaとai、aiuが表示される。

さらにaiと入力すると、候補がaiとaiuにしぼられる。

以上が、自身で候補を設定するプログラムのサンプルである。


ファイルブラウザ


前章で完成しなかったファイルブラウザを、エントリ補完ウィジェットを加えて作成してみる。

#include <gtk/gtk.h>

enum
{
  COLUMN_COMPLETION_TEXT,
  N_COMPLETION_COLUMNS
};

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

static GdkPixbuf *file_pixbuf, *folder_pixbuf;
static gchar* currentdir;

static GtkEntryCompletion* create_completion_widget(void)
{
  GtkEntryCompletion *completion;
  GtkTreeModel *completion_model;

  completion = gtk_entry_completion_new();
  completion_model = GTK_TREE_MODEL(gtk_list_store_new(N_COMPLETION_COLUMNS, G_TYPE_STRING));
  //補完文字列でソートするように設定
  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(completion_model), COLUMN_COMPLETION_TEXT, GTK_SORT_ASCENDING);
  gtk_entry_completion_set_model(completion, completion_model);
  g_object_unref(completion_model);
  gtk_entry_completion_set_text_column(completion, 0);

  return completion;
}

static void load_pixbuf(void)
{
  file_pixbuf = gdk_pixbuf_new_from_file("file.png", NULL);
  folder_pixbuf = gdk_pixbuf_new_from_file("folder.png", NULL);
}

static void add_data(GtkIconView *iconview, GtkEntryCompletion *completion)
{
  GtkListStore *iconview_store, *completion_store;
  GDir *dir;
  const gchar *name;
  GtkTreeIter iter;
  gchar *path, *display_name;
  gboolean is_dir;

  iconview_store = GTK_LIST_STORE(gtk_icon_view_get_model(iconview));
  completion_store = GTK_LIST_STORE(gtk_entry_completion_get_model(completion));

  gtk_list_store_clear(iconview_store);
  gtk_list_store_clear(completion_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(iconview_store, &iter);
      gtk_list_store_set(iconview_store, &iter,
        COLUMN_PATH, path,
        COLUMN_DISPLAY_NAME, display_name,
        COLUMN_IS_DIRECTORY, is_dir,
        COLUMN_PIXBUF, (is_dir) ? folder_pixbuf : file_pixbuf, -1);

      gtk_list_store_append(completion_store, &iter);
      gtk_list_store_set(completion_store, &iter, COLUMN_COMPLETION_TEXT, display_name, -1);
      g_free( path );
      g_free( display_name );
    }
  }
  g_dir_close( dir );

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

static gint sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer 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_ICONVIEW_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 data)
{
  GtkListStore *store;
  GtkTreeIter iter;
  gchar *path;
  gboolean is_dir;
  GtkEntryCompletion *completion;

  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, GTK_ENTRY_COMPLETION(data));
  }
  g_free( path );
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *vbox;
  GtkWidget *entry;
  GtkWidget *scrolled_window;
  GtkWidget *iconview;
  GtkEntryCompletion *completion;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "EntryCompletion");
  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);

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  gtk_container_add(GTK_CONTAINER(window), vbox);

  entry = gtk_entry_new();
  gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);

  completion = create_completion_widget();
  gtk_entry_set_completion(GTK_ENTRY(entry), completion);
  g_object_unref(completion);

  scrolled_window = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_ETCHED_IN);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);

  load_pixbuf();

  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), COLUMN_PIXBUF);
  gtk_icon_view_set_item_width(GTK_ICON_VIEW(iconview), 80);
  g_signal_connect(G_OBJECT(iconview), "item_activated", G_CALLBACK(cb_item_activated), completion);

  gtk_container_add(GTK_CONTAINER(scrolled_window), iconview);

  add_data(GTK_ICON_VIEW(iconview), completion);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

上部のエントリに文字を入力すると、カレントディレクトリ内のファイル名の候補が表示される。

ファイルブラウザ完成!


前章  | 目次 |  次章



トップ



/