#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

#include <gtk/gtk.h>

enum
  {
    PIXBUF_COLUMN,
    NAME_COLUMN,
    NUM_COLUMNS
  };

GdkPixbuf *pixbuf;

typedef struct _Programa Programa;
struct _Programa
{
  GtkWidget *main_window;
  GtkWidget *scrolled_win;

  GtkWidget *tree_view;

  GtkTreeStore *tree_model;
  GtkTreeSelection *tree_selection;
};

gboolean
sair_do_programa (GtkWidget *w, GdkEvent *event, gpointer data);

void
criar_nova_janela_cb (GtkWidget *botao, gpointer data);

void
mudou_selecao_cb (GtkWidget *w, gpointer data);

void
criar_colunas (Programa *prog);

void
criar_tree_model (Programa *prog);

void
criar_interface (Programa *prog);

void
adicionar_diretorio (Programa *prog, gchar *diretorio, GtkTreeIter *pai);

void
preencher_arvore (Programa *prog);

gboolean
sair_do_programa (GtkWidget *w, GdkEvent *event, gpointer data)
{
  gtk_main_quit ();
  return FALSE;
}

void
criar_nova_janela_cb (GtkWidget *botao, gpointer data)
{
  Programa *prog = (Programa*)data;
  Programa *novo = g_new (Programa, 1);

  criar_interface (novo);
  criar_colunas (novo);

  novo->tree_model = prog->tree_model;
  gtk_tree_view_set_model (GTK_TREE_VIEW(novo->tree_view),
			   GTK_TREE_MODEL(novo->tree_model));

  gtk_widget_show_all (novo->main_window);
}

void
mudou_selecao_cb (GtkWidget *w, gpointer data)
{
  Programa *prog = (Programa*)data;
  GtkTreeIter iter;

  gchar *selecao = NULL;

  if (!gtk_tree_selection_get_selected (prog->tree_selection,
					NULL, &iter))
    return;

  gtk_tree_model_get (GTK_TREE_MODEL(prog->tree_model),
		      &iter, NAME_COLUMN, &selecao, -1);
  printf ("seleção: %s\n", selecao);
  g_free (selecao);

}

void
deletar_linha_cb (GtkWidget *w, gpointer data)
{
  Programa *prog = (Programa*)data;
  GtkTreeIter iter;

  if (!gtk_tree_selection_get_selected (prog->tree_selection,
					NULL, &iter))
    return;

  gtk_tree_store_remove (GTK_TREE_STORE(prog->tree_model),
			 &iter);

}

void
criar_colunas (Programa *prog)
{
  GtkCellRenderer *cr;
  GtkTreeViewColumn *column;

  cr = gtk_cell_renderer_pixbuf_new ();
  column = gtk_tree_view_column_new_with_attributes ("Ícone",
						     cr,
						     "pixbuf", PIXBUF_COLUMN,
						     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(prog->tree_view),
			       column);

  cr = gtk_cell_renderer_text_new ();
  column = gtk_tree_view_column_new_with_attributes ("Nome",
						     cr,
						     "text", NAME_COLUMN,
						     NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW(prog->tree_view),
			       column);
}

void
criar_tree_model (Programa *prog)
{
  prog->tree_model = gtk_tree_store_new (NUM_COLUMNS,
					 GDK_TYPE_PIXBUF,
					 G_TYPE_STRING);

  gtk_tree_view_set_model (GTK_TREE_VIEW(prog->tree_view),
			   GTK_TREE_MODEL(prog->tree_model));
}

void
criar_interface (Programa *prog)
{
  GtkWidget *vbox;
  GtkWidget *botao;

  prog->main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (G_OBJECT(prog->main_window), "delete-event",
		    G_CALLBACK(sair_do_programa), NULL);
  gtk_window_set_default_size (GTK_WINDOW(prog->main_window),
			       640, 480);

  vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_add (GTK_CONTAINER(prog->main_window),
		     vbox);

  prog->scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  gtk_box_pack_start_defaults (GTK_BOX(vbox), prog->scrolled_win);

  prog->tree_view = gtk_tree_view_new ();
  gtk_container_add (GTK_CONTAINER(prog->scrolled_win),
		     prog->tree_view);

  prog->tree_selection =
    gtk_tree_view_get_selection (GTK_TREE_VIEW(prog->tree_view));
  g_signal_connect (G_OBJECT(prog->tree_selection), "changed",
		    G_CALLBACK(mudou_selecao_cb), prog);

  botao = gtk_button_new_with_label ("Deletar Linha");
  g_signal_connect (G_OBJECT(botao), "clicked",
		    G_CALLBACK(deletar_linha_cb),
		    prog);
  gtk_box_pack_start (GTK_BOX(vbox), botao, FALSE, FALSE, 0);


  botao = gtk_button_new_with_label ("Nova visão");
  g_signal_connect (G_OBJECT(botao), "clicked",
		    G_CALLBACK(criar_nova_janela_cb),
		    prog);
  gtk_box_pack_start (GTK_BOX(vbox), botao, FALSE, FALSE, 0);
}

void
adicionar_diretorio (Programa *prog, gchar *diretorio, GtkTreeIter *pai)
{
  DIR *d;
  struct dirent *dent;
  GtkTreeIter *iter = g_new (GtkTreeIter, 1);

  d = opendir (diretorio);
  if (!d)
    return;

  while (dent = readdir (d))
    {
      if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))
	continue;

      gchar *nome_absoluto =
	g_strdup_printf ("%s/%s", diretorio, dent->d_name);

      while (gtk_events_pending ())
	gtk_main_iteration_do (FALSE);

      gtk_tree_store_append (prog->tree_model,
			     iter, pai);
      gtk_tree_store_set (prog->tree_model, iter,
			  NAME_COLUMN, dent->d_name, -1);

      if (g_file_test (nome_absoluto, G_FILE_TEST_IS_DIR))
	{
	  gtk_tree_store_set (prog->tree_model, iter,
			      PIXBUF_COLUMN, pixbuf, -1);
	  adicionar_diretorio (prog, nome_absoluto, iter);
	}

      g_free (nome_absoluto);
    }
  closedir (d);

  gtk_tree_iter_free (iter);
}

void
preencher_arvore (Programa *prog)
{
  adicionar_diretorio (prog, "/etc/X11", NULL);
}

int
main (int argc, char **argv)
{
  Programa *prog = g_malloc (sizeof(Programa));

  gtk_init (&argc, &argv);

  pixbuf = gdk_pixbuf_new_from_file ("gnome-fs-directory.png",
				     NULL);

  criar_interface (prog);
  criar_colunas (prog);
  criar_tree_model (prog);
  preencher_arvore (prog);

  gtk_widget_show_all (prog->main_window);

  gtk_main ();

  return 0;
}