[gnome-commander/treeview] treeview: merged the latest work
- From: Piotr Eljasiak <epiotr src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-commander/treeview] treeview: merged the latest work
- Date: Sun, 19 Dec 2010 21:11:52 +0000 (UTC)
commit 5db450001e776327846d51fecb3a5f0703dc2e59
Author: Guillaume Wardavoir <earlgrey free fr>
Date: Sun Dec 19 22:10:53 2010 +0100
treeview: merged the latest work
src/foldview/Makefile.am | 21 +-
.../gnome-cmd-connection-treeview-control.cc | 1908 ++++++++++++++++
...gnome-cmd-connection-treeview-control.snippet.h | 344 +++
.../gnome-cmd-connection-treeview-model-gio.cc | 935 ++++++++
.../gnome-cmd-connection-treeview-model-struct.cc | 1203 ++++++++++
...-cmd-connection-treeview-model-struct.snippet.h | 935 ++++++++
.../gnome-cmd-connection-treeview-model-vfs.cc | 1145 ++++++++++
.../gnome-cmd-connection-treeview-model.cc | 2363 ++++++++++++++++++++
.../gnome-cmd-connection-treeview-model.snippet.h | 402 ++++
src/foldview/gnome-cmd-connection-treeview-view.cc | 800 +++++++
.../gnome-cmd-connection-treeview-view.snippet.h | 323 +++
src/foldview/gnome-cmd-connection-treeview.cc | 262 +++
src/foldview/gnome-cmd-connection-treeview.h | 287 +++
src/foldview/gnome-cmd-foldview-docs.h | 944 ++++++++
src/foldview/gnome-cmd-foldview-logger.cc | 159 ++
src/foldview/gnome-cmd-foldview-logger.h | 194 ++
src/foldview/gnome-cmd-foldview-private.h | 1060 ++-------
src/foldview/gnome-cmd-foldview-quickstack.h | 252 +++
src/foldview/gnome-cmd-foldview-treestore.cc | 1916 ++++++++++++----
src/foldview/gnome-cmd-foldview-treestore.h | 486 +++--
src/foldview/gnome-cmd-foldview-utils.h | 261 +++
src/foldview/gnome-cmd-foldview.cc | 811 +++++---
src/foldview/gnome-cmd-foldview.h | 14 +-
23 files changed, 15303 insertions(+), 1722 deletions(-)
---
diff --git a/src/foldview/Makefile.am b/src/foldview/Makefile.am
index 2497845..49f6d52 100644
--- a/src/foldview/Makefile.am
+++ b/src/foldview/Makefile.am
@@ -12,12 +12,23 @@ AM_CPPFLAGS = \
noinst_LIBRARIES = libtreeview.a
libtreeview_a_SOURCES = \
- gnome-cmd-foldview.cc gnome-cmd-foldview.h \
- gnome-cmd-foldview-control.cc \
- gnome-cmd-foldview-gvfs.cc gnome-cmd-foldview-gvfs.h \
- gnome-cmd-foldview-model.cc \
+ gnome-cmd-connection-treeview-control.cc \
+ gnome-cmd-connection-treeview-control.snippet.h \
+ gnome-cmd-connection-treeview-model-gio.cc \
+ gnome-cmd-connection-treeview-model-struct.cc \
+ gnome-cmd-connection-treeview-model-struct.snippet.h \
+ gnome-cmd-connection-treeview-model-vfs.cc \
+ gnome-cmd-connection-treeview-model.cc \
+ gnome-cmd-connection-treeview-model.snippet.h \
+ gnome-cmd-connection-treeview-view.cc \
+ gnome-cmd-connection-treeview-view.snippet.h \
+ gnome-cmd-connection-treeview.cc gnome-cmd-connection-treeview.h \
+ gnome-cmd-foldview-docs.h\
+ gnome-cmd-foldview-logger.cc gnome-cmd-foldview-logger.h \
gnome-cmd-foldview-private.h \
+ gnome-cmd-foldview-quickstack.h \
gnome-cmd-foldview-treestore.cc gnome-cmd-foldview-treestore.h \
- gnome-cmd-foldview-view.cc
+ gnome-cmd-foldview-utils.h \
+ gnome-cmd-foldview.cc gnome-cmd-foldview.h
-include $(top_srcdir)/git.mk
diff --git a/src/foldview/gnome-cmd-connection-treeview-control.cc b/src/foldview/gnome-cmd-connection-treeview-control.cc
new file mode 100644
index 0000000..3a34baf
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-control.cc
@@ -0,0 +1,1908 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-control.cc
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : Control
+
+ Parent : GnomeCmdConnectionTreeview
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+#include "gnome-cmd-file-selector.h"
+#include "gnome-cmd-main-win.h"
+
+
+extern GnomeCmdMainWin *main_win;
+
+// ***************************************************************************
+//
+// Constructor, ...
+//
+// ***************************************************************************
+GnomeCmdConnectionTreeview::Control::Control(
+ GnomeCmdConnectionTreeview * _ctv)
+{
+ raz_pointers();
+ init_instance(_ctv);
+}
+
+GnomeCmdConnectionTreeview::Control::~Control()
+{
+ message_fifo_stop();
+ sorting_list_stop();
+}
+
+void
+GnomeCmdConnectionTreeview::Control::raz_pointers()
+{
+ a_connection_treeview = NULL;
+
+ d_message_fifo_first = NULL;
+ d_message_fifo_last = NULL;
+ a_message_fifo_card = 0;
+ a_message_fifo_id = 0;
+
+ d_sorting_list_first = NULL;
+ d_sorting_list_last = NULL;
+ a_sorting_list_card = 0;
+ a_sorting_list_id = 0;
+}
+void
+GnomeCmdConnectionTreeview::Control::init_instance(GnomeCmdConnectionTreeview * _ctv)
+{
+ a_connection_treeview = _ctv;
+
+ if ( ! message_fifo_start() )
+ {
+ GCMD_ERR("Control::create():Message FIFO didnt start");
+ }
+
+ if ( ! sorting_list_start() )
+ {
+ GCMD_ERR("Control::create():Sorting list didnt start");
+ }
+}
+
+void GnomeCmdConnectionTreeview::Control::dispose()
+{
+ GCMD_INF("GnomeCmdConnectionTreeview::Control::dispose()");
+}
+
+void GnomeCmdConnectionTreeview::Control::finalize()
+{
+ GCMD_INF("GnomeCmdConnectionTreeview::Control::finalize()");
+}
+
+
+// ***************************************************************************
+// Signals
+// ***************************************************************************
+void
+GnomeCmdConnectionTreeview::Control::Signal_button_refresh_clicked(
+ GtkButton * _button,
+ gpointer _user_data)
+{
+ Control * ctv = NULL;
+ //.........................................................................
+ //GCMD_INF("view:Signal_refresh_clicked");
+
+ ctv = ((View::HeadBand*)_user_data)->view()->control();
+
+ ctv->model()->iter_refresh(NULL);
+}
+void
+GnomeCmdConnectionTreeview::Control::Signal_button_sort_clicked(
+ GtkButton * _button,
+ gpointer _user_data)
+{
+ Control * ctv = NULL;
+ //.........................................................................
+ //GCMD_INF("view:Signal_sort_clicked");
+
+ ctv = ((View::HeadBand*)_user_data)->view()->control();
+
+ ctv->model()->iter_sort(NULL);
+}
+
+
+void
+GnomeCmdConnectionTreeview::Control::Signal_button_show_hide_clicked(
+ GtkButton * _button,
+ gpointer _user_data)
+{
+ Control * ctv = NULL;
+ //.........................................................................
+ ctv = ((View::HeadBand*)_user_data)->view()->control();
+
+ if ( ctv->view()->treeview_showed() )
+ {
+ ctv->view()->hide_treeview();
+ ctv->connection_treeview()->set_packing_expansion(FALSE);
+ }
+ else
+ {
+ ctv->view()->show_treeview();
+ ctv->connection_treeview()->set_packing_expansion(TRUE);
+ }
+}
+
+void
+GnomeCmdConnectionTreeview::Control::Signal_button_close_clicked(
+ GtkButton * _button,
+ gpointer _user_data)
+{
+ Control * ctv = NULL;
+ //.........................................................................
+ ctv = ((View::HeadBand*)_user_data)->view()->control();
+
+ ctv->connection_treeview()->close();
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # Contextual menu #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// The menu
+//
+// ***************************************************************************
+
+GnomeCmdConnectionTreeview::Control::ctx_menu GnomeCmdConnectionTreeview::Control::Context_menu =
+{
+ NULL, (gint)3,
+ {
+ {
+ _("Directory"), (gint)2,
+ {
+ // context connect title callback
+ {{ GCMD_B8(00000111), TRUE, _("Open in active tab"), G_CALLBACK(Set_active_tab) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000111), TRUE, _("Open in a new tab"), G_CALLBACK(Open_new_tab) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ }
+ },
+
+ {
+ _("Tree"), (gint)4,
+ {
+ //connect title callback
+ {{ GCMD_B8(00000111), TRUE, _("Create new tree"), G_CALLBACK(Tree_create) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00001111), TRUE, _("Delete this tree"), G_CALLBACK(Tree_delete) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000111), TRUE, _("Refresh from item"), G_CALLBACK(Refresh) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000111), TRUE, _("Sort from item"), G_CALLBACK(Sort) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ }
+ },
+
+ {
+ _("Treeview"), (gint)2,
+ {
+ //connect title callback
+ {{ GCMD_B8(00000111), FALSE, _("Sync treeview"), G_CALLBACK(Sync_treeview) }, NULL, (gulong)0 },
+ {{ GCMD_B8(10000000), FALSE, _("Unsync treeview"), G_CALLBACK(Unsync_treeview) }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ {{ GCMD_B8(00000000), FALSE, _(""), NULL }, NULL, (gulong)0 },
+ }
+ }
+ }
+};
+
+void GnomeCmdConnectionTreeview::Control::context_menu_populate_add_separator(GtkWidget *widget)
+{
+ gtk_menu_shell_append(GTK_MENU_SHELL(widget), gtk_separator_menu_item_new());
+}
+
+void GnomeCmdConnectionTreeview::Control::context_menu_pop(
+ View::ctx_menu_data *ctxdata)
+{
+ gboolean b_inserted = FALSE;
+ gint is,ie;
+ eContext context = eNothing;
+
+ GtkTreeIter iter_clicked = Model::Iter_zero;
+ GtkTreeIter iter_selected = Model::Iter_zero;
+
+ //.........................................................................
+
+ //
+ // paths -> iters & logic
+ //
+ if ( ctxdata->d_path_clicked )
+ if ( model()->get_iter(ctxdata->d_path_clicked, &iter_clicked) )
+ context = (eContext)(context | eClicked);
+
+ if ( ctxdata->d_path_selected )
+ if ( model()->get_iter(ctxdata->d_path_selected, &iter_selected) )
+ context = (eContext)(context | eSelected);
+
+ if ( context == eBoth )
+ if ( model()->iter_same(&iter_clicked, &iter_selected) )
+ context = (eContext)(context | eBothEqual);
+
+ if ( context & eSelected )
+ if ( model()->iter_is_root(&iter_selected) )
+ context = (eContext)(context | eSelectedIsRoot);
+
+ //
+ // create the popup & populate it
+ //
+ Context_menu.a_widget = gtk_menu_new();
+
+ for ( is = 0 ; is != Context_menu.a_card ; is++ )
+ {
+ ctx_menu_section section = Context_menu.a_section[is];
+ b_inserted = FALSE;
+
+ for ( ie = 0 ; ie != section.a_card ; ie++ )
+ {
+ ctx_menu_entry entry = section.a_entry[ie];
+ ctx_menu_desc desc = entry.a_desc;
+
+ // context does not match, quit
+ if ( ( desc.context() & context ) != desc.context() )
+ if ( ! ( desc.context() & eAlways ) )
+ continue;
+
+ // eventually add a separator
+ if ( !b_inserted && ie == 0 && is != 0 )
+ {
+ b_inserted = TRUE;
+ gtk_menu_shell_append(GTK_MENU_SHELL(Context_menu.a_widget), gtk_separator_menu_item_new());
+ }
+
+ // add the entry
+ entry.a_widget = gtk_menu_item_new_with_label(desc.a_text);
+
+ // dont disconnect current handler, coz these are new widgets
+ // at each popup
+
+ if ( ! desc.a_sensitive )
+ gtk_widget_set_sensitive(entry.a_widget,FALSE);
+ else
+ {
+ // connect with new ctx data
+ entry.a_handle = g_signal_connect(
+ entry.a_widget,
+ "activate",
+ desc.a_callback,
+ (gpointer)ctxdata);
+ }
+
+ // add to menu
+ gtk_menu_shell_append(GTK_MENU_SHELL(Context_menu.a_widget), entry.a_widget);
+ }
+ }
+
+ gtk_widget_show_all(Context_menu.a_widget);
+
+ // pop
+ // void gtk_menu_popup(
+ // GtkMenu *menu,
+ // GtkWidget *parent_menu_shell,
+ // GtkWidget *parent_menu_item,
+ // GtkMenuPositionFunc func,
+ // gpointer data,
+ // guint button,
+ // guint32 activate_time);
+ //
+ // menu : a GtkMenu.
+ // parent_menu_shell : the menu shell containing the triggering menu item, or NULL. [allow-none]
+ // parent_menu_item : the menu item whose activation triggered the popup, or NULL. [allow-none]
+ // func : a user supplied function used to position the menu, or NULL. [allow-none]
+ // data : user supplied data to be passed to func. [allow-none]
+ // button : the mouse button which was pressed to initiate the event.
+ // activate_time : the time at which the activation event occurred.
+ gtk_menu_popup(
+ GTK_MENU(Context_menu.a_widget), NULL, NULL,
+ NULL, NULL,
+ ctxdata->a_button, ctxdata->a_time);
+}
+
+// ***************************************************************************
+//
+// The actions
+//
+// ***************************************************************************
+void GnomeCmdConnectionTreeview::Control::Set_active_tab(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->set_active_tab(ctxdata->d_path_selected);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::set_active_tab(GtkTreePath *_path)
+{
+ GnomeCmdFileSelector * fs = NULL;
+ GnomeVFSURI * uri = NULL;
+ GnomeCmdPath * path = NULL;
+ GnomeCmdDir * dir = NULL;
+
+ GtkTreeIter iter = Model::Iter_zero;
+
+ Model::Row * row = NULL;
+ //.........................................................................
+ //GCMD_INF("control_open_active_tab");
+
+ fs = main_win->fs(ACTIVE);
+ if ( ! GNOME_CMD_IS_FILE_SELECTOR (fs) )
+ return;
+
+ if ( ! model()->get_iter(_path, &iter) )
+ return;
+
+ row = model()->iter_get_treerow(&iter);
+ g_return_if_fail( row );
+
+ // open the new tab
+ uri = gnome_vfs_uri_new(row->uri_utf8());
+ path = gnome_cmd_con_create_path(connection_treeview()->connection(), uri->text);
+ dir = gnome_cmd_dir_new(connection_treeview()->connection(), path);
+ fs->file_list()->set_connection(connection_treeview()->connection(), dir);
+ gnome_vfs_uri_unref(uri);
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Open_new_tab(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->open_new_tab(ctxdata->d_path_selected);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::open_new_tab(GtkTreePath *_path)
+{
+ //GnomeCmdDir * dir = NULL;
+ //GnomeCmdPath * path = NULL;
+
+ GtkTreeIter iter = Model::Iter_zero;
+ GtkTreeIter iter_tree = Model::Iter_zero;
+
+ Model::Row * rw = NULL;
+ Model::Row * rt = NULL;
+ //.........................................................................
+ //GCMD_INF("control_open_new_tab");
+
+ if ( !model()->get_iter(_path, &iter) )
+ return;
+
+ if ( !model()->iter_get_root(&iter, &iter_tree) )
+ return;
+
+ rw = model()->iter_get_treerow(&iter);
+ rt = model()->iter_get_treerow(&iter_tree);
+ g_return_if_fail( rt->is_root() );
+
+ // open the new tab
+ ////path = gnome_cmd_con_create_path(trt->connection(), trw->uri());
+ ////dir = gnome_cmd_dir_new(trt->connection(), path);
+ ////main_win->fs(ACTIVE)->new_tab(dir, TRUE);
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Tree_create(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->tree_create(ctxdata);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::tree_create(GnomeCmdConnectionTreeview::View::ctx_menu_data *ctxdata)
+{
+ GtkTreeIter iter_in = Model::Iter_zero;
+ GtkTreeIter iter_tree = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("control_tree_create");
+
+ if ( !model()->get_iter(ctxdata->d_path_selected, &iter_in) )
+ return;
+
+ model()->iter_add_tree(&iter_in, &iter_tree);
+ model()->iter_check_if_empty(&iter_tree);
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Tree_delete(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->tree_delete(ctxdata);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::tree_delete(GnomeCmdConnectionTreeview::View::ctx_menu_data *ctxdata)
+{
+ //GtkTreeIter iter_in = Model::Iter_zero;
+ GtkTreeIter iter_tree = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ GCMD_INF("Control::control_tree_delete()");
+
+ model()->get_iter(ctxdata->d_path_selected, &iter_tree);
+ model()->iter_remove(&iter_tree); // _GWR_SEND_MSG_
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Refresh(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->refresh(ctxdata);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::refresh(GnomeCmdConnectionTreeview::View::ctx_menu_data *ctxdata)
+{
+ GtkTreeIter iter = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("control_refresh");
+
+ if ( !model()->get_iter(ctxdata->d_path_selected, &iter) )
+ return;
+
+ model()->iter_refresh(&iter);
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Sort(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->sort(ctxdata);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::sort(GnomeCmdConnectionTreeview::View::ctx_menu_data *ctxdata)
+{
+ GtkTreeIter iter = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("control_sort");
+
+ if ( ! model()->get_iter(ctxdata->d_path_selected, &iter) )
+ return;
+
+ model()->iter_sort(&iter);
+}
+// ===========================================================================
+GnomeCmdConnectionTreeview::Control::eSyncState
+GnomeCmdConnectionTreeview::Control::sync_check()
+{
+ if ( !a_synced )
+ {
+ if ( !a_synced_list )
+ {
+ return SYNC_N_LIST_N;
+ }
+ else
+ {
+ return SYNC_N_LIST_Y;
+ }
+ }
+ else
+ {
+ if ( !a_synced_list )
+ {
+ return SYNC_Y_LIST_N;
+ }
+ else
+ {
+ return SYNC_Y_LIST_Y;
+ }
+ }
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Sync_update(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->sync_update(ctxdata);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::sync_update(GnomeCmdConnectionTreeview::View::ctx_menu_data *ctxdata)
+{
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("control_sync_update");
+
+ if ( sync_check() != SYNC_Y_LIST_Y )
+ {
+ //GCMD_WNG("control_sync_update:not SYNC_Y_LIST_Y:%03i", control_sync_check());
+ return;
+ }
+
+ if ( !model()->get_iter(ctxdata->d_path_clicked, &iter) )
+ return;
+
+ uri = gnome_vfs_uri_new( model()->iter_get_uri(&iter) );
+ if ( uri == NULL )
+ return;
+
+ ////control_gcmd_file_list_set_connection(a_synced_list, uri); // _GWR_STANDBY_
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Unsync_treeview(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->unsync_treeview();
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::unsync_treeview()
+{
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("control_unsync_treeview");
+
+ switch ( sync_check() )
+ {
+ case SYNC_N_LIST_N:
+ GCMD_WNG("control_unsync_treeview:not synced");
+ return;
+ break;
+
+ case SYNC_N_LIST_Y:
+ GCMD_ERR("control_unsync_treeview:* mismatch * SYNC_N_LIST_Y");
+ break;
+
+ case SYNC_Y_LIST_Y:
+ a_synced = FALSE;
+ g_object_remove_weak_pointer( G_OBJECT(a_synced_list), (gpointer*)(&a_synced_list) );
+ a_synced_list = NULL;
+ break;
+
+ case SYNC_Y_LIST_N:
+ GCMD_INF("control_unsync_treeview:SYNC_Y_LIST_N");
+ a_synced = FALSE;
+ break;
+ }
+}
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Control::Sync_treeview(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->sync_treeview(ctxdata);
+ delete ctxdata;
+}
+void GnomeCmdConnectionTreeview::Control::sync_treeview(GnomeCmdConnectionTreeview::View::ctx_menu_data *ctxdata)
+{
+ GnomeCmdFileList *list = NULL;
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("control_sync_treeview");
+
+ // We use weak pointers on the GnomeCmdFileList so if the user close
+ // the tab, we can know it coz the weak pointer is set to NULL by glib
+
+ if ( !model()->get_iter(ctxdata->d_path_selected, &iter) )
+ {
+ GCMD_WNG("control_sync_treeview:no selected item");
+ return;
+ }
+
+ uri = gnome_vfs_uri_new( model()->iter_get_uri(&iter) );
+ if ( uri == NULL )
+ {
+ GCMD_WNG("control_sync_treeview:iter_get_uri_new failed");
+ return;
+ }
+
+ list = main_win->fs(ACTIVE)->file_list();
+ if ( list == NULL )
+ {
+ GCMD_WNG("control_sync_treeview:coudnot get file_list");
+ return;
+ }
+
+ switch ( sync_check() )
+ {
+ // synchronize with the given list
+ case SYNC_N_LIST_N:
+ a_synced = TRUE;
+ a_synced_list = list;
+
+ g_object_add_weak_pointer( G_OBJECT(list), (gpointer*)(&a_synced_list) );
+
+ ////control_gcmd_file_list_set_connection(a_synced_list, uri); // _GWR_STANDBY_
+ break;
+
+ // we are synchronized with a file_list that was deleted
+ // simply synchronize with the given list
+ case SYNC_Y_LIST_N:
+ GCMD_WNG("control_sync_treeview:SYNC_Y_LIST_N");
+
+ a_synced = TRUE;
+ a_synced_list = list;
+
+ g_object_add_weak_pointer( G_OBJECT(list), (gpointer*)(&a_synced_list) );
+
+ ////control_gcmd_file_list_set_connection(a_synced_list, uri); // _GWR_STANDBY_
+ break;
+
+ case SYNC_Y_LIST_Y:
+ GCMD_WNG("control_sync_treeview:already synced");
+ break;
+
+ case SYNC_N_LIST_Y:
+ GCMD_ERR("control_unsync_treeview:* mismatch * SYNC_N_LIST_Y");
+ break;
+ }
+
+ // free temp uri
+ gnome_vfs_uri_unref(uri);
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # Messages #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// Messages : queue
+//
+// ***************************************************************************
+//
+// We use a GList :
+//
+// Push Pop
+// +---+ +---+
+// | | | |
+// v | v |
+//
+// x x---x---x---x---x---x---x---x---x
+// ^ ^
+// | |
+// Last First
+
+//GStaticMutex Message_queue_mutex = G_STATIC_MUTEX_INIT;
+
+// GThread * a_message_queue_thread;
+// GList * d_message_queue_list;
+
+void GnomeCmdConnectionTreeview::Control::message_fifo_lock()
+{
+ //g_static_mutex_lock(&Message_queue_mutex);
+}
+void GnomeCmdConnectionTreeview::Control::message_fifo_unlock()
+{
+ //g_static_mutex_unlock(&Message_queue_mutex);
+}
+
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Control::message_fifo_start()
+{
+ d_message_fifo_first = g_list_alloc();
+ d_message_fifo_first->data = NULL;
+
+ d_message_fifo_last = d_message_fifo_first;
+
+ a_message_fifo_card = 0;
+
+ a_message_fifo_id = g_timeout_add(GCMDGTKFOLDVIEW_REFRESH_CYCLE_PERIOD_MS, Message_fifo_func_timeout, (gpointer)this);
+ if ( a_message_fifo_id == 0 )
+ return FALSE;
+
+ //a_message_queue_thread = g_thread_create(
+ // Message_queue_func_thread,
+ // (gpointer)this,
+ // FALSE,
+ // NULL);
+
+ return TRUE;
+}
+gboolean
+GnomeCmdConnectionTreeview::Control::message_fifo_stop()
+{
+ g_source_remove(a_message_fifo_id);
+ return TRUE;
+}
+
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Control::message_fifo_push(
+ Model::MsgCore* _msg)
+{
+ message_fifo_lock();
+
+ if ( ! _msg )
+ goto lab_failure;
+
+ d_message_fifo_last->data = (gpointer)_msg;
+ d_message_fifo_last = g_list_prepend(d_message_fifo_last, NULL);
+
+ a_message_fifo_card++;
+ //FIFO_INF("FIFO:message_fifo_push():Total :%04i", d_message_fifo_count);
+
+lab_exit:
+ sorting_list_unlock();
+ return TRUE;
+
+lab_failure:
+ sorting_list_unlock();
+ return FALSE;
+}
+
+GnomeCmdConnectionTreeview::Model::MsgCore*
+GnomeCmdConnectionTreeview::Control::message_fifo_pop()
+{
+ Model::MsgCore * msg = NULL;
+ //.........................................................................
+ message_fifo_lock();
+
+ msg = (Model::MsgCore*)d_message_fifo_first->data;
+
+ // message : change d_message_fifo_first
+ if ( msg )
+ {
+ d_message_fifo_first = d_message_fifo_first->prev;
+ g_list_free1(d_message_fifo_first->next);
+
+ a_message_fifo_card--;
+ //FIFO_INF("FIFO:message_fifo_pop() :Remaining:%04i", d_message_fifo_count);
+ }
+
+ message_fifo_unlock();
+
+ return msg;
+}
+
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Control::Message_fifo_func_timeout(
+ gpointer _data)
+{
+ GtkTreeIter iter = Model::Iter_zero;
+ Control * THIS = NULL;
+ Model::MsgCore * msg = NULL;
+ guint i = 0;
+ //.........................................................................
+ THIS = (Control*)_data;
+
+ //FIFO_INF("Model::FIFO:Called");
+
+ for ( i = 0 ; i != GCMDGTKFOLDVIEW_REFRESH_CYCLE_N_MESSAGES ; i++ )
+ {
+ THIS->message_fifo_lock();
+ msg = THIS->message_fifo_pop();
+ THIS->message_fifo_unlock();
+
+ if ( ! msg )
+ break;
+
+ FIFO_INF("message loop :( %03i of %03i ) [%s]",
+ (1 + i),
+ GCMDGTKFOLDVIEW_REFRESH_CYCLE_N_MESSAGES,
+ Model::Msg_name(msg->type()));
+
+
+ switch ( msg->type() )
+ {
+
+ case Model::eAddFirstTree :
+ THIS->iter_message_add_first_tree( (Model::MsgAddFirstTree*)msg );
+ break;
+
+ case Model::eAddChild :
+ THIS->iter_message_add_child( (Model::MsgAddChild*)msg );
+ break;
+
+ case Model::eAddDummyChild :
+ THIS->iter_message_add_dummy_child( (Model::MsgAddDummyChild*)msg );
+ break;
+
+ case Model::eDel :
+ THIS->iter_message_del( (Model::MsgDel*)msg );
+ break;
+
+ case Model::eSetReadable :
+ THIS->iter_message_set_readable( (Model::MsgSetReadable*)msg );
+ break;
+
+ case Model::eSetNotReadable :
+ THIS->iter_message_set_not_readable( (Model::MsgSetNotReadable*)msg );
+ break;
+
+ case Model::eAsyncMismatchIEFUC :
+ THIS->iter_message_AsyncMismatchIEFUC( (Model::MsgAsyncMismatchIEFUC*)msg );
+ break;
+
+ case Model::eAsyncMismatchICIEC :
+ THIS->iter_message_AsyncMismatchICIEC( (Model::MsgAsyncMismatchICIEC*)msg );
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ return TRUE;
+}
+
+// ***************************************************************************
+//
+// Messages : actions
+//
+// ***************************************************************************
+
+// ============================================================================
+// iter_message_add_first_tree
+// ============================================================================
+//
+// Create the first iter
+//
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_add_first_tree(
+ Model::MsgAddFirstTree * _msg)
+{
+ Model::IterInfo info;
+ Model::Row * row_new = NULL;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //
+ // Step #1 : Test iter :
+ // - existenz
+ //
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eNothing) )
+ {
+ MSG_WNG("iter_message_add_first_tree():gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Check if directory added is empty / not empty
+ //
+ MSG_INF("iter_message_add_first_tree():adding %s", _msg->file()->name_utf8() );
+
+ if ( _msg->file()->is_symlink() )
+ {
+ row_new = new Model::Row(
+ Model::eRowRoot, info.row()->uri_utf8(), _msg->file()->name_utf8(), (gchar*)((Model::Symlink*)_msg->file())->target_uri(),
+ _msg->file()->access(), TRUE,
+ is_samba(), is_local(), host_redmond());
+ }
+ else
+ {
+ row_new = new Model::Row(
+ Model::eRowRoot, info.row()->uri_utf8(), _msg->file()->name_utf8(), NULL,
+ _msg->file()->access(), FALSE,
+ is_samba(), is_local(), host_redmond());
+ }
+
+ // replace treerow by the new one, signal will be emitted
+ model()->iter_set_treerow(info.iter(), row_new);
+
+ // launch check if empty
+ model()->iter_check_if_empty(info.iter());
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+
+
+/// ==========================================================================
+/// iter_message_add_child()
+/// ==========================================================================
+///
+/// Add a child to an iter
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_add_child(
+ Model::MsgAddChild * _msg)
+{
+ Model::IterInfo info;
+ GtkTreeIter iter_child = Model::Iter_zero;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //
+ // Step #1 : Test iter :
+ // - readable
+ // - expanded
+ //
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eRead | IterInfo::eExp | IterInfo::eChildren | IterInfo::eFCID) )
+ {
+ MSG_WNG("iter_message_add_child():gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ if ( info.collapsed() )
+ {
+ MSG_WNG("iter_message_add_child():iter is collapsed"); // _GWR_CHECK_ arrow after expand
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( info.first_child_is_dummy() )
+ {
+ MSG_INF("iter_message_add_child():replacing dummy %s", _msg->file()->name_utf8() );
+ model()->iter_files_add_file(info.iter(), &iter_child, _msg->file(), FALSE, TRUE);
+ }
+ else
+ {
+ MSG_INF("iter_message_add_child():adding %s", _msg->file()->name_utf8() );
+ model()->iter_files_add_file(info.iter(), &iter_child, _msg->file(), FALSE, FALSE);
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Check if directory added is empty / not empty
+ //
+ if ( Access_readable(_msg->file()->access()) )
+ model()->iter_check_if_empty(&iter_child);
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+
+/// ==========================================================================
+/// iter_message_add_dummy_child()
+/// ==========================================================================
+///
+/// Add a dummy child to an iter
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_add_dummy_child(
+ Model::MsgAddDummyChild * _msg)
+{
+ Model::IterInfo info;
+ GtkTreeIter iter_dummy = Model::Iter_zero;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1 : Test iter :
+ // - readable
+ // - no children, except one dummy child
+ //
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eRead | IterInfo::eFCID) )
+ {
+ MSG_WNG("iter_message_add_dummy_child():Gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ if ( ! info.readable() )
+ {
+ MSG_WNG("iter_message_add_dummy_child():NOT Readable");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( info.children() )
+ {
+ if ( info.children() > 1 )
+ {
+ MSG_WNG("iter_message_add_dummy_child():iter has more than one child");
+ goto lab_exit_false;
+ }
+ if ( ! info.first_child_is_dummy() )
+ {
+ MSG_WNG("iter_message_add_dummy_child():iter has an unique child, but not a dummy");
+ goto lab_exit_false;
+ }
+ }
+
+ //.........................................................................
+ //
+ // Step #1 : Add the dummy child
+ //
+
+ //MSG_INF("iter_message_add_dummy_child():adding");
+ model()->iter_dummy_child_add(info.iter(), &iter_dummy);
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+
+
+/// ==========================================================================
+/// iter_message_del()
+/// ==========================================================================
+///
+/// Delete an iter
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_del(
+ Model::MsgDel * _msg)
+{
+ Model::IterInfo info;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //
+ // Step #1 : Test iter :
+ // - must exist
+ //
+
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eExp | IterInfo::eChildren | IterInfo::eGtkPath ) )
+ {
+ MSG_WNG("iter_message_del():Gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ // iter is sterile : goto remove_sterile
+ if ( ! info.children() )
+ goto remove_sterile;
+
+ //.........................................................................
+ // iter is fertile, and is expanded
+ if ( info.expanded() )
+ {
+ // It is a hack ! Let GtkTreeView update its cache by collapsing !
+ // We dont have to manually delete each row and signals on them !
+ if ( ! view()->row_collapse(info.gtk_path()) ) // __GWR__HACK__
+ {
+ GCMD_ERR("iter_message_del():iter could not be collapsed");
+ goto lab_exit_false;
+ }
+
+ // We dont return here, since the iter is in the following state !
+ }
+
+ //.........................................................................
+ // iter is fertile, and is not expanded. Silently remove all children.
+ // After that, we are in the following case.
+ model()->iter_collapsed_remove_children(info.iter());
+
+ //.........................................................................
+ // iter is sterile :remove it, and send "removed row" signal. But first
+ // stop monitoring
+remove_sterile:
+ model()->iter_monitor_stop(info.iter());
+
+ if ( model()->treestore()->ext_iter_sterile_remove(info.iter()) < 0 )
+ {
+ GCMD_ERR("iter_message_del():ext_iter_sterile_remove < 0");
+ goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+
+/// ==========================================================================
+/// iter_message_set_readable()
+/// ==========================================================================
+///
+/// Set an iter readable
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_set_readable(
+ Model::MsgSetReadable * _msg)
+{
+ Model::IterInfo info;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ // Step #1 : Test iter : iter must :
+ // - be not readable
+ // - be not expanded
+ // - have no child
+ //
+ if ( ! info.gather(model(), _msg->path() , IterInfo::eExp | IterInfo::eChildren) )
+ {
+ MSG_WNG("iter_message_set_readable():Gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ // already readable : abort
+ if ( info.readable() )
+ {
+ MSG_WNG("iter_message_set_readable():iter already readable [%s]", info.row()->utf8_name_display());
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( info.expanded() )
+ {
+ MSG_WNG("iter_message_set_readable():iter is expanded");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( info.children() )
+ {
+ MSG_WNG("iter_message_set_readable():iter has children");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ // All is ok
+
+ // change data
+ info.row()->readable(TRUE);
+
+ // inform treview that row has changed
+ model()->treestore()->ext_data_changed(info.iter());
+
+ // launch check if empty
+ model()->iter_check_if_empty(info.iter());
+
+ //.........................................................................
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+
+/// ==========================================================================
+/// iter_message_set_not_readable()
+/// ==========================================================================
+///
+/// Set an iter not readable
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_set_not_readable(
+ Model::MsgSetNotReadable * _msg)
+{
+ Model::IterInfo info;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1 : Test iter : iter must :
+ // - be readable
+ //
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eRead | IterInfo::eExp | IterInfo::eGtkPath | IterInfo::eChildren) )
+ {
+ MSG_WNG("iter_message_set_not_readable():Gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ // already not-readable : abort
+ if ( ! info.readable() )
+ {
+ MSG_WNG("iter_message_set_not_readable():already not-readable [%s]", info.row()->utf8_name_display());
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Go !
+ //
+
+ // if no children, unset directly
+ if ( ! info.children() )
+ goto lab_iter_sterile;
+
+ //.........................................................................
+ // iter is fertile, and expanded : collapse it
+ if ( info.expanded() )
+ {
+ // It is a hack ! Let GtkTreeView update its cache by collapsing !
+ // We dont have to manually delete each row and signals on them !
+ if ( ! view()->row_collapse( info.gtk_path() ) ) // __GWR__HACK__
+ {
+ MSG_ERR("iter_message_set_not_readable():iter could not be collapsed");
+ }
+
+ // We dont return here, since the iter is in the following state !
+ }
+
+ //.........................................................................
+ // iter is fertile, and collapsed : silently remove children
+ model()->iter_collapsed_remove_children(info.iter());
+
+ //.........................................................................
+ // Here iter is sterile
+lab_iter_sterile:
+
+ // change data
+ info.row()->readable(FALSE);
+
+ // inform treview that row has changed
+ model()->treestore()->ext_data_changed(info.iter());
+
+ //.........................................................................
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+
+/// ==========================================================================
+/// iter_message_AsyncMismatchIEFUC()
+/// ==========================================================================
+///
+/// ...
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_AsyncMismatchIEFUC(
+ Model::MsgAsyncMismatchIEFUC * _msg)
+{
+ Model::IterInfo info;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1 : Test iter : iter must
+ // - be expanded
+ // - dummychilded
+ //
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eRead | IterInfo::eExp | IterInfo::eFCID) )
+ {
+ MSG_WNG("iter_message_AsyncMismatchIEFUC():Gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ if ( ! info.first_child_is_dummy() )
+ {
+ MSG_WNG("iter_message_AsyncMismatchIEFUC():Not dummychilded");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( ! info.expanded() )
+ {
+ MSG_WNG("iter_message_AsyncMismatchIEFUC():Not expanded");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( ! info.readable() )
+ {
+ MSG_WNG("iter_message_AsyncMismatchIEFUC():Not readable");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Show warning icon
+ //
+ info.row()->icon(eIconWarning);
+ model()->treestore()->ext_data_changed(info.iter());
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+/// ==========================================================================
+/// iter_message_AsyncMismatchICIEC()
+/// ==========================================================================
+///
+/// ...
+///
+gboolean
+GnomeCmdConnectionTreeview::Control::iter_message_AsyncMismatchICIEC(
+ Model::MsgAsyncMismatchICIEC * _msg)
+{
+ Model::IterInfo info;
+ //.........................................................................
+ Model::Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1 : Test iter : iter must
+ // - exist
+ //
+ if ( ! info.gather(model(), _msg->path(), IterInfo::eNothing) )
+ {
+ MSG_WNG("iter_message_AsyncMismatchIEFUC():Gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Show warning icon
+ //
+ info.row()->icon(eIconWarning);
+ model()->treestore()->ext_data_changed(info.iter());
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return TRUE;
+lab_exit_false:
+ delete _msg;
+ model()->treestore()->ext_dump_tree(NULL);
+ Model::Unlock(); // _GDK_LOCK_
+ return FALSE;
+}
+// ###########################################################################
+// ### ###
+// ## ##
+// # Sorting #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// Sorting : list & timeout function
+//
+// ***************************************************************************
+//
+// We use a GList :
+//
+// Add ( outside code ) control code
+// +---+ +---+
+// | | | |
+// v | v |
+//
+// x x---x---x---x---x---x---x---x---x
+// ^ ^
+// | |
+// Last First
+//
+
+//GStaticMutex Sorting_list_mutex = G_STATIC_MUTEX_INIT;
+
+// GThread * a_sorting_list_thread;
+
+void GnomeCmdConnectionTreeview::Control::sorting_list_lock()
+{
+ //g_static_mutex_lock(&Message_queue_mutex);
+}
+void GnomeCmdConnectionTreeview::Control::sorting_list_unlock()
+{
+ //g_static_mutex_unlock(&Message_queue_mutex);
+}
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Control::sorting_list_start()
+{
+ d_sorting_list_first = g_list_alloc();
+ d_sorting_list_first->data = NULL;
+
+ d_sorting_list_last = d_sorting_list_first;
+
+ a_sorting_list_card = 0;
+
+ a_sorting_list_id = g_timeout_add(GCMDGTKFOLDVIEW_SORTING_CYCLE_PERIOD_MS, Sorting_list_func_timeout, (gpointer)this);
+ if ( a_sorting_list_id == 0 )
+ return FALSE;
+
+ //a_message_queue_thread = g_thread_create(
+ // Message_queue_func_thread,
+ // (gpointer)this,
+ // FALSE,
+ // NULL);
+
+ return TRUE;
+}
+gboolean
+GnomeCmdConnectionTreeview::Control::sorting_list_stop()
+{
+ g_source_remove(a_sorting_list_id);
+ return TRUE;
+}
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Control::sorting_list_add(
+ Model::MsgCore* _msg)
+{
+ sorting_list_lock();
+
+ if ( ! _msg )
+ goto lab_failure;
+
+ d_sorting_list_last->data = (gpointer)_msg;
+ a_sorting_list_card++;
+
+ d_sorting_list_last = g_list_prepend(d_sorting_list_last, NULL);
+
+ //FIFO_INF("FIFO:message_fifo_push():Total :%04i", d_message_fifo_count);
+
+lab_exit:
+ sorting_list_unlock();
+ return TRUE;
+
+lab_failure:
+ sorting_list_unlock();
+ return FALSE;
+}
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Control::Sorting_list_func_timeout(
+ gpointer _data)
+{
+ GtkTreeIter iter = Model::Iter_zero;
+ Control * THIS = NULL;
+ Model::IMsgSort * msg = NULL;
+
+ guint i = 0;
+ GList * list = NULL;
+ GList * temp = NULL;
+ //.........................................................................
+ THIS = (Control*)_data;
+
+ //SORT_INF(" --> Sort Function : %03i sort messages", THIS->a_sorting_list_card);
+
+ THIS->sorting_list_lock();
+
+ i = 1;
+ list = THIS->d_sorting_list_first;
+
+ while ( list->data )
+ {
+ //SORT_INF(" --> Sort function <--");
+
+ msg = (Model::IMsgSort*)(list->data);
+
+ //SORT_INF(" --> Sort function :sorting msg ( %03i of %03i )",
+ // i,
+ // THIS->a_sorting_list_card);
+
+ // something happend...
+ if ( msg->run() )
+ {
+ // ...in all cases, we have to delete the message :
+ //
+ // <== way
+ //
+ // .
+ // .
+ // .
+ // last . first
+ // | . |
+ // v . v
+ // x-----x-----x-----x-----x-----x
+ // ^ . ^
+ // | . |
+ // NULL. msg
+ // .
+ //
+
+ // ...something bad
+ if ( msg->error() )
+ {
+ SORT_ERR(" --> Sort function :sorting failed");
+ }
+
+ // ...something good
+ if ( msg->done() )
+ {
+ SORT_TKI(" --> Sort function :sorting done");
+ }
+
+ // delete message
+ delete msg;
+
+ // delete link
+ if ( list == THIS->d_sorting_list_first )
+ {
+ THIS->d_sorting_list_first = THIS->d_sorting_list_first->prev;
+ g_list_free1(list);
+ temp = THIS->d_sorting_list_first;
+ }
+ else
+ {
+ temp = g_list_previous(list);
+ list->prev->next = list->next;
+ list->next->prev = list->prev;
+ g_list_free1(list);
+ }
+
+ // prepare next round
+ list = temp;
+ i++;
+ }
+ // nothing happend
+ else
+ {
+ // prepare next round
+ list = g_list_previous(list);
+ i++;
+ }
+ }
+
+ THIS->sorting_list_unlock();
+
+ return TRUE;
+}
+
+// ***************************************************************************
+//
+// Sorting : IMsgSort
+//
+// ***************************************************************************
+
+GnomeCmdConnectionTreeview::Model::IMsgSort::IMsgSort(
+ TreestorePath * _path,
+ Model * _model) : MsgCore(_path)
+{
+ a_step = eInit;
+ a_iteration = 0;
+ a_initialized = FALSE;
+ a_error = FALSE;
+ a_done = FALSE;
+
+ a_model = _model;
+
+ d_list_original = NULL;
+ d_list_actual = NULL;
+ a_list_card = 0;
+}
+
+GnomeCmdConnectionTreeview::Model::IMsgSort::~IMsgSort()
+{
+ list_delete(&d_list_original);
+ list_delete(&d_list_actual);
+}
+
+
+// ===========================================================================
+// List manipulation
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::IMsgSort::list_changed()
+{
+ GList * l1 = NULL;
+ GList * l2 = NULL;
+ //.........................................................................
+ if ( ! d_list_actual || ! d_list_original )
+ return TRUE;
+
+ l1 = d_list_original; // since we prepend, it is the first element
+ l2 = d_list_actual; // ...idem...
+
+ while ( TRUE )
+ {
+ // one NULL
+ if ( ! l1 || ! l2 )
+ {
+ // two NULL : no change
+ if ( l1 == l2 )
+ {
+ //SORT_TEK("IMsgSort::list_changed():l1 [%08x]->[%08x] l2 [%08x]->[%08x]", l1, l1 ? l1->data : 0, l2, l2 ? l2->data : 0);
+ return FALSE;
+ }
+
+ // one NULL, one not NULL : change
+ //if ( l1 ) SORT_TEK("IMsgSort::list_changed():l1 [%08x]->[%08x] l2 [%08x]->[%08x]", l1, l1 ? l1->data : 0, l2, l2 ? l2->data : 0);
+ //if ( l2 ) SORT_TEK("IMsgSort::list_changed():l1 [%08x]->[%08x] l2 [%08x]->[%08x] l2+[%08x]", l1, l1 ? l1->data : 0, l2, l2 ? l2->data : 0, l2->next);
+ return TRUE;
+ }
+
+ // here two are not NULL ; if data differ : change
+ //SORT_TEK("IMsgSort::list_changed():l1 [%08x]->[%08x] l2 [%08x]->[%08x]", l1, l1 ? l1->data : 0, l2, l2 ? l2->data : 0);
+
+ if ( l1->data != l2->data )
+ return TRUE;
+
+ // loop
+ l1 = g_list_next(l1);
+ l2 = g_list_next(l2);
+ }
+
+ return FALSE;
+}
+void
+GnomeCmdConnectionTreeview::Model::IMsgSort::list_delete(
+ GList ** _list)
+{
+ GList * list = NULL;
+ //.........................................................................
+ if ( ! _list )
+ return;
+
+ list = *_list;
+
+ // list = g_list_first(_list);
+ //while ( list )
+ //{
+ // delete (TreestorePath*)(list->data);
+ // list = g_list_next(list);
+ //}
+
+ g_list_free(*_list);
+ *_list = NULL;
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::IMsgSort::list_get(
+ GList ** _list)
+{
+ Model::IterInfo info;
+ GtkTreeIter child = Iter_zero;
+ guint count = 0;
+ //.........................................................................
+ //
+ // get & verify info on iter
+ //
+ if ( ! info.gather(a_model, path(), IterInfo::eRead | IterInfo::eExp | IterInfo::eChildren) )
+ {
+ SORT_TKE("IMsgSort::list_update():Gather failed");
+ return FALSE;
+ }
+
+ if (
+ ! info.readable() ||
+ ! info.expanded()
+ )
+ {
+ SORT_TKI("IMsgSort::list_update():Iter is not sortable");
+ return FALSE;
+ }
+
+ //
+ // delete the list
+ //
+ list_delete(_list);
+
+ //
+ // build the list from model
+ //
+ if ( ! GnomeCmdFoldviewTreestore::iter_children(model()->treemodel(), &child, info.iter()) )
+ return FALSE;
+
+ do
+ {
+ *_list = g_list_prepend
+ (
+ *_list,
+ (gpointer)(model()->iter_get_treerow(&child))
+ );
+
+ count++;
+ }
+ while ( GnomeCmdFoldviewTreestore::iter_next(model()->treemodel(), &child) );
+
+ //SORT_TEK("IMsgSort::list_update():%03i children [%08x] [%08x] [%08x]", count, g_list_last((*_list)), g_list_last((*_list))->prev, g_list_last((*_list))->next);
+
+ return TRUE;
+}
+void
+GnomeCmdConnectionTreeview::Model::IMsgSort::list_original_copy(
+ GList ** _dest)
+{
+ if ( *_dest )
+ {
+ SORT_TKE("IMsgSort::list_original_copy():destion list not NULL");
+ return;
+ }
+
+ // affect the list
+ *_dest = g_list_copy(d_list_original);
+}
+// ===========================================================================
+// Run
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::IMsgSort::run()
+{
+
+ //.........................................................................
+ if ( a_step == eInit )
+ {
+ // build list_original
+ if ( ! list_get(&d_list_original) )
+ {
+ SORT_TKI("IMsgSort::run(): [init ] list_get(original) failed - aborting");
+ a_step = eAbort;
+ goto lab_exit;
+ }
+
+ a_list_card = g_list_length(d_list_original);
+
+ // build list_actual
+ list_delete(&d_list_actual);
+ list_original_copy(&d_list_actual);
+
+ if ( ! init() )
+ {
+ SORT_TKE("IMsgSort::run(): [init ] init() failed - aborting");
+ a_step = eAbort;
+ goto lab_exit;
+ }
+
+ a_initialized = TRUE;
+
+ a_step = eRun;
+
+ return 0;
+ }
+
+ //.........................................................................
+ if ( a_step == eRun )
+ {
+ // build list_actual
+ if ( ! list_get(&d_list_actual) )
+ {
+ SORT_TKI("IMsgSort::run(): [run ] list_get(actual) failed - aborting");
+ a_step = eAbort;
+ goto lab_exit;
+ }
+
+ // if list is modified, restart the sort process
+ if ( list_changed() )
+ {
+ SORT_TKI("IMsgSort::run(): [run ] list changed - restarting");
+ a_step = eRestart;
+ goto lab_exit;
+ }
+
+ // else do an iteration
+ a_iteration++;
+
+ if ( step() )
+ {
+ a_step = eDone;
+ goto lab_exit;
+ }
+ }
+
+ //.........................................................................
+ if ( a_step == eRestart )
+ {
+ list_delete(&d_list_original);
+ list_delete(&d_list_actual);
+
+ a_iteration = 0;
+ a_initialized = FALSE;
+ a_error = FALSE;
+ a_done = FALSE;
+
+ d_list_original = NULL;
+ d_list_actual = NULL;
+ a_list_card = 0;
+
+ // restart the sort
+ if ( ! restart() )
+ {
+ SORT_TKE("IMsgSort::run(): [restart] sort restart failed - aborting");
+ a_step = eAbort;
+ goto lab_exit;
+ }
+
+ a_step = eInit;
+ goto lab_exit;
+ }
+
+ //.........................................................................
+ if ( a_step == eDone )
+ {
+ list_delete(&d_list_original);
+ list_delete(&d_list_actual);
+
+ a_done = TRUE;
+ a_step = eNop;
+
+ return TRUE;
+ }
+
+ //.........................................................................
+ if ( a_step == eAbort )
+ {
+ list_delete(&d_list_original);
+ list_delete(&d_list_actual);
+
+ a_error = TRUE;
+ a_step = eNop;
+
+ return TRUE;
+ }
+
+ //.........................................................................
+ if ( a_step == eNop )
+ {
+ SORT_TKW("IMsgSort::run(): [nop ] running for nothing !!!");
+ return TRUE;
+ }
+
+ //.........................................................................
+lab_exit:
+ return FALSE;
+}
+// ===========================================================================
+// Spread
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::IMsgSort::spread()
+{
+ SORT_INF("IMsgSort::spread():not implemented");
+ return TRUE;
+}
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-control.snippet.h b/src/foldview/gnome-cmd-connection-treeview-control.snippet.h
new file mode 100644
index 0000000..e97fc01
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-control.snippet.h
@@ -0,0 +1,344 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-control.snippet.h
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : Control
+
+ Parent : GnomeCmdConnectionTreeView
+
+ This file is directly inluded in gnome-cmd-connection-treeview.h
+
+ ###########################################################################
+*/
+
+// ***************************************************************************
+// #define
+// ***************************************************************************
+// ===========================================================================
+//
+// ===========================================================================
+
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview::View
+//
+// ###########################################################################
+struct Control
+{
+ // ***********************************************************************
+ // * *
+ // * Enums, ... *
+ // * *
+ // ***********************************************************************
+ typedef Model::IterInfo IterInfo;
+ // =======================================================================
+ //
+ // =======================================================================
+ // ***********************************************************************
+ // * *
+ // * Structs *
+ // * *
+ // ***********************************************************************
+
+
+
+ // ***********************************************************************
+ // * *
+ // * Members *
+ // * *
+ // ***********************************************************************
+ private:
+ GnomeCmdConnectionTreeview * a_connection_treeview;
+
+ // =======================================================================
+ // divers
+ // =======================================================================
+
+
+ // ***********************************************************************
+ // * *
+ // * Methods *
+ // * *
+ // ***********************************************************************
+ // =======================================================================
+ // new, ...
+ // =======================================================================
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ void raz_pointers();
+ void init_instance(GnomeCmdConnectionTreeview*);
+
+ public:
+ Control(GnomeCmdConnectionTreeview*);
+ ~Control();
+
+ void dispose();
+ void finalize();
+ // =======================================================================
+ // Accessors, ...
+ // =======================================================================
+ private:
+ inline Model * model() { return a_connection_treeview->model(); }
+ inline View * view() { return a_connection_treeview->view(); }
+ inline GnomeCmdConnectionTreeview * connection_treeview() { return a_connection_treeview; }
+ public:
+ inline GtkWidget * widget() { return view()->widget(); }
+
+ void show();
+ void hide();
+ void update_style();
+ // =======================================================================
+ // wrappers on Model
+ // =======================================================================
+ public:
+ inline void iter_check_if_empty (GtkTreeIter* _iter) { model()->iter_check_if_empty(_iter); }
+ inline void iter_expanded_from_ui (GtkTreeIter* _iter, gboolean _replace_dummy) { model()->iter_expanded_from_ui(_iter, _replace_dummy); }
+ inline void iter_collapsed_from_ui (GtkTreeIter* _iter) { model()->iter_collapsed_from_ui(_iter); }
+ // =======================================================================
+ // wrappers on View
+ // =======================================================================
+ public:
+ eRowState row_state(GtkTreePath* _path) { return view()->row_state(_path); }
+ gboolean row_collapse(GtkTreePath* _path) { return view()->row_collapse(_path); }
+ // =======================================================================
+ // wrappers on GnomeCmdConnectionTreeview
+ // =======================================================================
+ public:
+ inline gboolean is_samba() { return a_connection_treeview->is_samba(); }
+ inline gboolean is_local() { return a_connection_treeview->is_local(); }
+ inline gboolean host_redmond() { return a_connection_treeview->host_redmond(); }
+ inline GnomeCmdCon * connection() { return a_connection_treeview->connection(); }
+ // =======================================================================
+ // Widgets signals
+ // =======================================================================
+ public:
+ static void Signal_button_refresh_clicked (GtkButton*, gpointer);
+ static void Signal_button_sort_clicked (GtkButton*, gpointer);
+ static void Signal_button_show_hide_clicked (GtkButton*, gpointer);
+ static void Signal_button_close_clicked (GtkButton*, gpointer);
+ // =======================================================================
+ // Context menu
+ // =======================================================================
+ // -----------------------------------------------------------------------
+ // Context menu code
+ // -----------------------------------------------------------------------
+ public:
+ enum eContext
+ {
+
+ eNothing = 0 ,
+
+ eSelected = GCMD_B8(00000001) ,
+ eClicked = GCMD_B8(00000010) ,
+ eBoth = GCMD_B8(00000011) ,
+ eBothEqual = GCMD_B8(00000111) ,
+
+ eSelectedIsRoot = GCMD_B8(00001000) ,
+
+ eAlways = GCMD_B8(10000000)
+ };
+
+ private:
+ struct ctx_menu_desc
+ {
+ gint a_context; // context on which the entry has to be added
+ gboolean a_sensitive; // wether the entry has to be sensitive
+ gchar *a_text;
+ GCallback a_callback;
+
+ eContext context() { return (eContext)a_context; }
+ };
+ struct ctx_menu_entry
+ {
+ ctx_menu_desc a_desc;
+ GtkWidget *a_widget;
+ gulong a_handle;
+ };
+ struct ctx_menu_section
+ {
+ gchar *a_title;
+ gint a_card;
+ ctx_menu_entry a_entry[5];
+ };
+ struct ctx_menu
+ {
+ GtkWidget *a_widget;
+ gint a_card;
+ ctx_menu_section a_section[5];
+ };
+
+ static ctx_menu Context_menu;
+
+ void context_menu_populate_add_separator(GtkWidget *widget);
+ void context_menu_populate_add_section(GtkWidget *widget, gint i, View::ctx_menu_data *ctxdata);
+ void context_menu_populate(GtkWidget*, View::ctx_menu_data*);
+ public:
+ void context_menu_pop(View::ctx_menu_data*);
+
+ // -----------------------------------------------------------------------
+ // Context menu : User actions
+ // -----------------------------------------------------------------------
+ private:
+ void set_active_tab (GtkTreePath *path);
+ void open_new_tab (GtkTreePath *path);
+ void tree_create (View::ctx_menu_data*);
+ void tree_delete (View::ctx_menu_data*);
+ void refresh (View::ctx_menu_data*);
+ void sort (View::ctx_menu_data*);
+ public:
+ static void Set_active_tab (GtkMenuItem*, View::ctx_menu_data*);
+ static void Open_new_tab (GtkMenuItem*, View::ctx_menu_data*);
+ static void Tree_create (GtkMenuItem*, View::ctx_menu_data*);
+ static void Tree_delete (GtkMenuItem*, View::ctx_menu_data*);
+ static void Refresh (GtkMenuItem*, View::ctx_menu_data*);
+ static void Sort (GtkMenuItem*, View::ctx_menu_data*);
+
+ private:
+ enum eSyncState
+ {
+ SYNC_Y_LIST_Y,
+ SYNC_Y_LIST_N,
+ SYNC_N_LIST_Y,
+ SYNC_N_LIST_N
+ };
+ eSyncState sync_check ();
+ private:
+ void sync_treeview (View::ctx_menu_data*);
+ void unsync_treeview ();
+ void sync_update (View::ctx_menu_data*);
+ public:
+ static void Sync_treeview (GtkMenuItem*, View::ctx_menu_data*);
+ static void Unsync_treeview (GtkMenuItem*, View::ctx_menu_data*);
+ static void Sync_update (GtkMenuItem*, View::ctx_menu_data*);
+
+ private:
+ GnomeCmdFileList * a_synced_list;
+ gboolean a_synced;
+
+ // =======================================================================
+ // Controller : Messages
+ // =======================================================================
+ //
+ // Messages are implemented in the controller rather than in the model
+ // because :
+ //
+ // - Model is getting bloated
+ //
+ // - some actions need to act on the model, but on the view too (
+ // ex : remove an iter, implemented with a hack ( _GWR_HACK_ ) ). That
+ // is not allowed to a model.
+ //
+
+ // -----------------------------------------------------------------------
+ // Message queue
+ // -----------------------------------------------------------------------
+ private:
+ GList * d_message_fifo_first;
+ GList * d_message_fifo_last;
+ guint32 a_message_fifo_card;
+ guint a_message_fifo_id;
+
+ void message_fifo_lock();
+ void message_fifo_unlock();
+
+ gboolean message_fifo_start();
+ gboolean message_fifo_stop();
+
+ Model::MsgCore * message_fifo_pop();
+ static gboolean Message_fifo_func_timeout(gpointer);
+
+ public:
+ gboolean message_fifo_push(Model::MsgCore*);
+ // -----------------------------------------------------------------------
+ // Messages actions
+ // -----------------------------------------------------------------------
+ private:
+ gboolean iter_message_add_first_tree (Model::MsgAddFirstTree *);
+ gboolean iter_message_add_child (Model::MsgAddChild *);
+ gboolean iter_message_add_dummy_child (Model::MsgAddDummyChild *);
+ gboolean iter_message_del (Model::MsgDel *);
+ gboolean iter_message_set_readable (Model::MsgSetReadable *);
+ gboolean iter_message_set_not_readable (Model::MsgSetNotReadable *);
+ gboolean iter_message_AsyncMismatchIEFUC (Model::MsgAsyncMismatchIEFUC*);
+ gboolean iter_message_AsyncMismatchICIEC (Model::MsgAsyncMismatchICIEC*);
+ // =======================================================================
+ // Controller : Sorting
+ // =======================================================================
+ //
+ // Sorting is implemented in the controller rather than in the model
+ // because :
+ //
+ // - Model is getting bloated
+ //
+ // - some actions need to act on the model, but on the view too (
+ // ex : remove an iter, implemented with a hack ( _GWR_HACK_ ) ). That
+ // is not allowed to a model.
+ //
+
+ // -----------------------------------------------------------------------
+ // Sorting list
+ // -----------------------------------------------------------------------
+ public:
+ GList * d_sorting_list_first;
+ GList * d_sorting_list_last;
+ guint32 a_sorting_list_card;
+ guint a_sorting_list_id;
+
+ void sorting_list_lock();
+ void sorting_list_unlock();
+
+ gboolean sorting_list_start();
+ gboolean sorting_list_stop();
+
+ gboolean sorting_list_add(Model::MsgCore*);
+
+ static gboolean Sorting_list_func_timeout(gpointer);
+ //static gpointer Sorting_list_func_thread(gpointer);
+
+ // -----------------------------------------------------------------------
+ // Sorting : done in specific messages
+ // -----------------------------------------------------------------------
+
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-model-gio.cc b/src/foldview/gnome-cmd-connection-treeview-model-gio.cc
new file mode 100644
index 0000000..35d520c
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-model-gio.cc
@@ -0,0 +1,935 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : many, vfs specific
+
+ Parent : GnomeCmdConnectionTreeview::Model
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+// ***************************************************************************
+// * Defines *
+// ***************************************************************************
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # GIO structs #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// Enumerate children
+//
+// ***************************************************************************
+
+// ===========================================================================
+// GioAsyncEnumerateChildren
+// ===========================================================================
+struct GnomeCmdConnectionTreeview::Model::GioAsyncEnumerateChildren : AsyncEnumerateChildren
+{
+ private:
+ GFile * d_gfile;
+ GCancellable * d_gcancellable_1; // ..._enumerate_children_async
+ GCancellable * d_gcancellable_2; // ..._next_files_async
+
+ public:
+ void* operator new (size_t) ;
+ void operator delete (void*);
+
+ GioAsyncEnumerateChildren(AsyncCallerData*, const Uri, gint _max_result, gboolean _follow_links) ;
+ virtual ~GioAsyncEnumerateChildren();
+
+ public:
+ GFile * gfile() { return d_gfile; }
+ GCancellable * gcancellable_1() { return d_gcancellable_1; }
+ GCancellable * gcancellable_2() { return d_gcancellable_2; }
+};
+
+void*
+GnomeCmdConnectionTreeview::Model::GioAsyncEnumerateChildren::operator new(size_t _size)
+{
+ return (void*)(g_try_new0(GioAsyncEnumerateChildren, 1));
+}
+
+void
+GnomeCmdConnectionTreeview::Model::GioAsyncEnumerateChildren::operator delete (void *_p)
+{
+ g_free(_p);
+}
+
+
+GnomeCmdConnectionTreeview::Model::GioAsyncEnumerateChildren::GioAsyncEnumerateChildren(
+ AsyncCallerData * _caller_data,
+ const Uri _uri,
+ gint _max_result,
+ gboolean _follow_links)
+ : AsyncEnumerateChildren(_caller_data, _uri, _max_result, _follow_links)
+{
+ d_gfile = g_file_new_for_uri( uri() );
+ d_gcancellable_1 = g_cancellable_new();
+ d_gcancellable_2 = g_cancellable_new();
+}
+
+GnomeCmdConnectionTreeview::Model::GioAsyncEnumerateChildren::~GioAsyncEnumerateChildren()
+{
+ g_object_unref(d_gcancellable_1);
+ g_object_unref(d_gcancellable_2);
+}
+
+// ***************************************************************************
+//
+// Monitoring
+//
+// ***************************************************************************
+
+// ===========================================================================
+// GioMonitorHelper
+// ===========================================================================
+//
+// This struct is for g_file_query_info_finish usage simplification
+//
+struct GnomeCmdConnectionTreeview::Model::GioMonitorHelper
+{
+ GFileInfo * d_g_file_info;
+ GFileType a_type;
+ eFileAccess a_access;
+ const gchar * a_display_name;
+ gboolean a_is_symlink;
+ const gchar * a_symlink_target_display_name;
+};
+
+// ===========================================================================
+// GioMonitor
+// ===========================================================================
+void*
+GnomeCmdConnectionTreeview::Model::GioMonitor::operator new(size_t size)
+{
+ return (void*)g_try_new0(GioMonitor, 1);
+}
+void
+GnomeCmdConnectionTreeview::Model::GioMonitor::operator delete(void *p)
+{
+ g_free(p);
+}
+
+GnomeCmdConnectionTreeview::Model::GioMonitor::GioMonitor()
+{
+}
+GnomeCmdConnectionTreeview::Model::GioMonitor::~GioMonitor()
+{
+ MONITOR_INF("Model::GioMonitor::~GioMonitor()");
+
+ g_object_unref(d_file);
+ g_object_unref(d_monitor);
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::GioMonitor::monitoring_start(Model* _model, Row* row)
+{
+ GCancellable * cancellable = NULL;
+ GError * gerror = NULL;
+
+ MonitorData * md = NULL;
+ //.........................................................................
+
+ // GFileMonitor* g_file_monitor_directory(
+ // GFile * file,
+ // GFileMonitorFlags flags,
+ // GCancellable * cancellable,
+ // GError ** error);
+ //
+ // file : input GFile.
+ // flags : a set of GFileMonitorFlags.
+ // cancellable : optional GCancellable object, NULL to ignore.
+ // error : a GError, or NULL.
+ // Returns : a GFileMonitor for the given file, or NULL on error.
+
+ md = (MonitorData*)g_try_new0(MonitorData,1);
+ if ( ! md )
+ {
+ MONITOR_ERR("Model::GioMonitor::start():g_try_new0 failed for m0");
+ return FALSE;
+ }
+ md->a_model = _model;
+ md->a_row = row;
+
+ d_file = g_file_new_for_uri(row->uri_utf8());
+ if ( ! d_file )
+ {
+ MONITOR_ERR("Model::GioMonitor::start():Could not create GFile for uri %s", row->uri_utf8());
+ return FALSE;
+ }
+
+ d_monitor = g_file_monitor_directory(
+ d_file,
+ G_FILE_MONITOR_NONE,
+ cancellable, // NULL, since we are monothreaded
+ &gerror);
+
+ if ( ! d_monitor )
+ {
+ MONITOR_ERR("Model::GioMonitor::start():Failure [%s] %s", row->uri_utf8(), gerror->message);
+ return FALSE;
+ }
+
+ a_signal_handle = g_signal_connect(d_monitor, "changed", G_CALLBACK(GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback), (gpointer)md);
+ if ( ! a_signal_handle )
+ {
+ MONITOR_ERR("Model::GioMonitor::start():Could not connect signal [%s]", row->uri_utf8());
+ return FALSE;
+ }
+ else
+ {
+ MONITOR_INF("Model::GioMonitor::start():Signal handle [%s] [0x%16x]", row->uri_utf8(), a_signal_handle);
+ }
+
+ MONITOR_INF("Model::GioMonitor::start():Success [%s] [%s]", row->path()->dump(), row->uri_utf8());
+
+ Monitor::a_started = TRUE;
+
+ return TRUE;
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::GioMonitor::monitoring_stop()
+{
+ if ( !g_file_monitor_cancel(d_monitor ))
+ {
+ MONITOR_ERR("Model::GioMonitor::stop():Failed");
+ return FALSE;
+ }
+
+ MONITOR_INF("Model::GioMonitor::stop():Success");
+
+ Monitor::a_started = FALSE;
+
+ return TRUE;
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # Model Wrappers #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// Enumerate children
+//
+// ***************************************************************************
+
+// ===========================================================================
+// GIO::iter_check_if_empty
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::GIO::iter_check_if_empty(
+ AsyncCallerData * _acd,
+ const Uri _uri)
+{
+ GioAsyncEnumerateChildren * gaec = NULL;
+ //.........................................................................
+ gaec = new GioAsyncEnumerateChildren(_acd, _uri, 1, TRUE);
+
+
+ CHECK_INF("Model::GIO::iter_check_if_empty:%s", gaec->uri());
+
+ g_file_enumerate_children_async(
+ gaec->gfile(),
+ "standard::display-name,standard::type,standard::is-symlink,standard::symlink-target,access::can-read,access::can-write",
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ Iter_enumerate_children_callback_1,
+ (gpointer)gaec);
+}
+
+// ===========================================================================
+// GIO::iter_expand
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::GIO::iter_enumerate_children(
+ AsyncCallerData * _acd,
+ const Uri _uri)
+{
+ GioAsyncEnumerateChildren * gaec = NULL;
+ //.........................................................................
+ gaec = new GioAsyncEnumerateChildren(_acd, _uri, -1, TRUE);
+
+ // void g_file_enumerate_children_async(
+ // GFile * file,
+ // const char * attributes,
+ // GFileQueryInfoFlags flags,
+ // int io_priority,
+ // GCancellable * cancellable,
+ // GAsyncReadyCallback callback,
+ // gpointer user_data)
+ //
+ // file : input GFile.
+ // attributes : an attribute query string.
+ // flags : a set of GFileQueryInfoFlags.
+ // io_priority : the I/O priority of the request.
+ // cancellable : optional GCancellable object, NULL to ignore.
+ // callback : a GAsyncReadyCallback to call when the request is satisfied
+ // user_data : the data to pass to callback function
+ g_file_enumerate_children_async(
+ gaec->gfile(),
+ "standard::display-name,standard::type,standard::is-symlink,standard::symlink-target,access::can-read,access::can-write",
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ Iter_enumerate_children_callback_1,
+ (gpointer)gaec);
+}
+
+//=============================================================================
+// GnomeVFS::iter_file_info
+//=============================================================================
+void
+GnomeCmdConnectionTreeview::Model::GIO::iter_get_file_info(
+ AsyncCallerData * _acd,
+ const Uri _uri)
+{
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # GIO methods #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// Enumerate children
+//
+// ***************************************************************************
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Enumerate children : GIO callback 1
+//
+// Here we get a GFileEnumerator, on which we have to call another
+// async function to get GFileInfos.
+//
+// We init the request, and in the callback, this call we be done again
+// and again, until all GFileInfos have been get
+//
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Iter_enumerate_children_callback_1(
+ GObject * _source_object,
+ GAsyncResult * _res,
+ gpointer _data)
+{
+ GError * gerror = NULL;
+ GFileEnumerator * gfe = NULL;
+ //.........................................................................
+
+ // finish async query
+ gfe = g_file_enumerate_children_finish((GFile*)_source_object, _res, &gerror);
+ if ( !gfe )
+ {
+ ENUMERATE_ERR("Model::GIO::ecc_1():g_file_enumerate_children_finish failed [%s]", gerror->message);
+ return;
+ }
+
+ // get the GFileInfos :
+
+ // void g_file_enumerator_next_files_async(
+ // GFileEnumerator * enumerator,
+ // int num_files,
+ // int io_priority,
+ // GCancellable * cancellable,
+ // GAsyncReadyCallback callback,
+ // gpointer user_data);
+ //
+ // enumerator : a GFileEnumerator.
+ // num_files : the number of file info objects to request
+ // io_priority : the io priority of the request.
+ // cancellable : optional GCancellable object, NULL to ignore.
+ // callback : a GAsyncReadyCallback to call when the request is satisfied
+ // user_data : the data to pass to callback function
+
+ g_file_enumerator_next_files_async(
+ gfe,
+ 10,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ Iter_enumerate_children_callback_2,
+ _data);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Enumerate children : GIO callback 2
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Iter_enumerate_children_callback_2(
+ GObject * _source_object,
+ GAsyncResult * _res,
+ gpointer _data)
+{
+ GioAsyncEnumerateChildren * gaec = NULL;
+ AsyncCallerData * acd = NULL;
+
+ GError * gerror = NULL;
+ GList * list = NULL;
+
+ gint count = 0;
+ gint added = 0;
+ GFileInfo * file_info = NULL;
+ GFileType file_type = G_FILE_TYPE_UNKNOWN;
+ const gchar * file_display_name = NULL;
+ const gchar * file_display_name_ck = NULL;
+ gboolean b_read;
+ gboolean b_write;
+ eFileAccess file_access = eAccessUN;
+ gboolean file_is_symlink = FALSE;
+ const gchar * file_symlink_target_name = NULL;
+
+ File * file = NULL;
+ //.........................................................................
+
+ gaec = (GioAsyncEnumerateChildren*)_data;
+ acd = (AsyncCallerData*)(gaec->caller_data());
+
+ //.........................................................................
+ // finish query
+ list = g_file_enumerator_next_files_finish((GFileEnumerator*)_source_object, _res, &gerror);
+ if ( ! list )
+ {
+ // end of enumeration
+ if ( ! gerror )
+ goto lab_eof;
+
+ // error
+ ENUMERATE_ERR("Model::GIO::ecc_2():g_file_enumerator_next_files_finish failed [%s]", gerror->message);
+ goto lab_error;
+ }
+
+ //.........................................................................
+ // init loop
+ count = 0;
+ list = g_list_first(list);
+
+ //.........................................................................
+ // lOOooOOp
+lab_loop:
+
+ count++;
+
+ // get infos
+ file_info = (GFileInfo*)(list->data);
+
+ file_display_name = g_file_info_get_attribute_string(file_info, "standard::display-name");
+ if ( file_display_name == NULL )
+ {
+ ENUMERATE_ERR("Model::GIO::ecc_2():g_file_info_get_attribute_string (standard::display_name) failed");
+ goto lab_error;
+ }
+ file_display_name_ck = g_utf8_collate_key(file_display_name, -1);
+ //ENUMERATE_INF("Model:ecc_2():%s", file_display_name);
+
+ file_type = (GFileType)g_file_info_get_attribute_uint32(file_info, "standard::type");
+ if ( file_type == 0 )
+ {
+ ENUMERATE_ERR("Model::GIO::ecc_2():g_file_info_get_attribute_uint32 (standard::type) failed");
+ goto lab_error;
+ }
+
+ b_read = g_file_info_get_attribute_boolean(file_info, "access::can-read");
+ b_write = g_file_info_get_attribute_boolean(file_info, "access::can-write");
+ file_access = Access_from_read_write(b_read, b_write);
+
+ file_is_symlink = g_file_info_get_attribute_boolean(file_info, "standard::is-symlink");
+ file_symlink_target_name = g_file_info_get_attribute_byte_string(file_info, "standard::symlink-target");
+
+
+ switch ( file_type )
+ {
+ //.....................................................................
+ case G_FILE_TYPE_SYMBOLIC_LINK:
+
+ // if follow_links is TRUE, we should not be here - except if we have
+ // a BROKEN LINK. We thus cant know if the link was pointing on a
+ // directory or something else. LNK struct handle broken links
+ // if you pass NULL as the file pointer in constructor.
+ if ( gaec->follow_links() )
+ {
+ ENUMERATE_WNG("Model::GIO::ecc_2():[%03i][%03i] - broken symlink, ignored [%s]", count, added, file_display_name);
+ break;
+ }
+
+ //ENUMERATE_INF("Model:ecc_2():[%03i][%03i] - symlink, ignored [%s]", count, added, file_display_name);
+
+ //added++;
+ //ALSC_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] S<%s>", ga->hi(), l, count, added, ga->mr(), info->name);
+ //lnk = new LNK(g_strdup(info->name), g_strdup(info->symlink_name), info->permissions, info->flags );
+ //ls->append( (gvfs_file*)lnk );
+ // if the caller want partial listing
+ //if (
+ // ( ga->mr() >= 0 ) &&
+ // ( ls->len() >= ga->mr() )
+ // )
+ // goto lab_abort;
+
+ break;
+
+ //.....................................................................
+ case G_FILE_TYPE_DIRECTORY:
+
+ if ( strcmp(GnomeCmdConnectionTreeview::Collate_key_dot, file_display_name_ck ) &&
+ strcmp(GnomeCmdConnectionTreeview::Collate_key_dotdot, file_display_name_ck ))
+ {
+ added++;
+
+ ENUMERATE_INF("Model::GIO::ecc_2():[%03i][%03i] +[%s]", count, added, file_display_name);
+
+ // it is a symlink pointing on a directory
+ if ( file_is_symlink )
+ file = new FoldviewLink(file_display_name, file_symlink_target_name, file_access);
+ // it is a directory
+ else
+ file = new FoldviewDir(file_display_name, file_access);
+
+ gaec->list_append( file );
+
+ // if the caller want partial listing
+ if (
+ ( gaec->max_result() >= 0 ) &&
+ ( gaec->list_card() >= gaec->max_result() )
+ )
+ goto lab_partial_listing;
+ }
+ break;
+
+ //.....................................................................
+ default:
+ ENUMERATE_INF("Model::GIO::ecc_2():[%03i][%03i] [%s]", count, added, file_display_name);
+ }
+
+ list = g_list_next(list);
+ if ( ! list )
+ goto lab_no_more_entry;
+
+ goto lab_loop;
+
+//.............................................................................
+lab_eof:
+
+ ENUMERATE_INF("Model::GIO::ecc_2():EOF");
+ // Call caller callback ; caller is responsible for freeing memory
+ // eventually allocated in m_user_data member
+ // of the struct_gvfs_caller_data
+ gaec->caller_data()->callback()(gaec);
+
+ goto lab_end;
+
+//.............................................................................
+lab_no_more_entry:
+
+ ENUMERATE_INF("Model::GIO::ecc_2():NO MORE ENTRY - relaunching");
+ // relaunch same request
+ g_file_enumerator_next_files_async(
+ (GFileEnumerator*)_source_object,
+ 10,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ Iter_enumerate_children_callback_2,
+ _data);
+
+ g_free((void*)file_display_name_ck);
+ return;
+
+//.............................................................................
+lab_partial_listing:
+
+ ENUMERATE_INF("Model::GIO::ecc_2():PARTIAL LISTING REACHED [%03i]", gaec->max_result());
+ // Call caller callback ; caller is responsible for freeing memory
+ // eventually allocated in m_user_data member
+ // of the struct_gvfs_caller_data
+ gaec->caller_data()->callback()(gaec);
+
+ //goto lab_end;
+
+//.............................................................................
+lab_error:
+lab_end:
+
+ // delete the GioAsyncEnumerateChildren
+ delete gaec;
+
+ if ( file_display_name_ck )
+ g_free((void*)file_display_name_ck);
+
+ return;
+}
+
+// ***************************************************************************
+//
+// Monitoring
+//
+// ***************************************************************************
+
+// ===========================================================================
+// Monitoring : static callback
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback(
+ GFileMonitor * _monitor,
+ GFile * _file,
+ GFile * _other_file,
+ GFileMonitorEvent _event_type,
+ gpointer _data)
+{
+ MonitorData * md = NULL;
+
+ GAsyncReadyCallback callback = NULL;
+ GFile * gfile_to_scan = NULL;
+ gboolean b_self = FALSE;
+ //.........................................................................
+ // G_FILE_MONITOR_EVENT_CHANGED
+ // G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
+ // G_FILE_MONITOR_EVENT_DELETED
+ // G_FILE_MONITOR_EVENT_CREATED
+ // G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED
+ // G_FILE_MONITOR_EVENT_PRE_UNMOUNT
+ // G_FILE_MONITOR_EVENT_UNMOUNTED
+ //.........................................................................
+
+ //MONITOR_INF("Model::GIO::Monitor_callback():EVENT");
+
+ md = (MonitorData*)_data;
+ g_return_if_fail( md );
+
+ b_self = ( _file == _other_file ? TRUE : FALSE );
+
+ switch ( _event_type )
+ {
+ //.....................................................................
+ // file created in directory
+ // chmod, ... on directory
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ MONITOR_INF("Model::GIO::Monitor_callback():EVENT_CHANGED [%s]", md->a_row->utf8_name_display());
+
+ // file created : exit
+ if ( ! b_self )
+ goto abort;
+
+ // chmod, ...
+ callback = Monitor_callback_acc;
+ gfile_to_scan = _file;
+ break;
+
+ //.....................................................................
+ // file / subdirectory deleted in directory
+ //
+ // _other_file is always NULL ; the file that was deleted is _file.
+ //
+
+ case G_FILE_MONITOR_EVENT_DELETED:
+
+ MONITOR_INF("Model::GIO::Monitor_callback():EVENT_DELETED [%s] [%s]", md->a_row->utf8_name_display(), g_file_get_basename(_file));
+
+
+ if ( b_self )
+ {
+ // Parent deleted :
+ //MONITOR_INF("Model::GIO::Monitor_callback():EVENT_DELETED (SELF)", md->a_row->utf8_name_display());
+ //Monitor_callback_del(md);
+ goto exit;
+ }
+ else
+ {
+ // Child deleted :
+ // not getting file info, since the file is...deleted
+ //MONITOR_INF("Model::GIO::Monitor_callback():EVENT_DELETED (CHILD) [%s] [0x%016x]", md->a_row->utf8_name_display(), _other_file);
+ //Monitor_callback_child_del(md);
+ goto exit;
+ }
+ break;
+
+ //.....................................................................
+ // subdirectory created in directory
+ case G_FILE_MONITOR_EVENT_CREATED:
+ MONITOR_INF("Model::GIO::Monitor_callback():EVENT_CREATED [%s]", md->a_row->utf8_name_display());
+ callback = Monitor_callback_child_new;
+ gfile_to_scan = _file;
+ break;
+
+ //.....................................................................
+ case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
+ MONITOR_INF("Model::GIO::Monitor_callback():ATTRIBUTE_CHANGED [%s]", md->a_row->utf8_name_display());
+ callback = Monitor_callback_child_acc;
+ gfile_to_scan = _other_file;
+ goto exit;
+ break;
+
+ case G_FILE_MONITOR_EVENT_PRE_UNMOUNT :
+ case G_FILE_MONITOR_EVENT_UNMOUNTED :
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT :
+ MONITOR_INF("Model::GIO::Monitor_callback():OTHER_EVENT [%s]", md->a_row->utf8_name_display());
+ goto abort;
+ }
+
+ // void g_file_query_info_async(
+ // GFile * file,
+ // const char * attributes,
+ // GFileQueryInfoFlags flags,
+ // int io_priority,
+ // GCancellable * cancellable,
+ // GAsyncReadyCallback callback,
+ // gpointer user_data);
+ //
+ // file : input GFile.
+ // attributes : an attribute query string.
+ // flags : a set of GFileQueryInfoFlags.
+ // io_priority : the I/O priority of the request.
+ // cancellable : optional GCancellable object, NULL to ignore.
+ // callback : a GAsyncReadyCallback to call when the request is satisfied
+ // user_data : the data to pass to callback function
+ //
+ // Asynchronously gets the requested information about specified file.
+ // The result is a GFileInfo object that contains key-value attributes
+ // (such as type or size for the file). For more details, see
+ // g_file_query_info() which is the synchronous version of this call.
+ // When the operation is finished, callback will be called. You can then
+ // call g_file_query_info_finish() to get the result of the operation.
+
+ g_file_query_info_async(
+ gfile_to_scan,
+ "standard::type,standard::display-name,standard::is-symlink,standard::symlink-target,access::*",
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ callback,
+ (gpointer)md);
+
+ return;
+
+abort:
+exit:
+ return;
+}
+
+// ===========================================================================
+// Monitoring : query_info static callback
+// ===========================================================================
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitoring : query_info static callback helper
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gboolean
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback_helper_query_info(
+ const gchar * _event_str,
+ GObject * _source_object,
+ GAsyncResult * _res,
+ gpointer _data,
+ MonitorData * _md,
+ GioMonitorHelper * _gmh)
+{
+ GError * gerror = NULL;
+ //.........................................................................
+ _gmh->d_g_file_info = NULL;
+ _gmh->a_type = G_FILE_TYPE_UNKNOWN;
+ _gmh->a_access = eAccessUN;
+ _gmh->a_display_name = NULL;
+ _gmh->a_is_symlink = FALSE;
+ _gmh->a_symlink_target_display_name = NULL;
+
+ // GFileInfo*
+ // g_file_query_info_finish(
+ // GFile * file,
+ // GAsyncResult * res,
+ // GError ** error)
+ //
+ // Finishes an asynchronous file info query.
+ //
+ // file : input GFile.
+ // res : a GAsyncResult.
+ // error : a GError.
+ // Returns : GFileInfo for given file or NULL on error. Free the returned
+ // object with g_object_unref().
+ _gmh->d_g_file_info = g_file_query_info_finish((GFile*)_source_object, _res, &gerror);
+ if ( ! _gmh->d_g_file_info )
+ {
+ MONITOR_ERR("Model::GIO::Monitor_callback_%s():g_file_query_info_finish failed - %s [%s]", _event_str, gerror->message, _md->a_row->uri_utf8());
+ return FALSE;
+ }
+
+ // file type
+ _gmh->a_type = (GFileType)g_file_info_get_attribute_uint32(_gmh->d_g_file_info, "standard::type");
+ if ( _gmh->a_type == 0 )
+ {
+ MONITOR_ERR("Model::GIO::Monitor_callback_%s():g_file_info_get_attribute_uint32 (standard::type) failed - %s [%s]", _event_str, gerror->message, _md->a_row->uri_utf8());
+ return FALSE;
+ }
+
+ // eFileAccess
+ gboolean b_read = g_file_info_get_attribute_boolean(_gmh->d_g_file_info, "access::can-read");
+ gboolean b_write = g_file_info_get_attribute_boolean(_gmh->d_g_file_info, "access::can-write");
+ _gmh->a_access = Access_from_read_write(b_read, b_write);
+
+ // display name
+ _gmh->a_display_name = g_file_info_get_attribute_string(_gmh->d_g_file_info, "standard::display-name");
+ if ( _gmh->a_display_name == NULL )
+ {
+ MONITOR_ERR("Model::GIO::Monitor_callback_%s():g_file_info_get_attribute_string (standard::display-name) failed - %s [%s]", _event_str, gerror->message, _md->a_row->uri_utf8());
+ return FALSE;
+ }
+
+ // symlink ?
+ _gmh->a_is_symlink = g_file_info_get_attribute_boolean(_gmh->d_g_file_info, "standard::is-symlink");
+
+ if ( _gmh->a_is_symlink )
+ {
+ _gmh->a_symlink_target_display_name = g_file_info_get_attribute_string(_gmh->d_g_file_info, "standard::symlink-target");
+ if ( _gmh->a_symlink_target_display_name == NULL )
+ {
+ MONITOR_ERR("Model::GIO::Monitor_callback_%s():g_file_info_get_attribute_string (standard::symlink-target) failed - %s [%s]", _event_str, gerror->message, _md->a_row->uri_utf8());
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitoring : Monitor_callback_del
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback_del(
+ MonitorData * _md)
+{
+ MONITOR_INF("Model::GIO::Monitor_callback_del()");
+
+ Iter_monitor_callback_del(_md);
+
+ return;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitoring : Monitor_callback_child_del
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback_child_del(
+ MonitorData * _md)
+{
+ gchar * name_debug = _("a child directory");
+ //.........................................................................
+ MONITOR_INF("Model::GIO::Monitor_callback_child_del()");
+
+ Iter_monitor_callback_child_del(_md, name_debug);
+
+ return;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitoring : Monitor_callback_child_new
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback_child_new(
+ GObject * _source_object,
+ GAsyncResult * _res,
+ gpointer _data)
+{
+ MonitorData * md = NULL;
+ GioMonitorHelper gmh = {NULL, G_FILE_TYPE_UNKNOWN, eAccessUN, NULL, FALSE, NULL};
+ File * child = NULL;
+ //.........................................................................
+ MONITOR_INF("Model::GIO::Monitor_callback_child_new()");
+
+ md = (MonitorData*)_data;
+ if ( !md )
+ {
+ MONITOR_ERR(" MonitorData is NULL");
+ goto exit;
+ }
+
+ if ( ! Monitor_callback_helper_query_info("child_new", _source_object, _res, _data, md, &gmh) )
+ goto exit;
+
+ if ( gmh.a_type != G_FILE_TYPE_DIRECTORY )
+ {
+ MONITOR_INF(" Type is not G_FILE_TYPE_DIRECTORY, ignored");
+ goto exit;
+ }
+
+ child = new Directory(gmh.a_display_name, eAccessRW);
+
+ Iter_monitor_callback_child_new(md, child);
+
+ delete child;
+
+exit:
+
+ return;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitoring : Monitor_callback_acc
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback_acc(
+ GObject * _source_object,
+ GAsyncResult * _res,
+ gpointer _data)
+{
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitoring : Monitor_callback_child_acc
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GIO::Monitor_callback_child_acc(
+ GObject * _source_object,
+ GAsyncResult * _res,
+ gpointer _data)
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-model-struct.cc b/src/foldview/gnome-cmd-connection-treeview-model-struct.cc
new file mode 100644
index 0000000..5ea5abf
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-model-struct.cc
@@ -0,0 +1,1203 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : many
+
+ Parent : GnomeCmdConnectionTreeview::Model
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+static gboolean _USE_GIO_ = GCMDGTKFOLDVIEW_USE_GIO;
+
+// ###########################################################################
+//
+// IterInfo
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::Model::IterInfo::IterInfo()
+{
+ a_model = NULL;
+
+ a_iter = GnomeCmdConnectionTreeview::Model::Iter_zero;
+ d_path = NULL;
+ d_gtk_path = NULL;
+ a_row = NULL;
+
+ a_expanded = FALSE;
+ a_readable = FALSE;
+ a_children = -1;
+ a_first_child_is_dummy = FALSE;
+}
+GnomeCmdConnectionTreeview::Model::IterInfo::~IterInfo()
+{
+ if ( d_path )
+ delete d_path;
+
+ if ( d_gtk_path )
+ gtk_tree_path_free(d_gtk_path);
+}
+
+void
+GnomeCmdConnectionTreeview::Model::IterInfo::reset()
+{
+ a_model = NULL;
+
+ a_iter = GnomeCmdConnectionTreeview::Model::Iter_zero;
+
+ if ( d_path )
+ {
+ delete d_path;
+ d_path = NULL;
+ }
+
+ if ( d_gtk_path )
+ {
+ gtk_tree_path_free(d_gtk_path);
+ d_gtk_path = NULL;
+ }
+ a_row = NULL;
+
+ a_expanded = FALSE;
+ a_readable = FALSE;
+ a_children = -1;
+ a_first_child_is_dummy = FALSE;
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::IterInfo::gather(
+ Model * _model,
+ TreestorePath * _path,
+ IterInfo::eFields _fields)
+{
+ GtkTreeIter iter = Iter_zero;
+ //.........................................................................
+ if ( ! _model->treestore()->ext_iter_from_path(_path, &iter) )
+ return FALSE;
+
+ // store path
+ d_path = _path->dup();
+ if ( ! d_path )
+ return FALSE;
+
+ return gather(_model, &iter, _fields);
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::IterInfo::gather(
+ Model * _model,
+ GtkTreeIter * _iter,
+ IterInfo::eFields _fields)
+{
+ GtkTreeIter iter_child = Iter_zero;
+ Row * row_child = NULL;
+ //.........................................................................
+ a_model = _model;
+
+ //.........................................................................
+ //
+ // Variables
+ //
+
+ // iter
+ GCMD_ITER_COPY(&a_iter, _iter);
+
+ // path
+ if ( ! d_path )
+ {
+ d_path = a_model->treestore()->ext_path_from_iter(&a_iter);
+ if ( ! d_path )
+ return FALSE;
+ }
+
+ // row
+ if ( ! a_model->iter_get_treerow(&a_iter, &a_row) )
+ return FALSE;
+
+ // GtkTreePath
+ if ( _fields & eGtkPath )
+ {
+ d_gtk_path = GnomeCmdFoldviewTreestore::get_path(a_model->treemodel(), &a_iter);
+ if ( ! d_gtk_path )
+ return FALSE;
+ }
+
+ //.........................................................................
+ //
+ // Tests
+ //
+
+ // expanded
+ if ( _fields & eExp )
+ {
+ a_expanded = a_model->iter_is_expanded(&a_iter);
+ }
+
+ // readability
+ if ( _fields & eRead )
+ {
+ a_readable = a_row->readable();
+ }
+
+ if ( _fields & eChildren )
+ {
+ a_children = _model->iter_n_children(&a_iter);
+ }
+
+ if ( _fields & eFCID )
+ {
+ if ( ! ( _fields & eChildren) )
+ return FALSE;
+
+ if ( ! a_children )
+ return TRUE;
+
+ if ( ! GnomeCmdFoldviewTreestore::iter_children(a_model->treemodel(), &iter_child, &a_iter) )
+ return FALSE;
+
+ if ( ! a_model->iter_get_treerow(&iter_child, &row_child) )
+ return FALSE;
+
+ a_first_child_is_dummy = row_child->is_dummy();
+ }
+
+ return TRUE;
+}
+
+// ###########################################################################
+//
+// File, Directory, Symlink
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::Model::File::File(
+ const gchar * _utf8_display_name,
+ eFileAccess _access,
+ eFileType _type)
+{
+ d_utf8_name = g_strdup(_utf8_display_name);
+
+ a_access = _access;
+ a_type = _type;
+}
+GnomeCmdConnectionTreeview::Model::File::~File()
+{
+ g_free(d_utf8_name);
+
+ if ( d_disk_name )
+ g_free(d_disk_name);
+
+ if ( d_ck_utf8_name )
+ g_free(d_ck_utf8_name);
+}
+// ===========================================================================
+GnomeCmdConnectionTreeview::Model::Directory::Directory(
+ const gchar * _utf8_display_name,
+ eFileAccess _access)
+ : File(_utf8_display_name, _access, GnomeCmdConnectionTreeview::eTypeDirectory)
+{
+}
+GnomeCmdConnectionTreeview::Model::Directory::~Directory()
+{
+}
+void*
+GnomeCmdConnectionTreeview::Model::Directory::operator new(size_t size)
+{
+ GnomeCmdConnectionTreeview::Model::Directory *d = g_try_new0(GnomeCmdConnectionTreeview::Model::Directory, 1);
+
+ if ( !d )
+ GCMD_ERR("GnomeCmdConnectionTreeview::Model::Directory::new():g_try_new0 failed");
+
+ return d;
+}
+void
+GnomeCmdConnectionTreeview::Model::Directory::operator delete(void *p)
+{
+ g_free(p);
+}
+
+GnomeCmdConnectionTreeview::Model::File*
+GnomeCmdConnectionTreeview::Model::Directory::dup()
+{
+ File * file = NULL;
+ //.........................................................................
+ file = new Directory(name_utf8(), access());
+
+ return file;
+}
+
+// ===========================================================================
+GnomeCmdConnectionTreeview::Model::Symlink::Symlink(
+ const gchar * _utf8_display_name,
+ const gchar * _utf8_target_uri,
+ eFileAccess _access)
+ : File(_utf8_display_name, _access, GnomeCmdConnectionTreeview::eTypeSymlink)
+{
+ d_utf8_target_uri = g_strdup(_utf8_target_uri);
+}
+GnomeCmdConnectionTreeview::Model::Symlink::~Symlink()
+{
+ g_free(d_utf8_target_uri);
+}
+void*
+GnomeCmdConnectionTreeview::Model::Symlink::operator new(size_t size)
+{
+ GnomeCmdConnectionTreeview::Model::Symlink *s = g_try_new0(GnomeCmdConnectionTreeview::Model::Symlink, 1);
+
+ if ( !s )
+ GCMD_ERR("GnomeCmdConnectionTreeview::Model::Symlink::new():g_try_new0 failed");
+
+ return s;
+}
+void
+GnomeCmdConnectionTreeview::Model::Symlink::operator delete(void *p)
+{
+ g_free(p);
+}
+GnomeCmdConnectionTreeview::Model::File*
+GnomeCmdConnectionTreeview::Model::Symlink::dup()
+{
+ File * file = NULL;
+ //.........................................................................
+ file = new Symlink(name_utf8(), target_uri(), access());
+
+ return file;
+}
+
+// ###########################################################################
+//
+// Refresh, RefreshList
+//
+// ###########################################################################
+/*
+// ===========================================================================
+// Model::Refresh
+// ===========================================================================
+void*
+GnomeCmdConnectionTreeview::Model::Refresh::operator new(size_t size)
+{
+ Refresh *r = g_try_new0(GnomeCmdConnectionTreeview::Model::Refresh, 1);
+
+ if ( ! r )
+ GCMD_ERR("GnomeCmdConnectionTreeview::Model::Refresh::new():g_try_new0 failed");
+
+ return r;
+}
+void
+GnomeCmdConnectionTreeview::Model::Refresh::operator delete(void *p)
+{
+ g_free(p);
+}
+
+GnomeCmdConnectionTreeview::Model::Refresh::Refresh(
+ TreestorePath * _path_mallocated,
+ const gchar * _uri)
+{
+ d_path = _path_mallocated;
+ d_uri = g_strdup(_uri);
+}
+
+GnomeCmdConnectionTreeview::Model::Refresh::~Refresh()
+{
+ delete d_path;
+ g_free(d_uri);
+}
+// ===========================================================================
+// Model::RefreshList
+// ===========================================================================
+void*
+GnomeCmdConnectionTreeview::Model::RefreshList::operator new(size_t size)
+{
+ RefreshList *r = g_try_new0(GnomeCmdConnectionTreeview::Model::RefreshList, 1);
+
+ if ( ! r )
+ GCMD_ERR("GnomeCmdConnectionTreeview::Model::RefreshList::new():g_try_new0 failed");
+
+ return r;
+}
+void
+GnomeCmdConnectionTreeview::Model::RefreshList::operator delete(void *p)
+{
+ g_free(p);
+}
+
+GnomeCmdConnectionTreeview::Model::RefreshList::RefreshList(
+ Model * _model,
+ GList * _list)
+{
+ a_model = _model;
+ d_list = _list;
+ a_current = NULL;
+}
+
+GnomeCmdConnectionTreeview::Model::RefreshList::~RefreshList()
+{
+ g_list_free(d_list);
+}
+
+GnomeCmdConnectionTreeview::Model*
+GnomeCmdConnectionTreeview::Model::RefreshList::model()
+{
+ return a_model;
+}
+
+void
+GnomeCmdConnectionTreeview::Model::RefreshList::reset()
+{
+ d_list = g_list_first(d_list);
+ a_current = d_list;
+}
+
+void
+GnomeCmdConnectionTreeview::Model::RefreshList::add(Refresh*)
+{
+}
+
+GnomeCmdConnectionTreeview::Model::Refresh*
+GnomeCmdConnectionTreeview::Model::RefreshList::getplusplus()
+{
+ Refresh * r = NULL;
+ //.........................................................................
+ if ( ! a_current )
+ return NULL;
+
+ r = (Refresh*)(a_current->data);
+ a_current = a_current->next;
+
+ return r;
+}
+*/
+// ###########################################################################
+//
+// TreeRowStd
+//
+// ###########################################################################
+
+// ***************************************************************************
+// ctor / dtor
+// ***************************************************************************
+void
+GnomeCmdConnectionTreeview::Model::TreeRowStd::init_flags_and_collate_keys(
+ eFileAccess _access,
+ gboolean _is_link,
+ gboolean _is_dummy,
+ eRowStatus _status,
+ eRowType _type,
+ //................................
+ gboolean _is_samba,
+ gboolean _is_local,
+ gboolean _host_redmond)
+{
+ eIcon icon = eIconUnknown;
+ glong l = 0;
+ gchar* temp = NULL;
+ //.........................................................................
+ // Info flags
+
+ // icon
+ if ( ! _is_dummy )
+ if ( ! _is_link )
+ icon = View::Icon_from_type_access(eTypeDirectory, _access);
+ else
+ icon = View::Icon_from_type_access(eTypeSymlink, _access);
+ else
+ icon = eIconUnknown;
+
+ // flags
+ a_info_1 =
+ ( (guint32)icon << e_ICON_SHIFT ) +
+ ( (guint32)(_is_link ? 1 : 0 ) << e_LINK_SHIFT ) +
+ ( (guint32)(_access) << e_ACCESS_SHIFT ) +
+ ( (guint32)(_status) << e_STATUS_SHIFT ) +
+ ( (guint32)(_type) << e_TYPE_SHIFT ) +
+ //...................................................
+ ( (guint32)(_is_samba ? 1 : 0 ) << e_SAMBA_SHIFT ) +
+ ( (guint32)(_is_local ? 1 : 0 ) << e_LOCAL_SHIFT ) +
+ ( (guint32)(_host_redmond ? 1 : 0 ) << e_REDMOND_SHIFT );
+
+ //.........................................................................
+
+ // -> raw collate key ( case sensitive )
+ l = g_utf8_strlen(d_utf8_name_display, -1);
+ d_utf8_collate_keys[eCollateKeyRaw] = g_utf8_collate_key_for_filename(d_utf8_name_display, l);
+
+ // -> case-insensitive collate key
+ temp = g_utf8_casefold (d_utf8_name_display, l);
+ l = g_utf8_strlen (temp, -1);
+ d_utf8_collate_keys[eCollateKeyCaseInsensitive] = g_utf8_collate_key_for_filename(temp, l);
+ g_free(temp);
+}
+
+GnomeCmdConnectionTreeview::Model::TreeRowStd::TreeRowStd()
+{
+ // For TreeRowRoot & TreeRowDummy
+}
+GnomeCmdConnectionTreeview::Model::TreeRowStd::TreeRowStd(
+ Row * _row,
+ Row * _row_parent,
+ File * _file)
+{
+ if ( _file->is_symlink() )
+ d_utf8_symlink_target_uri = g_strdup(((Symlink*)_file)->target_uri());
+ else
+ d_utf8_symlink_target_uri = g_strdup(_("Not a symlink - ( BUG ! THIS SHOULD NEVER BE DISPLAYED )"));
+
+ d_utf8_name_display = g_strdup(_file->name_utf8());
+
+ init_flags_and_collate_keys(
+ _file->access(), _file->is_symlink(), FALSE,
+ eStatusOK, eRowStd,
+ _row_parent->is_samba(), _row_parent->is_local(), _row_parent->host_redmond());
+}
+
+GnomeCmdConnectionTreeview::Model::TreeRowStd::~TreeRowStd()
+{
+ gint i = 0;
+ //.........................................................................
+
+ //GCMD_INF("Model::~TreeRowStd()");
+
+ // delete all
+ g_free(d_utf8_name_display);
+ g_free(d_utf8_symlink_target_uri);
+
+ for ( i = 0 ; i != eCollateKeyCard ; i++ )
+ g_free(d_utf8_collate_keys[i]);
+}
+
+// ***************************************************************************
+// Some accessors
+// ***************************************************************************
+GnomeCmdConnectionTreeview::eIcon
+GnomeCmdConnectionTreeview::Model::TreeRowStd::icon()
+{
+ return (eIcon)( (a_info_1 & e_ICON_BITS ) >> e_ICON_SHIFT );
+}
+void
+GnomeCmdConnectionTreeview::Model::TreeRowStd::icon(eIcon _icon)
+{
+ a_info_1 = a_info_1 & e_ICON_MASK;
+ a_info_1 = a_info_1 | ( (guint32)_icon << e_ICON_SHIFT );
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::is_link()
+{
+ return (gboolean)((a_info_1 & e_LINK_BITS ) >> e_LINK_SHIFT);
+}
+GnomeCmdConnectionTreeview::eFileAccess
+GnomeCmdConnectionTreeview::Model::TreeRowStd::access()
+{
+ return (GnomeCmdConnectionTreeview::eFileAccess)( (a_info_1 & e_ACCESS_BITS ) >> e_ACCESS_SHIFT );
+}
+GnomeCmdConnectionTreeview::Model::eRowStatus
+GnomeCmdConnectionTreeview::Model::TreeRowStd::row_status()
+{
+ return (GnomeCmdConnectionTreeview::Model::eRowStatus)( (a_info_1 & e_STATUS_BITS ) >> e_STATUS_SHIFT );
+}
+GnomeCmdConnectionTreeview::Model::eRowType
+GnomeCmdConnectionTreeview::Model::TreeRowStd::rowtype()
+{
+ return (GnomeCmdConnectionTreeview::Model::eRowType)( (a_info_1 & e_TYPE_BITS ) >> e_TYPE_SHIFT );
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::is_std()
+{
+ return ( (eRowType)((a_info_1 & e_TYPE_BITS ) >> e_TYPE_SHIFT) == eRowStd);
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::is_root()
+{
+ return ( (eRowType)((a_info_1 & e_TYPE_BITS ) >> e_TYPE_SHIFT) == eRowRoot);
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::is_dummy()
+{
+ return ( (eRowType)((a_info_1 & e_TYPE_BITS ) >> e_TYPE_SHIFT) == eRowDummy);
+}
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::is_samba()
+{
+ return ( ( (a_info_1 & e_SAMBA_BITS ) >> e_SAMBA_SHIFT ) != 0 );
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::is_local()
+{
+ return ( ( (a_info_1 & e_LOCAL_BITS ) >> e_LOCAL_SHIFT ) != 0 );
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::host_redmond()
+{
+ return ( ( (a_info_1 & e_REDMOND_BITS ) >> e_REDMOND_SHIFT ) != 0 );
+}
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::TreeRowStd::readable()
+{
+ return (
+ (
+ (guint32)( (a_info_1 & e_ACCESS_BITS ) >> e_ACCESS_SHIFT ) &
+ (guint32)( ePermRead )
+ )
+ != 0
+ );
+}
+void
+GnomeCmdConnectionTreeview::Model::TreeRowStd::readable(gboolean _readable)
+{
+ eIcon icon = eIconUnknown;
+ eFileAccess a = eAccessFB;
+
+ // access
+ a = (eFileAccess)
+ (
+ _readable ?
+ ((guint32)access()) | ( ((guint32)ePermRead)) :
+ ((guint32)access()) & (~((guint32)ePermRead))
+ );
+
+ // icon
+ if ( ! is_dummy() )
+ {
+ if ( ! is_link() )
+ icon = View::Icon_from_type_access(eTypeDirectory, a);
+ else
+ icon = View::Icon_from_type_access(eTypeSymlink, a);
+ }
+
+ // set new values
+ a_info_1 = (a_info_1 & e_ACCESS_MASK) & e_ICON_SHIFT;
+ a_info_1 = a_info_1 +
+ ( (guint32)a << e_ACCESS_SHIFT ) +
+ ( (guint32)icon << e_ICON_SHIFT );
+}
+// ===========================================================================
+const gchar*
+GnomeCmdConnectionTreeview::Model::TreeRowStd::utf8_name_display()
+{
+ return d_utf8_name_display;
+}
+const GnomeCmdConnectionTreeview::Uri
+GnomeCmdConnectionTreeview::Model::TreeRowStd::utf8_symlink_target_uri()
+{
+ return d_utf8_symlink_target_uri;
+}
+const gchar*
+GnomeCmdConnectionTreeview::Model::TreeRowStd::utf8_collate_key(
+ gint collate_key_to_use)
+{
+ return d_utf8_collate_keys[collate_key_to_use];
+}
+// ###########################################################################
+//
+// TreeRowRoot
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::Model::TreeRowRoot::TreeRowRoot(
+ Uri _utf8_uri,
+ const gchar * _utf8_name_display,
+ Uri _utf8_symlink_target_uri,
+ eFileAccess _access,
+ gboolean _is_symlink,
+ gboolean _is_samba,
+ gboolean _is_local,
+ gboolean _host_redmond)
+{
+ //.........................................................................
+ d_utf8_name_display = g_strdup(_utf8_name_display);
+
+ if( _is_symlink )
+ d_utf8_symlink_target_uri = g_strdup( _utf8_symlink_target_uri );
+ else
+ d_utf8_symlink_target_uri = g_strdup(_("NOT SYMLINK - This should not be displayed"));
+
+ init_flags_and_collate_keys(
+ _access, _is_symlink, FALSE,
+ eStatusOK, eRowRoot,
+ _is_samba,
+ _is_local,
+ FALSE); // _GWR_TODO_ : _host_redmond
+}
+
+GnomeCmdConnectionTreeview::Model::TreeRowRoot::~TreeRowRoot()
+{
+ //GCMD_INF("Model::~TreeRowRoot()");
+}
+// ###########################################################################
+//
+// TreeRowDummy
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::Model::TreeRowDummy::TreeRowDummy(
+ Row * _row,
+ Row * _row_parent)
+{
+ d_utf8_name_display = g_strdup(_("...Working..."));
+ d_utf8_symlink_target_uri = g_strdup(_("Not a symlink (dummy) - ( BUG ! THIS SHOULD NEVER BE DISPLAYED )"));
+
+ init_flags_and_collate_keys(
+ eAccessRW, FALSE, TRUE,
+ eStatusOK, eRowDummy,
+ _row_parent->is_samba(), _row_parent->is_local(), _row_parent->host_redmond());
+}
+
+GnomeCmdConnectionTreeview::Model::TreeRowDummy::~TreeRowDummy()
+{
+ //GCMD_INF("Model::~TreeRowDummy()");
+}
+// ###########################################################################
+//
+// Row
+//
+// ###########################################################################
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Row() [ aggregate of TreeRowStd ]
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GnomeCmdConnectionTreeview::Model::Row::Row(
+ eRowType _rowtype,
+ Row * _row_parent,
+ File * _file)
+{
+ g_return_if_fail( _rowtype == eRowStd );
+
+ d_path = NULL;
+ d_utf8_uri = NULL;
+ d_monitor = NULL;
+ d_treerow = NULL;
+
+ // uri
+ if ( _row_parent->is_samba() )
+ d_utf8_uri = g_strconcat(_row_parent->uri_utf8(), "\\", _file->name_utf8(), NULL);
+ else
+ if ( _row_parent->is_local() && _row_parent->host_redmond() )
+ d_utf8_uri = g_strconcat(_row_parent->uri_utf8(), "\\", _file->name_utf8(), NULL);
+ else
+ {
+ gchar *temp = g_utf8_collate_key(_row_parent->uri_utf8(), -1);
+ if ( g_utf8_collate(temp, Collate_key_uri_01) )
+ d_utf8_uri = g_strconcat(_row_parent->uri_utf8(), "/", _file->name_utf8(), NULL);
+ else
+ d_utf8_uri = g_strconcat("file:///", _file->name_utf8(), NULL);
+ g_free(temp);
+ }
+ // treerow
+ d_treerow = (TreeRowInterface*)( new TreeRowStd(this, _row_parent, _file) );
+
+ // monitor : will be created when the Row will be added to the treestore
+}
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Row() [ aggregate of TreeRowRoot ]
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GnomeCmdConnectionTreeview::Model::Row::Row(
+ eRowType _rowtype,
+ Uri _utf8_uri,
+ const gchar * _utf8_display_name,
+ Uri _utf8_symlink_target_uri,
+ eFileAccess _access,
+ gboolean _is_symlink,
+ gboolean _is_samba,
+ gboolean _is_local,
+ gboolean _host_redmond)
+{
+ g_return_if_fail( _rowtype == eRowRoot );
+
+ d_path = NULL;
+ d_utf8_uri = NULL;
+ d_monitor = NULL;
+ d_treerow = NULL;
+
+ d_utf8_uri = g_strdup( _utf8_uri );
+
+ d_treerow = (TreeRowInterface*)( new TreeRowRoot(_utf8_uri, _utf8_display_name, _utf8_symlink_target_uri, _access, _is_symlink, _is_samba, _is_local, _host_redmond) );
+
+ // monitor : will be created when the Row will be added to the treestore
+}
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Row() [ aggregate of TreeRowDummy ]
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GnomeCmdConnectionTreeview::Model::Row::Row(
+ eRowType _rowtype,
+ Row * _row_parent)
+{
+ g_return_if_fail( _rowtype == eRowDummy );
+
+ d_path = NULL;
+ d_utf8_uri = NULL;
+ d_monitor = NULL;
+ d_treerow = NULL;
+
+ d_utf8_uri = g_strdup(_("file:///...Working..."));
+
+ d_treerow = (TreeRowInterface*)( new TreeRowDummy(this, _row_parent) );
+
+ // monitor : will be created when calling monitoring_start(), because we
+ // dont know the Path yet. The path will be known when the treestore will
+ // call set_path_from_treestore().
+}
+
+GnomeCmdConnectionTreeview::Model::Row::~Row()
+{
+ if ( is_std() )
+ {
+ //GCMD_INF("Model::~Row()::std");
+ }
+ else
+ {
+ if ( is_dummy() )
+ {
+ //GCMD_INF("Model::~Row()::dummy");
+ }
+ else
+ {
+ if ( is_root() )
+ {
+ //GCMD_INF("Model::~Row()::root");
+ }
+ else
+ {
+ GCMD_ERR("Model::~Row()::???");
+ }
+ }
+ }
+
+ g_free(d_utf8_uri);
+ delete d_path;
+
+ delete d_treerow;
+
+ if ( d_monitor )
+ {
+ if ( d_monitor->monitoring_started() )
+ d_monitor->monitoring_stop();
+
+ delete d_monitor;
+ d_monitor = NULL;
+ }
+}
+
+
+// ***************************************************************************
+// Accessors
+// ***************************************************************************
+
+
+// ***************************************************************************
+// GnomeCmdFoldviewTreestore::DataInterface impl
+// ***************************************************************************
+
+// inlined : GnomeCmdConnectionTreeview::Model::Row::path()
+
+void
+GnomeCmdConnectionTreeview::Model::Row::set_path_from_treestore(
+ GnomeCmdFoldviewTreestore::Path * _path)
+{
+ g_return_if_fail( ! d_path );
+
+ d_path = _path;
+}
+
+gint
+GnomeCmdConnectionTreeview::Model::Row::compare(
+ GnomeCmdFoldviewTreestore::DataInterface * _data)
+{
+ Row * row = NULL;
+ //.........................................................................
+ row = (Row*)_data;
+
+ return strcmp
+ (
+ this->utf8_collate_key(eCollateKeyRaw),
+ row->utf8_collate_key(eCollateKeyRaw)
+ );
+}
+
+gint
+GnomeCmdConnectionTreeview::Model::Row::compare_str(
+ const gchar * _str)
+{
+ return strcmp
+ (
+ this->utf8_collate_key(eCollateKeyRaw),
+ _str
+ );
+}
+
+// ***************************************************************************
+// GnomeCmdFoldviewTreestore::MonitorInterface impl
+// ***************************************************************************
+gboolean
+GnomeCmdConnectionTreeview::Model::Row::monitoring_started()
+{
+ if ( ! d_monitor )
+ return FALSE;
+
+ return d_monitor->monitoring_started();
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::Row::monitoring_start(
+ Model * _model,
+ Row * _row)
+{
+ g_return_val_if_fail( this == _row, FALSE );
+
+ // new monitor
+ if ( ! d_monitor )
+ {
+ if ( _USE_GIO_ )
+ d_monitor = new GioMonitor();
+ else
+ d_monitor = new GnomeVFSMonitor();
+ }
+
+ return d_monitor->monitoring_start(_model, this);
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::Row::monitoring_stop()
+{
+ if ( ! d_monitor )
+ return TRUE;
+
+ if ( d_monitor->monitoring_stop() )
+ {
+ delete d_monitor;
+ d_monitor = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ###########################################################################
+//
+// Filesystem access
+//
+// ###########################################################################
+
+
+// ***************************************************************************
+//
+// Directory listing
+//
+// ***************************************************************************
+
+//=============================================================================
+// Model::AsyncCallerData
+//=============================================================================
+void*
+GnomeCmdConnectionTreeview::Model::AsyncCallerData::operator new ( size_t _size)
+{
+ AsyncCallerData *acd = g_try_new0(AsyncCallerData, 1);
+
+ return (void*)acd;
+}
+
+void
+GnomeCmdConnectionTreeview::Model::AsyncCallerData::operator delete(void* _p)
+{
+ g_free(_p);
+}
+
+
+GnomeCmdConnectionTreeview::Model::AsyncCallerData::AsyncCallerData(
+ Model * _model,
+ AsyncCallerCallback _callback,
+ TreestorePath * _path)
+{
+ a_model = _model;
+ a_callback = _callback;
+ d_path = _path;
+}
+
+
+GnomeCmdConnectionTreeview::Model::AsyncCallerData::~AsyncCallerData()
+{
+ delete d_path;
+};
+
+//=============================================================================
+// Model::AsyncCore
+//=============================================================================
+GnomeCmdConnectionTreeview::Model::AsyncCore::AsyncCore(
+ AsyncCallerData * _acd)
+{
+ a_caller_data = _acd;
+
+ a_error = eErrorNone;
+ d_error_str = NULL;
+}
+
+GnomeCmdConnectionTreeview::Model::AsyncCore::~AsyncCore()
+{
+ //delete d_caller_data; // _GWR_TODO_
+
+ if ( d_error_str )
+ g_free( d_error_str );
+}
+
+void
+GnomeCmdConnectionTreeview::Model::AsyncCore::error_set(
+ eFileError _error,
+ const gchar * _str)
+{
+ a_error = _error;
+ d_error_str = g_strdup(_str);
+}
+
+//=============================================================================
+// Model::AsyncEnumerateChildren
+//=============================================================================
+GnomeCmdConnectionTreeview::Model::AsyncEnumerateChildren::AsyncEnumerateChildren(
+ AsyncCallerData * _caller_data,
+ const Uri _uri,
+ gint _max_result,
+ gboolean _follow_links) : AsyncCore(_caller_data)
+{
+ d_uri = g_strdup(_uri);
+ a_max_result = _max_result;
+ a_follow_links = _follow_links;
+
+ d_list = NULL;
+ a_list_card = NULL;
+}
+
+GnomeCmdConnectionTreeview::Model::AsyncEnumerateChildren::~AsyncEnumerateChildren()
+{
+ GList * list = NULL;
+ File * file = NULL;
+ //.........................................................................
+ list = g_list_first(d_list);
+ while ( list )
+ {
+ file = (File*)list->data;
+ delete file;
+ list = g_list_next(list);
+ }
+ g_list_free(d_list);
+
+ g_free(d_uri);
+}
+
+void
+GnomeCmdConnectionTreeview::Model::AsyncEnumerateChildren::list_remove(
+ GList * _list)
+{
+ g_return_if_fail( _list );
+
+ delete (File*)(_list->data);
+ d_list = g_list_delete_link(d_list, _list);
+
+ a_list_card--;
+}
+
+void
+GnomeCmdConnectionTreeview::Model::AsyncEnumerateChildren::list_append(
+ File * _file)
+{
+ g_return_if_fail( _file );
+
+ d_list = g_list_append(d_list, _file);
+ a_list_card++;
+}
+
+
+//=============================================================================
+// Model::AsyncGetFileInfo
+//=============================================================================
+GnomeCmdConnectionTreeview::Model::AsyncGetFileInfo::AsyncGetFileInfo(
+ AsyncCallerData * _caller_data,
+ const Uri _uri) : AsyncCore(_caller_data)
+{
+ d_uri = g_strdup(_uri);
+ a_name = NULL;
+ b_file_not_found = FALSE;
+ a_access = eAccessUN;
+ a_is_symlink = FALSE;
+ a_symlink_name = NULL;
+}
+
+GnomeCmdConnectionTreeview::Model::AsyncGetFileInfo::~AsyncGetFileInfo()
+{
+ g_free(d_uri);
+}
+
+// ***************************************************************************
+//
+// Monitoring
+//
+// ***************************************************************************
+
+// ===========================================================================
+// Model::Monitor
+// ===========================================================================
+GnomeCmdConnectionTreeview::Model::Monitor::Monitor()
+{
+}
+GnomeCmdConnectionTreeview::Model::Monitor::~Monitor()
+{
+ MONITOR_INF("Model::Monitor::~Monitor()");
+
+ // ensure we are no more monitoring anything
+ if ( monitoring_started() )
+ {
+ MONITOR_ERR("GnomeCmdConnectionTreeview::Model::Monitor::~Monitor():still monitoring");
+ }
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::Monitor::monitoring_started()
+{
+ return a_started;
+}
+
+
+
+// ###########################################################################
+//
+// Sorting
+//
+// ###########################################################################
+
+// ***************************************************************************
+//
+// IMsgSort
+//
+// ***************************************************************************
+
+
+
+
+// ***************************************************************************
+//
+// IMsgSort
+//
+// ***************************************************************************
+GnomeCmdConnectionTreeview::Model::MsgSort_Insertion::MsgSort_Insertion(
+ TreestorePath * _path,
+ Model * _model) : IMsgSort(_path, _model)
+{
+ a_i0 = 2;
+ d_list_work = NULL;
+}
+
+GnomeCmdConnectionTreeview::Model::MsgSort_Insertion::~MsgSort_Insertion()
+{
+ list_delete(&d_list_work);
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::MsgSort_Insertion::init()
+{
+ a_i0 = 2;
+ list_delete(&d_list_work);
+ list_original_copy(&d_list_work);
+
+ return TRUE;
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::MsgSort_Insertion::restart()
+{
+ list_delete(&d_list_work);
+
+ return TRUE;
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::MsgSort_Insertion::step()
+{
+ guint i = 0;
+ Row * r1 = NULL;
+ Row * r2 = NULL;
+ GList * l1 = NULL;
+ GList * l2 = NULL;
+ //.........................................................................
+ SORT_TKI("MsgSort_Insertion::next():(%03i / %03i) %02i%%", a_i0, list_card(), a_i0 * 100 / list_card());
+
+ if ( a_i0 > list_card() )
+ goto lab_sorted;
+
+ i = a_i0;
+
+ do
+ {
+ // get elements
+ r1 = (Row*)g_list_nth_data(d_list_work, i - 2);
+ r2 = (Row*)g_list_nth_data(d_list_work, i - 1);
+
+ // elements are ordered : exit
+ if ( r1->compare(r2) <= 0 )
+ goto lab_exit;
+
+ // elements not ordered : swap them and loop
+ g_list_nth(d_list_work, i - 2 )->data = r2;
+ g_list_nth(d_list_work, i - 1 )->data = r1;
+
+ if ( --i == 1 )
+ goto lab_exit;
+ }
+ while ( TRUE );
+
+
+lab_exit:
+ a_i0++;
+ return FALSE;
+
+lab_sorted:
+ SORT_TKI("MsgSort_Insertion::next():sorted !");
+
+ l1 = d_list_actual;
+ l2 = d_list_work;
+
+ for ( i = 0 ; i != list_card() ; i++ )
+ {
+ SORT_INF("%05s %05s",
+ ((Row*)(l1->data))->utf8_name_display(),
+ ((Row*)(l2->data))->utf8_name_display() );
+
+ l1 = g_list_next(l1);
+ l2 = g_list_next(l2);
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-model-struct.snippet.h b/src/foldview/gnome-cmd-connection-treeview-model-struct.snippet.h
new file mode 100644
index 0000000..78787d7
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-model-struct.snippet.h
@@ -0,0 +1,935 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-model-struct.snippet.h
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : Model
+
+ Parent : GnomeCmdConnectionTreeView
+
+ This file is directly inluded in gnome-cmd-connection-treeview-model.snippet.h
+
+ ###########################################################################
+*/
+
+
+// ###########################################################################
+//
+// IterInfo ( public because operator )
+//
+// ###########################################################################
+public:
+struct IterInfo
+{
+ public:
+ enum eFields
+ {
+ eNothing = 0 ,
+
+ eGtkPath = 0x00000001,
+
+ eExp = 0x00010000,
+ eRead = 0x00100000,
+ eChildren = 0x01000000,
+ eFCID = 0x11000001
+ };
+
+ public:
+ friend eFields operator | (eFields a, eFields b);
+
+ //.................................................................
+ private:
+ Model * a_model;
+
+ GtkTreeIter a_iter;
+ TreestorePath * d_path;
+ GtkTreePath * d_gtk_path;
+
+ Row * a_row;
+ gboolean a_expanded;
+ gboolean a_readable;
+ gint a_children;
+ gboolean a_first_child_is_dummy;
+
+ //eError a_error;
+
+ //.................................................................
+ public:
+ GtkTreeIter * iter() { return &a_iter; }
+ TreestorePath * path() { return d_path; }
+ GtkTreePath * gtk_path() { return d_gtk_path; }
+
+ Row * row() { return a_row; }
+ gboolean expanded() { return a_expanded; }
+ gboolean collapsed() { return ! a_expanded; }
+ gboolean readable() { return a_readable; }
+ gint32 children() { return a_children; }
+ gboolean first_child_is_dummy() { return a_first_child_is_dummy; }
+
+ public:
+ //eError error() { return a_error; }
+ //gboolean error_logical() { return ( a_error & 0x01000000); }
+ void reset();
+ gboolean gather(Model*, GtkTreeIter*, eFields);
+ gboolean gather(Model*, TreestorePath*, eFields);
+ //.................................................................
+ private:
+ void* operator new(size_t t) { return (void*)0; }
+ void operator delete(void* p) { }
+
+ public:
+ IterInfo();
+ ~IterInfo();
+
+
+};
+// ###########################################################################
+// Filesystem access structs : File, Directory, Symlink
+//
+// GFile is cool, but I dont need all that stuff inside it. So I define
+// custom little structs.
+// ###########################################################################
+public:
+struct File
+{
+ private:
+ gchar * d_ck_utf8_name; // for refresh only
+
+ protected:
+ gchar * d_disk_name;
+ gchar * d_utf8_name;
+ eFileAccess a_access;
+ eFileType a_type;
+
+ public:
+ File(const gchar*, eFileAccess, eFileType);
+ virtual ~File() = 0;
+
+ public:
+ void compute_ck_utf8_name() { d_ck_utf8_name = g_utf8_collate_key_for_filename(name_utf8(), -1); }
+ const gchar * ck_utf8_name() { return d_ck_utf8_name; }
+
+ const gchar * name_disk() { return d_disk_name; }
+ const gchar * name_utf8() { return d_utf8_name; }
+ eFileAccess access() { return a_access; }
+ eFileType type() { return a_type; }
+
+ gboolean is_symlink() { return ( a_type == eTypeSymlink ); }
+ gboolean is_dir() { return ( a_type == eTypeDirectory ); }
+
+ virtual File * dup() = 0;
+
+};
+//.....................................................................
+struct Directory : public File
+{
+ public:
+ void * operator new (size_t size);
+ void operator delete (void* p);
+
+ public:
+ Directory(const gchar *_utf8_display_name, eFileAccess);
+ virtual ~Directory();
+
+ virtual File* dup();
+};
+//.....................................................................
+struct Symlink : public File
+{
+ private:
+ gchar * d_utf8_target_uri;
+
+ public:
+ void * operator new (size_t size);
+ void operator delete (void* p);
+
+ Symlink(const gchar *_utf8_display_name, const gchar *_utf8_target_uri, eFileAccess);
+ virtual ~Symlink();
+
+ public:
+ const gchar * target_uri() { return d_utf8_target_uri; }
+
+ virtual File* dup();
+};
+// ###########################################################################
+// TreeRow stuff
+// ###########################################################################
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// TreeRowInterface
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+private:
+struct TreeRowInterface
+{
+ public:
+ virtual ~TreeRowInterface() {}
+
+ // flags
+ public:
+ virtual eIcon icon() = 0;
+ virtual void icon(eIcon) = 0;
+ virtual gboolean is_link() = 0;
+ virtual eFileAccess access() = 0;
+ virtual eRowStatus row_status() = 0;
+ virtual eRowType rowtype() = 0;
+ virtual gboolean is_std() = 0;
+ virtual gboolean is_root() = 0;
+ virtual gboolean is_dummy() = 0;
+ //..............................
+ virtual gboolean is_samba() = 0;
+ virtual gboolean is_local() = 0;
+ virtual gboolean host_redmond() = 0;
+ //..............................
+ virtual gboolean readable() = 0;
+ virtual void readable(gboolean) = 0;
+ // uris, names, ...
+ public:
+ virtual const gchar * utf8_name_display() = 0;
+ virtual const Uri utf8_symlink_target_uri() = 0;
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// TreeRowStd
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+private:
+struct TreeRowStd : public TreeRowInterface
+{
+ //.................................................................
+ // Info flags
+ // I use one gint32 to store every numeric info about a TreeRow.
+ // Thus we save memory.
+ private: enum
+ {
+ e_ICON_SHIFT = 0 ,
+ e_ICON_BITS = GCMD_B32(00000000,00000000,00000000,00001111) ,
+ e_ICON_MASK = ~e_ICON_BITS ,
+
+ e_LINK_SHIFT = 4 ,
+ e_LINK_BITS = GCMD_B32(00000000,10000000,00000000,00010000) ,
+ e_LINK_MASK = ~e_LINK_BITS ,
+
+ e_ACCESS_SHIFT = 5 ,
+ e_ACCESS_BITS = GCMD_B32(00000000,00000000,00000000,11100000) ,
+ e_ACCESS_MASK = ~e_ACCESS_BITS ,
+
+ e_STATUS_SHIFT = 8 ,
+ e_STATUS_BITS = GCMD_B32(00000000,00000000,00000111,00000000) ,
+ e_STATUS_MASK = ~e_STATUS_BITS ,
+
+ e_TYPE_SHIFT = 11 ,
+ e_TYPE_BITS = GCMD_B32(00000000,00000000,00011000,00000000) ,
+ e_TYPE_MASK = ~e_TYPE_BITS ,
+
+ //.............................................................
+ e_SAMBA_SHIFT = 16 ,
+ e_SAMBA_BITS = GCMD_B32(00000000,00000001,00000000,00000000) ,
+ e_SAMBA_MASK = ~e_SAMBA_BITS ,
+
+ e_LOCAL_SHIFT = 17 ,
+ e_LOCAL_BITS = GCMD_B32(00000000,00000010,00000000,00000000) ,
+ e_LOCAL_MASK = ~e_LOCAL_BITS ,
+
+ e_REDMOND_SHIFT = 18 ,
+ e_REDMOND_BITS = GCMD_B32(00000000,00000100,00000000,00000000) ,
+ e_REDMOND_MASK = ~e_REDMOND_BITS
+ };
+ guint32 a_info_1;
+
+ //.................................................................
+ // other members
+ protected:
+ gchar * d_utf8_name_display;
+ gchar * d_utf8_symlink_target_uri;
+
+ private:
+ gchar * d_utf8_collate_keys[eCollateKeyCard];
+
+ //.................................................................
+ // ctor, dtor
+ protected:
+ void init_flags_and_collate_keys(eFileAccess, gboolean _is_link, gboolean _is_dummy, eRowStatus, eRowType, gboolean _is_samba, gboolean _is_local, gboolean _host_redmond);
+
+ public:
+ TreeRowStd();
+ TreeRowStd(Row* _row, Row *_row_parent, File *_file);
+ virtual ~TreeRowStd();
+
+ // ...............................................................
+ // partial impl ( GnomeCmdFoldviewTreestore::DataInterface )
+ public:
+ const gchar * utf8_collate_key(gint collate_key_to_use);
+
+ // ...............................................................
+ // impl ( TreeRowInterace )
+ public:
+ virtual eIcon icon();
+ virtual void icon(eIcon);
+ virtual gboolean is_link();
+ virtual eFileAccess access();
+ virtual eRowStatus row_status();
+ virtual eRowType rowtype();
+ virtual gboolean is_std();
+ virtual gboolean is_root();
+ virtual gboolean is_dummy();
+ //..............................
+ virtual gboolean is_samba();
+ virtual gboolean is_local();
+ virtual gboolean host_redmond();
+ //..............................
+ virtual gboolean readable();
+ virtual void readable(gboolean);
+
+ virtual const gchar * utf8_name_display();
+ virtual const Uri utf8_symlink_target_uri();
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// TreeRowRoot
+//
+// Just like the struct above, but for root nodes : store a CnomeCmdCon
+// and a GnomeCmdPath so the model can retrive them from any iter
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct TreeRowRoot : public TreeRowStd
+{
+ private:
+ ConnectionMethodID a_con_id;
+
+ public:
+ TreeRowRoot(
+ Uri _utf8_uri, const gchar* _utf8_display_name, Uri _utf8_symlink_target_uri,
+ eFileAccess _access, gboolean _is_symlink,
+ gboolean _is_samba, gboolean _is_local, gboolean _host_redmond);
+ virtual ~TreeRowRoot();
+
+ public:
+ ConnectionMethodID connection_id() { return a_con_id; }
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// TreeRowDummy
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct TreeRowDummy : public TreeRowStd
+{
+ public:
+ TreeRowDummy(Row* _row, Row *_row_parent);
+ virtual ~TreeRowDummy();
+};
+
+// ###########################################################################
+// Filesystem access structs : Core ( GIO & GnomeVFS independant )
+// ###########################################################################
+struct AsyncCallerData
+{
+ private:
+ Model * a_model;
+ AsyncCallerCallback a_callback;
+ TreestorePath * d_path;
+
+ public:
+ void* operator new (size_t size);
+ void operator delete (void *p);
+ AsyncCallerData(Model*, AsyncCallerCallback, TreestorePath*);
+ virtual ~AsyncCallerData();
+
+ public:
+ TreestorePath * path() { return d_path; }
+ Model * model() { return a_model; }
+ AsyncCallerCallback callback() { return a_callback; }
+};
+//.....................................................................
+struct AsyncCore
+{
+ eFileError a_error;
+ gchar * d_error_str;
+
+ protected:
+ AsyncCallerData * a_caller_data;
+
+ protected:
+ AsyncCore(AsyncCallerData*);
+ virtual ~AsyncCore();
+
+ public:
+ AsyncCallerData * caller_data() { return a_caller_data; }
+
+ public:
+ void error_set(eFileError, const gchar*);
+ gboolean error() { return ( a_error != eErrorNone ); }
+ const gchar* error_str() { return d_error_str; }
+
+};
+// ###########################################################################
+// Filesystem access structs : Get file info
+// ###########################################################################
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Filesystem access structs : Get file info : Core ( GIO & GnomeVFS independant )
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct AsyncGetFileInfo : AsyncCore
+{
+ friend struct GnomeVFS;
+ friend struct GIO;
+ private:
+ Uri d_uri;
+ gchar * a_name;
+ eFileType a_type;
+ eFileAccess a_access;
+ gboolean a_is_symlink;
+ Uri a_symlink_name;
+
+ gboolean b_file_not_found;
+
+ protected:
+ AsyncGetFileInfo(AsyncCallerData*, const Uri);
+ virtual ~AsyncGetFileInfo();
+
+ public:
+ const Uri uri() { return d_uri; }
+ const gchar * name() { return a_name; }
+ eFileType type() { return a_type; }
+ eFileAccess access() { return a_access; }
+ gboolean is_symlink() { return a_is_symlink; }
+ const Uri uri_symlink_target() { return a_symlink_name; }
+};
+// ###########################################################################
+// Filesystem access structs : enumerate children
+// ###########################################################################
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Filesystem access structs : Enumerate : Core ( GIO & GnomeVFS independant )
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct AsyncEnumerateChildren : AsyncCore
+{
+ private:
+ Uri d_uri;
+ gint a_max_result;
+ gboolean a_follow_links;
+
+ GList * d_list;
+ gint a_list_card;
+
+ protected:
+ AsyncEnumerateChildren(AsyncCallerData*, const Uri, gint _max_result, gboolean _follow_links) ;
+ virtual ~AsyncEnumerateChildren();
+
+ public:
+ const Uri uri() { return d_uri; }
+ gint max_result() { return a_max_result; }
+ gboolean follow_links() { return a_follow_links; }
+
+ public:
+ GList * list() { return d_list; }
+ gint list_card() { return a_list_card; }
+ void list_append(File*);
+ void list_remove(GList*);
+};
+// ###########################################################################
+// Filesystem access struct : GIO
+// ###########################################################################
+private:
+struct GIO
+{
+ public:
+ static void Iter_enumerate_children_callback_1(GObject* , GAsyncResult *, gpointer);
+ static void Iter_enumerate_children_callback_2(GObject* , GAsyncResult *, gpointer);
+
+ void iter_enumerate_children (AsyncCallerData*, const Uri);
+ void iter_check_if_empty (AsyncCallerData*, const Uri);
+ void iter_get_file_info (AsyncCallerData*, const Uri);
+ //.................................................................
+ static void Monitor_callback (GFileMonitor*, GFile*, GFile*, GFileMonitorEvent, gpointer);
+ static gboolean Monitor_callback_helper_query_info (const gchar*, GObject*, GAsyncResult*, gpointer, MonitorData*, GioMonitorHelper*);
+ static void Monitor_callback_del (MonitorData*);
+ static void Monitor_callback_child_del (MonitorData*);
+ static void Monitor_callback_child_new (GObject* ,GAsyncResult*, gpointer);
+ static void Monitor_callback_acc (GObject* ,GAsyncResult*, gpointer);
+ static void Monitor_callback_child_acc (GObject* ,GAsyncResult*, gpointer);
+};
+// ###########################################################################
+// Filesystem access struct : GnomeVFS
+// ###########################################################################
+private:
+struct GnomeVFS
+{
+ friend struct GnomeVFSMonitor;
+
+ private:
+ static eFileAccess Access_from_GnomeVFSFilePermissions (GnomeVFSFilePermissions);
+ static eFileType Type_from_GnomeVFSFileType (GnomeVFSFileType);
+ static eFileError Error_from_GnomeVFSResult (GnomeVFSResult);
+
+ //.................................................................
+ static void Iter_get_file_info_callback(GnomeVFSAsyncHandle*, GList*,gpointer);
+
+ static void Iter_enumerate_children_callback(GnomeVFSAsyncHandle*, GnomeVFSResult, GList*, guint, gpointer);
+
+ public:
+ void iter_enumerate_children (AsyncCallerData*, const Uri);
+ void iter_check_if_empty (AsyncCallerData*, const Uri);
+ void iter_get_file_info (AsyncCallerData*, const Uri);
+ // no need for this one for instant
+ //void iter_get_file_info (AsyncCallerData*, const Uri);
+ //.................................................................
+ private:
+ static void Monitor_callback(GnomeVFSMonitorHandle* , const gchar*, const gchar*, GnomeVFSMonitorEventType, gpointer);
+ static void Monitor_callback_del (MonitorData*);
+ static void Monitor_callback_child_del (MonitorData*, const Uri);
+ static void Monitor_callback_child_new (GnomeVFSAsyncHandle*, GList*, gpointer);
+ //static void Monitor_callback_acc (GnomeVFSAsyncHandle*, GList*, gpointer);
+ static void Monitor_callback_child_acc (GnomeVFSAsyncHandle*, GList*, gpointer);
+};
+// ===================================================================
+// Filesystem access structs : Monitoring
+// ===================================================================
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Filesystem access structs : Monitoring : Core ( GIO & GnomeVFS independant )
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+private:
+struct MonitorInterface
+{
+ public:
+ virtual ~MonitorInterface() {};
+ virtual gboolean monitoring_start(Model*, Row*) = 0;
+ virtual gboolean monitoring_stop() = 0;
+ virtual gboolean monitoring_started() = 0;
+};
+//.....................................................................
+private:
+struct Monitor : public MonitorInterface
+{
+ protected:
+ gboolean a_started;
+
+ public:
+ Monitor();
+ virtual ~Monitor();
+
+ virtual gboolean monitoring_start(Model*, Row*) = 0;
+ virtual gboolean monitoring_stop() = 0;
+ virtual gboolean monitoring_started();
+};
+//.....................................................................
+private:
+struct MonitorData
+{
+ public:
+ Model * a_model;
+ Row * a_row;
+
+ //MonitorData(Row*);
+ //~MonitorData();
+};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Filesystem access structs : Monitoring : GnomeVFS
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct GnomeVFSMonitor : public Monitor
+{
+ public:
+ void operator delete (void * p);
+ void * operator new (size_t size);
+
+ GnomeVFSMonitor();
+ virtual ~GnomeVFSMonitor();
+
+ private:
+ GnomeVFSMonitorHandle * a_monitor_handle;
+
+ public:
+ GnomeVFSMonitorHandle * monitor_handle() { return a_monitor_handle; }
+ GnomeVFSMonitorHandle ** monitor_handle_ptr() { return &a_monitor_handle; }
+
+ gboolean monitoring_start(Model*, Row*);
+ gboolean monitoring_stop();
+};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Filesystem access structs : Monitoring : GIO
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct GioMonitor : public Monitor
+{
+ public:
+ void operator delete (void * p);
+ void * operator new (size_t size);
+
+ GioMonitor();
+ virtual ~GioMonitor();
+
+ private:
+ GFile * d_file; // we store this only for exiting
+ GFileMonitor * d_monitor; // gcmd properly, it is a mess
+ gulong a_signal_handle;
+
+ public:
+ GFile * gfile() { return d_file; }
+ GFileMonitor * monitor() { return d_monitor; }
+
+ gboolean monitoring_start(Model*, Row*);
+ gboolean monitoring_stop();
+};
+// ===================================================================
+// Row
+// ===================================================================
+public: // public becoz of View::Treeview
+struct Row : public GnomeCmdFoldviewTreestore::DataInterface,
+ public TreeRowInterface,
+ public MonitorInterface
+{
+ private:
+ TreestorePath * d_path;
+ Uri d_utf8_uri;
+
+ TreeRowInterface * d_treerow;
+ MonitorInterface * d_monitor;
+
+ public:
+ Row(eRowType _rowtype, Row *_row_parent, File *_file);
+ Row(eRowType _rowtype, Uri _utf8_uri, const gchar* _utf8_display_name, Uri _utf8_symlink_target_uri,
+ eFileAccess _access, gboolean _is_symlink,
+ gboolean _is_samba, gboolean _is_local, gboolean _host_redmond);
+ Row(eRowType _rowtype, Row *_row_parent);
+ ~Row();
+
+ // ...............................................................
+ // Accessors
+ public:
+ inline TreeRowInterface * treerow() { return (TreeRowInterface*)d_treerow; }
+
+ inline TreeRowStd * treerow_std() { return (TreeRowStd*)d_treerow; }
+
+ inline TreeRowRoot * treerow_root()
+ {
+ g_return_val_if_fail( treerow()->is_root(), NULL );
+ return (TreeRowRoot*)d_treerow;
+ }
+ inline TreeRowDummy * treerow_dummy()
+ {
+ g_return_val_if_fail( treerow()->is_dummy(), NULL );
+ return (TreeRowDummy*)d_treerow;
+ }
+ inline MonitorInterface * monitor() { return (MonitorInterface*)d_monitor; }
+
+ inline const Uri uri_utf8() { return d_utf8_uri; }
+ inline const gchar * utf8_collate_key(gint collate_key_to_use)
+ {
+ return ((TreeRowStd*)treerow())->utf8_collate_key(collate_key_to_use);
+ }
+ // ...............................................................
+ // impl ( GnomeCmdFoldviewTreestore::DataInterface )
+ public:
+ virtual gint compare (DataInterface*);
+ virtual gint compare_str (const gchar*);
+
+ inline virtual TreestorePath * path() { return d_path; }
+ virtual void set_path_from_treestore(GnomeCmdFoldviewTreestore::Path*);
+ // ...............................................................
+ // impl ( TreeRowInterface ) -> aggregation wrappers
+ // -> flags
+ public:
+ virtual eIcon icon() { return treerow()->icon(); }
+ virtual void icon(eIcon _icon) { treerow_std()->icon(_icon); }
+ virtual gboolean is_link() { return treerow()->is_link(); }
+ virtual eFileAccess access() { return treerow()->access(); }
+ virtual eRowStatus row_status() { return treerow()->row_status(); }
+ virtual eRowType rowtype() { return treerow()->rowtype(); }
+ virtual gboolean is_std() { return treerow()->is_std(); }
+ virtual gboolean is_root() { return treerow()->is_root(); }
+ virtual gboolean is_dummy() { return treerow()->is_dummy(); }
+ //..............................
+ virtual gboolean is_samba() { return treerow()->is_samba(); }
+ virtual gboolean is_local() { return treerow()->is_local(); }
+ virtual gboolean host_redmond() { return treerow()->host_redmond(); }
+ //..............................
+ virtual gboolean readable() { return treerow()->readable(); }
+ virtual void readable(gboolean _b) { treerow()->readable(_b); }
+ // -> uris, names, ...
+ public:
+ virtual const gchar * utf8_name_display() { return treerow()->utf8_name_display(); }
+ virtual const Uri utf8_symlink_target_uri() { return treerow()->utf8_symlink_target_uri(); }
+
+ // ...............................................................
+ // impl ( MonitorInterface -> aggregation wrappers
+ virtual gboolean monitoring_start(Model*, Row*);
+ virtual gboolean monitoring_stop();
+ virtual gboolean monitoring_started();
+};
+// ===================================================================
+// Messages structs
+// ===================================================================
+public:
+enum eMsgType
+{
+ eAddDummyChild = 1,
+ eAddChild = 2,
+ eAddFirstTree = 3,
+
+ eDel = 10,
+
+ eSetReadable = 20,
+ eSetNotReadable = 21,
+
+ eSort = 30,
+
+ eAsyncMismatch = 100,
+ eAsyncMismatchIEFUC = 101,
+ eAsyncMismatchICIEC = 102,
+ eAsyncMismatchAFT = 103
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgCore
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgCore
+{
+ private:
+ TreestorePath * d_path;
+
+ public:
+ virtual eMsgType type() = 0;
+ TreestorePath * path() { return d_path; }
+
+ public:
+ MsgCore(TreestorePath* _path)
+ {
+ d_path = _path ? _path->dup() : NULL;
+ }
+ virtual ~MsgCore()
+ {
+ if ( d_path )
+ delete d_path;
+ }
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgAddDummyChild
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgAddDummyChild : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eAddDummyChild; }
+
+ public:
+ MsgAddDummyChild(TreestorePath* _path) : MsgCore(_path) {}
+ virtual ~MsgAddDummyChild() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgAddChild
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgAddChild : public MsgCore
+{
+ File * d_file;
+
+ public:
+ virtual eMsgType type() { return eAddChild; }
+ File * file() { return d_file; }
+ public:
+ MsgAddChild(TreestorePath* _path, File* _file) : MsgCore(_path)
+ {
+ d_file = _file->dup();
+ }
+ virtual ~MsgAddChild()
+ {
+ delete d_file;
+ }
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgAddFirstTree
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgAddFirstTree : public MsgCore
+{
+ private:
+ File * d_file;
+
+ public:
+ virtual eMsgType type() { return eAddFirstTree; }
+ File * file() { return d_file; }
+ public:
+ MsgAddFirstTree(TreestorePath* _path, File* _file) : MsgCore(_path)
+ {
+ d_file = _file->dup();
+ }
+ virtual ~MsgAddFirstTree()
+ {
+ delete d_file;
+ }
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgDel
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgDel : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eDel; }
+
+ public:
+ MsgDel(TreestorePath* _path) : MsgCore(_path) {}
+ virtual ~MsgDel() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgSetReadable
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgSetReadable : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eSetReadable; }
+
+ public:
+ MsgSetReadable(TreestorePath * _path) : MsgCore(_path) {}
+ virtual ~MsgSetReadable() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgSetReadable
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgSetNotReadable : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eSetNotReadable; }
+
+ public:
+ MsgSetNotReadable(TreestorePath * _path) : MsgCore(_path) {}
+ virtual ~MsgSetNotReadable() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgAsyncMismatchIEFUC
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgAsyncMismatchIEFUC : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eAsyncMismatchIEFUC; }
+
+ public:
+ MsgAsyncMismatchIEFUC(TreestorePath * _path) : MsgCore(_path) {}
+ virtual ~MsgAsyncMismatchIEFUC() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgAsyncMismatchICIEC
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgAsyncMismatchICIEC : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eAsyncMismatchICIEC; }
+
+ public:
+ MsgAsyncMismatchICIEC(TreestorePath * _path) : MsgCore(_path) {}
+ virtual ~MsgAsyncMismatchICIEC() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgAsyncMismatchAFT
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgAsyncMismatchAFT : public MsgCore
+{
+ public:
+ virtual eMsgType type() { return eAsyncMismatchAFT; }
+
+ public:
+ MsgAsyncMismatchAFT(TreestorePath * _path) : MsgCore(_path) {}
+ virtual ~MsgAsyncMismatchAFT() {}
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// IMsgSort
+//
+// Interface that must implement any sort msg struct
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct IMsgSort : MsgCore
+{
+ //.................................................................
+ // automat
+ //
+ private:
+ enum eStep
+ {
+ eInit = 0,
+ eStart = 10,
+ eRun = 20,
+ eRestart = 30,
+ eDone = 40,
+ eAbort = 50,
+ eNop = 60
+ };
+
+ private:
+ eStep a_step;
+ gint a_iteration;
+ gboolean a_initialized;
+ gboolean a_error;
+ gboolean a_done;
+
+ public:
+ gboolean run();
+ gboolean spread();
+ inline gboolean done() { return a_done; }
+ inline gboolean error() { return a_error; }
+ //.................................................................
+ // lists
+ //
+ private:
+ GList * d_list_original;
+ guint a_list_card;
+
+ protected:
+ GList * d_list_actual;
+ //.................................................................
+ private:
+ gboolean list_get(GList ** _list);
+ gboolean list_changed();
+
+ protected:
+ inline guint list_card() { return a_list_card; }
+ void list_delete(GList**);
+ void list_original_copy(GList** _dest);
+
+ //.................................................................
+ // divers
+ //
+ private:
+ Model * a_model;
+ //.................................................................
+ private:
+ inline Model * model() { return a_model; }
+
+ public:
+ virtual eMsgType type() { return eSort; }
+
+ public:
+ virtual gboolean init() = 0;
+ virtual gboolean step() = 0;
+ virtual gboolean restart() = 0;
+
+ public:
+ IMsgSort(TreestorePath* _path, Model*);
+ virtual ~IMsgSort();
+};
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MsgSort_Insertion
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+struct MsgSort_Insertion : public IMsgSort
+{
+ private:
+ guint a_i0;
+ GList * d_list_work;
+
+
+ public:
+ virtual gboolean init();
+ virtual gboolean step();
+ virtual gboolean restart();
+
+ public:
+ MsgSort_Insertion(TreestorePath*, Model*);
+ virtual ~MsgSort_Insertion();
+};
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-model-vfs.cc b/src/foldview/gnome-cmd-connection-treeview-model-vfs.cc
new file mode 100644
index 0000000..ec18e1b
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-model-vfs.cc
@@ -0,0 +1,1145 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : many, vfs specific
+
+ Parent : GnomeCmdConnectionTreeview::Model
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+// ***************************************************************************
+// * Defines *
+// ***************************************************************************
+#define SVFSRESULT(result) gnome_vfs_result_to_string(result)
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # Divers #
+// ## ##
+// ### ###
+// ###########################################################################
+GnomeCmdConnectionTreeview::eFileAccess
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Access_from_GnomeVFSFilePermissions(
+ GnomeVFSFilePermissions _permissions)
+{
+ return Access_from_read_write
+ (
+ ( ( _permissions & GNOME_VFS_PERM_ACCESS_READABLE ) != 0 ),
+ ( ( _permissions & GNOME_VFS_PERM_ACCESS_WRITABLE ) != 0 )
+ );
+}
+
+GnomeCmdConnectionTreeview::eFileType
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Type_from_GnomeVFSFileType(
+ GnomeVFSFileType _type)
+{
+ eFileType type = eTypeUnknown;
+
+ if ( _type == GNOME_VFS_FILE_TYPE_DIRECTORY )
+ type = GnomeCmdConnectionTreeview::eTypeDirectory;
+
+ if ( _type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK )
+ type = GnomeCmdConnectionTreeview::eTypeSymlink;
+
+ return type;
+}
+
+GnomeCmdConnectionTreeview::eFileError
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Error_from_GnomeVFSResult(
+ GnomeVFSResult _result)
+{
+ switch ( _result )
+ {
+ case GNOME_VFS_ERROR_NOT_FOUND : return eErrorFileNotFound;
+ case GNOME_VFS_ERROR_ACCESS_DENIED : return eErrorAccessDenied;
+ case GNOME_VFS_ERROR_CANCELLED : return eErrorCancelled;
+ case GNOME_VFS_ERROR_TIMEOUT : return eErrorTimeout;
+ default : return eErrorOther;
+ }
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # GnomeVFS structs #
+// ## ##
+// ### ###
+// ###########################################################################
+
+// ***************************************************************************
+//
+// GnomeVFSAsyncTpl <>
+//
+// ***************************************************************************
+//
+// Because
+//
+// GnomeVFSAsyncEnumerateChildren
+//
+// and
+//
+// GnomeVFSAsyncGetFileInfo
+//
+// have no differences in their GnomeVFS members / fields, we use a template
+// to add these.
+//
+template <typename T> struct GnomeCmdConnectionTreeview::Model::GnomeVFSAsyncTpl : public T
+{
+ private:
+ GnomeVFSURI * d_gnomeVFS_uri;
+ GnomeVFSAsyncHandle * a_handle;
+
+ public:
+ // constructor for GnomeVFSAsyncTpl<GnomeVFSAsyncGetFileInfo>
+ GnomeVFSAsyncTpl(AsyncCallerData*, const Uri);
+ // constructor for GnomeVFSAsyncTpl<GnomeVFSAsyncEnumerateChildren>
+ GnomeVFSAsyncTpl(AsyncCallerData*, const Uri, gint _max_result, gboolean _follow_links);
+
+ virtual ~GnomeVFSAsyncTpl();
+
+ void* operator new (size_t) ;
+ void operator delete (void*);
+
+ public:
+ GnomeVFSURI * gnomevfs_uri() { return d_gnomeVFS_uri; }
+ GnomeVFSAsyncHandle * handle() { return a_handle; }
+ GnomeVFSAsyncHandle ** handle_ptr() { return &a_handle; }
+ void cancel_async_op() { gnome_vfs_async_cancel(handle()); }
+};
+
+template <typename T>
+void*
+GnomeCmdConnectionTreeview::Model::GnomeVFSAsyncTpl<T>::operator new(size_t _size)
+{
+ return (void*)(g_try_new0(GnomeVFSAsyncTpl<T>, 1));
+}
+
+template <typename T>
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFSAsyncTpl<T>::operator delete (void *_p)
+{
+ g_free(_p);
+}
+
+template <typename T>
+GnomeCmdConnectionTreeview::Model::GnomeVFSAsyncTpl<T>::~GnomeVFSAsyncTpl()
+{
+ gnome_vfs_uri_unref(d_gnomeVFS_uri);
+}
+
+
+// ***************************************************************************
+//
+// Get File Info
+//
+// ( GnomeVFSAsyncGetFileInfo = GnomeVFSAsyncTpl<AsyncGetFileInfo> )
+//
+// ***************************************************************************
+//
+// Has been declared as specified-template in gnome-cmd-foldview-private.h
+// Only need to code constructor => templates rock !
+//
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Constructor for GnomeVFSAsyncTpl<AsyncGetFileInfo>
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+template <typename T>
+GnomeCmdConnectionTreeview::Model::GnomeVFSAsyncTpl<T>::GnomeVFSAsyncTpl(
+ AsyncCallerData* _acd,
+ const Uri _uri) : T(_acd, _uri)
+{
+ d_gnomeVFS_uri = gnome_vfs_uri_new(_uri);
+ a_handle = NULL;
+}
+// ***************************************************************************
+//
+// Enumerate children
+//
+// ( GnomeVFSAsyncEnumerateChildren = GnomeVFSAsyncTpl<AsyncEnumerateChildren> )
+//
+// ***************************************************************************
+//
+// Has been declared as specified-template in gnome-cmd-foldview-private.h
+// Only need to code constructor => templates rock !
+//
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Constructor for GnomeVFSAsyncTpl<AsyncEnumerateChildren>
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+template <typename T>
+GnomeCmdConnectionTreeview::Model::GnomeVFSAsyncTpl<T>::GnomeVFSAsyncTpl(
+ AsyncCallerData* _acd,
+ const Uri _uri,
+ gint _max_result,
+ gboolean _follow_links) : T(_acd, _uri, _max_result, _follow_links)
+{
+ d_gnomeVFS_uri = gnome_vfs_uri_new(_uri);
+ a_handle = NULL;
+}
+
+// ***************************************************************************
+//
+// Monitoring
+//
+// ***************************************************************************
+
+// ===========================================================================
+// GnomeVFSMonitor
+// ===========================================================================
+void*
+GnomeCmdConnectionTreeview::Model::GnomeVFSMonitor::operator new(size_t size)
+{
+ return (void*)g_try_new0(GnomeVFSMonitor, 1);
+}
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFSMonitor::operator delete(void *p)
+{
+ g_free(p);
+}
+
+GnomeCmdConnectionTreeview::Model::GnomeVFSMonitor::GnomeVFSMonitor()
+{
+ a_monitor_handle = 0;
+}
+GnomeCmdConnectionTreeview::Model::GnomeVFSMonitor::~GnomeVFSMonitor()
+{
+ MONITOR_INF("Model::GnomeVFSMonitor::~GnomeVFSMonitor()");
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::GnomeVFSMonitor::monitoring_start(Model* _model, Row *row)
+{
+ GnomeVFSResult result = GNOME_VFS_OK;
+ MonitorData * md = NULL;
+ //.........................................................................
+
+
+ // GnomeVFSResult gnome_vfs_monitor_add(
+ // GnomeVFSMonitorHandle ** handle,
+ // const gchar * text_uri,
+ // GnomeVFSMonitorType monitor_type,
+ // GnomeVFSMonitorCallback callback,
+ // gpointer user_data);
+ //
+ // Watch the file or directory at text_uri for changes (or the creation/
+ // deletion of the file) and call callback when there is a change. If a
+ // directory monitor is added, callback is notified when any file in
+ // the directory changes.
+ //
+ // handle : after the call, handle will be a pointer to an operation handle.
+ // text_uri : string representing the uri to monitor.
+ // monitor_type : add a directory or file monitor.
+ // callback : function to call when the monitor is tripped.
+ // user_data : data to pass to callback.
+ // Returns : an integer representing the result of the operation.
+
+ md = (MonitorData*)g_try_new0(MonitorData,1);
+ if ( ! md )
+ {
+ MONITOR_ERR("Model::GnomeVFSMonitor::start():g_try_new0 failed for MonitorData");
+ return FALSE;
+ }
+ md->a_model = _model;
+ md->a_row = row;
+
+ result = gnome_vfs_monitor_add(
+ monitor_handle_ptr(),
+ row->uri_utf8(),
+ GNOME_VFS_MONITOR_DIRECTORY,
+ (GnomeVFSMonitorCallback)GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback,
+ (gpointer)md);
+
+ if ( result != GNOME_VFS_OK )
+ {
+ MONITOR_ERR("Model::GnomeVFSMonitor::start():[%s]", SVFSRESULT(result));
+ return FALSE;
+ }
+
+ MONITOR_INF("Model::GnomeVFSMonitor::start():Success [%s] [%s]", row->path()->dump(), row->uri_utf8());
+
+ Monitor::a_started = TRUE;
+
+ return TRUE;
+}
+gboolean
+GnomeCmdConnectionTreeview::Model::GnomeVFSMonitor::monitoring_stop()
+{
+ GnomeVFSResult result = GNOME_VFS_OK;
+ //.........................................................................
+ result = gnome_vfs_monitor_cancel(monitor_handle());
+
+ if ( result != GNOME_VFS_OK )
+ {
+ MONITOR_ERR("Model::GnomeVFSMonitor::stop():[%s]", SVFSRESULT(result));
+ return FALSE;
+ }
+
+ MONITOR_INF("Model::GnomeVFSMonitor::stop():Success");
+
+ Monitor::a_started = FALSE;
+
+ return TRUE;
+}
+
+
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # GnomeVFS methods #
+// ## ##
+// ### ###
+// ###########################################################################
+
+
+// ***************************************************************************
+//
+// Get file info
+//
+// ***************************************************************************
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Model::GnomeVFS::Iter_get_file_info_callback()
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Iter_get_file_info_callback(
+ GnomeVFSAsyncHandle * _handle,
+ GList * _results,
+ gpointer _data)
+{
+ GcmdStruct<GnomeVFSAsyncGetFileInfo> * gfi = NULL;
+ GList * list = NULL;
+ GnomeVFSGetFileInfoResult * result = NULL;
+ GnomeVFSFileInfo * info = NULL;
+
+ //.........................................................................
+ // #warning [*] Model::GnomeVFS::GnomeVFS::igfic() : GList delete ? NO !
+ //REFRESH_INF("Model::GnomeVFS::GnomeVFS::igfic()");
+
+ gfi = (GcmdStruct<GnomeVFSAsyncGetFileInfo>*)_data;
+ g_return_if_fail( gfi );
+
+ list = g_list_first(_results);
+ if ( ! list )
+ {
+ REFRESH_ERR("Model::GnomeVFS::GnomeVFS::igfic():empty result list");
+ goto lab_exit_false;
+ }
+
+ // GnomeVFSGetFileInfoResult :
+ //
+ // GnomeVFSURI * uri;
+ // GnomeVFSResult result;
+ // GnomeVFSFileInfo * file_info;
+ //
+ result = (GnomeVFSGetFileInfoResult*)(list->data);
+
+ if ( result->result != GNOME_VFS_OK )
+ {
+ REFRESH_ERR("Model::GnomeVFS::GnomeVFS::igfic():async call failure [%s]", SVFSRESULT(result->result));
+ gfi->error_set(Error_from_GnomeVFSResult(result->result), gnome_vfs_result_to_string(result->result));
+ goto lab_call_caller;
+ }
+
+ info = (GnomeVFSFileInfo*)(result->file_info);
+ if ( ! info )
+ {
+ REFRESH_ERR("Model::GnomeVFS::GnomeVFS::igfic():file info is NULL");
+ gfi->error_set(Error_from_GnomeVFSResult(result->result), gnome_vfs_result_to_string(result->result));
+ goto lab_call_caller;
+ }
+
+ gfi->a_name = info->name;
+ gfi->a_is_symlink = GNOME_VFS_FILE_INFO_SYMLINK(info);
+ gfi->a_symlink_name = info->symlink_name;
+ gfi->a_type = Type_from_GnomeVFSFileType(info->type);
+ gfi->a_access = Access_from_GnomeVFSFilePermissions(info->permissions);
+
+lab_call_caller:
+ (gfi->caller_data()->callback())(gfi);
+
+lab_exit_true:
+ delete gfi;
+ return;
+
+lab_exit_false:
+ delete gfi;
+ return;
+
+}
+
+// ***************************************************************************
+//
+// Enumerate children
+//
+// ***************************************************************************
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Model::GnomeVFS::Iter_enumerate_children_callback()
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Iter_enumerate_children_callback(
+ GnomeVFSAsyncHandle * _handle,
+ GnomeVFSResult _result,
+ GList * _list,
+ guint _entries_read,
+ gpointer _data)
+{
+ GnomeVFSFileInfo * info = NULL;
+
+ GList * l = NULL;
+ guint count = 0;
+ guint added = 0;
+
+ GnomeVFSAsyncEnumerateChildren * vaec = NULL;
+
+ FoldviewFile * file = NULL;
+ const gchar * file_display_name = NULL;
+ const gchar * file_display_name_ck = NULL;
+ gboolean b_read;
+ gboolean b_write;
+ eFileAccess file_access = eAccessUN;
+ gboolean file_has_flag_symlink = FALSE;
+ const gchar * file_symlink_target_name = NULL;
+ //.........................................................................
+
+ vaec = (GnomeVFSAsyncEnumerateChildren*)(_data);
+
+ // counter
+ count = 0;
+
+ // handle the '0-entry-case'
+ if ( _entries_read == 0 )
+ {
+ ENUMERATE_INF("alsc:[handle:%03i] entries:%03i name:%s, parent:%s", vaec->handle(), _entries_read, "no_more_entry" , vaec->uri());
+ goto lab_no_more_entry;
+ }
+
+ // init loop - we have at least one entry
+ l = g_list_first(_list);
+
+lab_loop:
+
+ b_read = b_write = FALSE;
+
+ count++;
+
+ info = (GnomeVFSFileInfo*)(l->data);
+
+ ENUMERATE_INF("alsc:[handle:%03i] entries:%03i name[%s] parent[%s]", vaec->handle(), _entries_read, info->name, vaec->uri());
+
+ file_display_name = info->name;
+ file_display_name_ck = g_utf8_collate_key(file_display_name, -1);
+
+ if ( ( info->permissions & GNOME_VFS_PERM_ACCESS_READABLE ) != 0 ) b_read = TRUE;
+ if ( ( info->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE ) != 0 ) b_write = TRUE;
+ file_access = Access_from_read_write(b_read,b_write);
+
+ file_has_flag_symlink = ( ( info->flags & GNOME_VFS_FILE_FLAGS_SYMLINK ) != 0 );
+ file_symlink_target_name = info->symlink_name;
+
+ //ENUMERATE_INF("alsc:[%03i] entry name:%s", vaec->handle(), file_display_name);
+
+ switch ( info->type )
+ {
+ //.....................................................................
+ case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK:
+
+ g_free((void*)file_display_name_ck);
+
+ // if follow_links is TRUE, we should not be here - except if we have
+ // a BROKEN LINK. We thus cant know if the link was pointing on a
+ // directory or something else. LNK struct handle broken links
+ // if you pass NULL as the file pointer in constructor.
+ if ( vaec->follow_links() )
+ {
+ ENUMERATE_WNG("alsc:[%03i][0x%16x] [%03i][%03i][%03i] [broken link, ignored]<%s>", vaec->handle(), l, count, added, vaec->max_result(), file_display_name);
+ //lnk = new LNK(g_strdup(info->name), ,NULL);
+ break;
+ }
+
+ //ENUMERATE_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] Symbolic link, ignored <%s>", vaec->handle(), l, count, added, vaec->max_result(), file_display_name);
+
+
+ //added++;
+
+ //ALSC_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] S<%s>", vaec->handle(), l, count, added, vaec->max_result(), file_display_name);
+
+ //lnk = new LNK(g_strdup(info->name), g_strdup(info->symlink_name), info->permissions, info->flags );
+ //ls->append( (gvfs_file*)lnk );
+
+ // if the caller want partial listing
+ //if (
+ // ( ga->mr() >= 0 ) &&
+ // ( ls->len() >= ga->mr() )
+ // )
+ // goto lab_abort;
+
+ break;
+
+ //.....................................................................
+ case GNOME_VFS_FILE_TYPE_DIRECTORY :
+
+ if ( strcmp(GnomeCmdConnectionTreeview::Collate_key_dot, file_display_name_ck ) &&
+ strcmp(GnomeCmdConnectionTreeview::Collate_key_dotdot, file_display_name_ck ))
+ {
+ ENUMERATE_INF("strcmp:%i", strcmp(GnomeCmdConnectionTreeview::Collate_key_dot, file_display_name_ck ));
+ ENUMERATE_INF("strcmp:%i", strcmp(GnomeCmdConnectionTreeview::Collate_key_dotdot, file_display_name_ck ));
+
+ added++;
+
+ ENUMERATE_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] +<%s>", vaec->handle(), l, count, added, vaec->max_result(), file_display_name);
+
+ // it is a symlink pointing on a directory
+ if ( file_has_flag_symlink )
+ file = new FoldviewLink(file_display_name, file_symlink_target_name, file_access);
+ // it is a directory
+ else
+ file = new FoldviewDir(file_display_name, file_access);
+
+ vaec->list_append( file );
+
+ // if the caller want partial listing
+ if (
+ ( vaec->max_result() >= 0 ) &&
+ ( vaec->list_card() >= vaec->max_result() )
+ )
+ {
+ g_free((void*)file_display_name_ck);
+ goto lab_abort;
+ }
+ }
+ g_free((void*)file_display_name_ck);
+ break;
+
+ //.....................................................................
+ default:
+ g_free((void*)file_display_name_ck);
+ ENUMERATE_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] <%s>", vaec->handle(), l, count, added, vaec->max_result(), file_display_name);
+ break;
+ }
+
+ // if gvfs bugs on entries_read, we bug too with this
+ if ( count == _entries_read )
+ goto lab_no_more_entry;
+
+ l = g_list_next(l);
+
+ goto lab_loop;
+
+//.............................................................................
+lab_no_more_entry:
+
+ // if OK, simply return, we will be re-called for further entries
+ if ( _result == GNOME_VFS_OK )
+ {
+ ENUMERATE_INF("alsc:[%03i][0x%16x] (GNOME_VFS_OK)", vaec->handle(), l);
+ return;
+ }
+
+ // else ensure we are in EOF case : GNOME_VFS_ERROR_EOF should be set
+ if ( _result == GNOME_VFS_ERROR_EOF )
+ goto lab_eof;
+
+ // else an error as occured : result is not OK, neither EOF.
+ // this occurs for example with symlinks, or access-denied directories ;
+ // - show a little warning
+ // - set error fileds in AsyncEnumerateChildren
+ // - and do as EOF, since there is no more entry.
+ ENUMERATE_ERR("alsc:[%03i][0x%16x] (NO ENTRY - Jumping to EOF):%s",
+ vaec->handle(), l, gnome_vfs_result_to_string(_result));
+
+ vaec->error_set(Error_from_GnomeVFSResult(_result), gnome_vfs_result_to_string(_result));
+//.............................................................................
+lab_eof:
+
+ ENUMERATE_INF("alsc:[%03i][0x%16x] (EOF)", vaec->handle(), l);
+ // Call caller callback ; caller is responsible for freeing memory
+ // eventually allocated in m_user_data member
+ // of the struct_gvfs_caller_data
+ vaec->caller_data()->callback()(vaec);
+
+ delete vaec;
+
+ // "Final end"
+ return;
+
+//.............................................................................
+lab_abort:
+
+ ENUMERATE_INF("alsc:[%03i][0x%16x] (ABORT)", vaec->handle(), l);
+ // Call caller callback ; caller is responsible for freeing memory
+ // eventually allocated in m_user_data member
+ // of the struct_gvfs_caller_data
+ (vaec->caller_data()->callback())(vaec);
+ // cancel async op
+ vaec->cancel_async_op();
+
+ delete vaec;
+
+ // "Final end"
+ //return;
+}
+
+// ***************************************************************************
+//
+// Monitoring
+//
+// ***************************************************************************
+
+// ===========================================================================
+// Monitoring : static callback
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback(
+ GnomeVFSMonitorHandle * _handle,
+ const gchar * _monitor_uri,
+ const gchar * _info_uri,
+ GnomeVFSMonitorEventType _event_type,
+ gpointer _data)
+{
+ MonitorData * md = NULL;
+
+ GnomeVFSAsyncHandle * handle = NULL;
+ GList * list = NULL;
+ GnomeVFSAsyncGetFileInfoCallback callback = NULL;
+
+ GnomeVFSURI * uri_mon = NULL;
+ GnomeVFSURI * uri_inf = NULL;
+ gchar * basename_mon = NULL;
+ gchar * basename_inf = NULL;
+ gboolean b_self = FALSE;
+ //.........................................................................
+ // GNOME_VFS_MONITOR_EVENT_CHANGED file data changed (FAM, inotify).
+ // GNOME_VFS_MONITOR_EVENT_DELETED file deleted event (FAM, inotify).
+ // GNOME_VFS_MONITOR_EVENT_STARTEXECUTING file was executed (FAM only).
+ // GNOME_VFS_MONITOR_EVENT_STOPEXECUTING executed file isn't executed anymore (FAM only).
+ // GNOME_VFS_MONITOR_EVENT_CREATED file created event (FAM, inotify).
+ // GNOME_VFS_MONITOR_EVENT_METADATA_CHANGED file metadata changed (inotify only).
+ //.........................................................................
+ md = (MonitorData*)_data;
+ g_return_if_fail( md );
+
+ // GnomeVFS is bad. It gives file:///toto/, with a trailing slash. Thus we
+ // are forced to extract the basename from temporary GnomeVFSURIs
+ uri_mon = gnome_vfs_uri_new(_monitor_uri);
+ uri_inf = gnome_vfs_uri_new(_info_uri);
+ basename_mon = gnome_vfs_uri_extract_short_name(uri_mon);
+ basename_inf = gnome_vfs_uri_extract_short_name(uri_inf);
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback(): [%s] [%s]", basename_mon, basename_inf);
+ b_self = g_utf8_collate(basename_mon, basename_inf) == 0 ? TRUE : FALSE;
+ gnome_vfs_uri_unref(uri_mon);
+ gnome_vfs_uri_unref(uri_inf);
+ switch ( _event_type )
+ {
+ //.....................................................................
+ case GNOME_VFS_MONITOR_EVENT_DELETED:
+
+ if ( b_self )
+ {
+ // Parent deleted :
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback():EVENT_DELETED (SELF) [mon:%s] [inf:%s]", _monitor_uri, _info_uri);
+ Monitor_callback_del(md);
+ goto exit;
+ }
+ else
+ {
+ // Child deleted :
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback():EVENT_DELETED (CHILD) [mon:%s] [inf:%s]", _monitor_uri, _info_uri);
+ Monitor_callback_child_del(md, basename_inf);
+ goto exit;
+ }
+ break;
+
+ //.....................................................................
+ case GNOME_VFS_MONITOR_EVENT_CREATED:
+
+ if ( b_self )
+ {
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback():EVENT_CREATED (SELF, skipping) [mon:%s] [inf:%s]", _monitor_uri, _info_uri);
+ goto abort;
+ }
+ else
+ {
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback():EVENT_CREATED (CHILD) [mon:%s] [inf:%s]", _monitor_uri, _info_uri);
+ callback = Monitor_callback_child_new;
+ list = g_list_append(list, gnome_vfs_uri_new(_info_uri));
+ }
+
+ break;
+
+ //.....................................................................
+ case GNOME_VFS_MONITOR_EVENT_METADATA_CHANGED :
+
+ // // _GWR_GVFS_BUG_
+ // Due to a GnomeVFS bug,we are forced to use child event. When a dir
+ // is not readable, showed in foldview, and when it becomes readable,
+ // we dont get { self-metadata-changed, parent-metadata-changed } events.
+ // Instead of that, we get { self-CREATED , parent-metadata-changed }.
+ //
+ // Its annoying, because working on children force us to check if the parent
+ // is collapsed, etc...
+ //
+
+ if ( b_self )
+ {
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback():EVENT_METADATA_CHANGED (SELF, skipping) [mon:%s] [inf:%s]", _monitor_uri, _info_uri);
+ //callback = Monitor_callback_acc;
+ //list = g_list_append(list, gnome_vfs_uri_new(_info_uri));
+ goto abort;
+ }
+ else
+ {
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback():EVENT_METADATA_CHANGED (CHILD) [mon:%s] [inf:%s]", _monitor_uri, _info_uri);
+ callback = Monitor_callback_child_acc;
+ list = g_list_append(list, gnome_vfs_uri_new(_info_uri));
+ }
+
+ break;
+
+ //.....................................................................
+ case GNOME_VFS_MONITOR_EVENT_CHANGED : goto abort;
+ case GNOME_VFS_MONITOR_EVENT_STARTEXECUTING : goto abort;
+ case GNOME_VFS_MONITOR_EVENT_STOPEXECUTING : goto abort;
+ }
+
+
+ // void gnome_vfs_async_get_file_info(
+ // GnomeVFSAsyncHandle ** handle_return,
+ // GList * uri_list,
+ // GnomeVFSFileInfoOptions options,
+ // int priority,
+ // GnomeVFSAsyncGetFileInfoCallback callback,
+ // gpointer callback_data);
+ //
+ // Fetch information about the files indicated in uri_list and return the
+ // information progressively to callback.
+ //
+ // handle_return : when the function returns, will point to a handle for
+ // the async operation.
+ // uri_list : a GList of GnomeVFSURIs to fetch information about.
+ // options : packed boolean type providing control over various details
+ // of the get_file_info operation.
+ // priority : a value from GNOME_VFS_PRIORITY_MIN to GNOME_VFS_PRIORITY_MAX
+ // (normally should be GNOME_VFS_PRIORITY_DEFAULT) indicating
+ // the priority to assign this job in allocating threads from the thread pool.
+ // callback : function to be called when the operation is complete.
+ // callback_data : data to pass to callback.
+
+ gnome_vfs_async_get_file_info(
+ &handle,
+ list,
+ (GnomeVFSFileInfoOptions)
+ (
+ GNOME_VFS_FILE_INFO_FOLLOW_LINKS |
+ GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS
+ ),
+ GNOME_VFS_PRIORITY_DEFAULT,
+ (GnomeVFSAsyncGetFileInfoCallback)callback,
+ _data);
+
+abort:
+exit:
+ return;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitor_callback_del()
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback_del(
+ MonitorData * _md)
+{
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback_del()");
+
+ Iter_monitor_callback_del(_md);
+
+ return;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitor_callback_child_del()
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback_child_del(
+ MonitorData * _md,
+ const Uri _uri_child)
+{
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback_child_del()");
+
+ GnomeVFSURI * temp = gnome_vfs_uri_new(_uri_child);
+ gchar * s = gnome_vfs_uri_extract_short_name(temp);
+
+ Iter_monitor_callback_child_del(_md, s);
+
+ g_free(s);
+ gnome_vfs_uri_unref(temp);
+
+ return;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitor_callback_child_new()
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback_child_new(
+ GnomeVFSAsyncHandle * _handle,
+ GList * _results,
+ gpointer _data)
+{
+ MonitorData * md = NULL;
+ GList * list = NULL;
+ GnomeVFSGetFileInfoResult * result = NULL;
+ GnomeVFSFileInfo * info = NULL;
+
+ char * name = NULL;
+ eFileType type = eTypeUnknown;
+ eFileAccess access = eAccessUN;
+ gboolean is_symlink = FALSE;
+ gchar * symlink_name = NULL;
+
+ File * child = NULL;
+ //.........................................................................
+ // #warning [*] Model::GnomeVFS::Monitor_callback_child_new() : GList delete ? NO !
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback_child_new()");
+
+ md = (MonitorData*)_data;
+ g_return_if_fail( md );
+
+ list = g_list_first(_results);
+ if ( ! list )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_child_new():empty result list");
+ goto abort;
+ }
+
+ // GnomeVFSGetFileInfoResult :
+ //
+ // GnomeVFSURI * uri;
+ // GnomeVFSResult result;
+ // GnomeVFSFileInfo * file_info;
+ //
+ result = (GnomeVFSGetFileInfoResult*)(list->data);
+
+ if ( result->result != GNOME_VFS_OK )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_child_new():async call failure [%s]", SVFSRESULT(result->result));
+ goto abort;
+ }
+
+ info = (GnomeVFSFileInfo*)(result->file_info);
+ if ( ! info )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_child_new():file info is NULL");
+ goto abort;
+ }
+
+ name = info->name;
+ type = Type_from_GnomeVFSFileType(info->type);
+ access = Access_from_GnomeVFSFilePermissions(info->permissions);
+ is_symlink = GNOME_VFS_FILE_INFO_SYMLINK(info);
+ symlink_name = info->symlink_name;
+
+ if ( type != eTypeDirectory )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_child_new():type is not directory [GnomeVFS:0x%08x]", info->type);
+ goto abort;
+ }
+ if ( access == eAccessUN )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_child_new():access not resolved [GnomeVFS:0x%08x]", info->permissions);
+ goto abort;
+ }
+
+ if ( ! is_symlink )
+ child = new Directory(name, access);
+ else
+ child = new Symlink(name, symlink_name, access);
+
+ Iter_monitor_callback_child_new(md, child);
+
+ delete child;
+
+abort:
+//exit:
+
+ return;
+}
+
+/*
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitor_callback_acc()
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback_acc(
+ GnomeVFSAsyncHandle * _handle,
+ GList * _results,
+ gpointer _data)
+{
+ MonitorData * md = NULL;
+ GList * list = NULL;
+ GnomeVFSGetFileInfoResult * result = NULL;
+ GnomeVFSFileInfo * info = NULL;
+
+ char * name = NULL;
+ eFileType type = eTypeUnknown;
+ eFileAccess access = eAccessUN;
+ gboolean is_symlink = FALSE;
+ gchar * symlink_name = NULL;
+ //.........................................................................
+ #warning Model::GnomeVFS::Monitor_callback_acc() : GList delete ?
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback_acc()");
+
+ md = (MonitorData*)_data;
+ g_return_if_fail( md );
+
+ list = g_list_first(_results);
+ if ( ! list )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_acc():empty result list");
+ goto abort;
+ }
+
+ // GnomeVFSGetFileInfoResult :
+ //
+ // GnomeVFSURI * uri;
+ // GnomeVFSResult result;
+ // GnomeVFSFileInfo * file_info;
+ //
+ result = (GnomeVFSGetFileInfoResult*)(list->data);
+
+ if ( result->result != GNOME_VFS_OK )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_acc():async call failure [%s]", SVFSRESULT(result->result));
+ goto abort;
+ }
+
+ info = (GnomeVFSFileInfo*)(result->file_info);
+ if ( ! info )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_acc():file info is NULL");
+ goto abort;
+ }
+
+ name = info->name;
+ type = Type_from_GnomeVFSFileType(info->type);
+ access = Access_from_GnomeVFSFilePermissions(info->permissions);
+ is_symlink = GNOME_VFS_FILE_INFO_SYMLINK(info);
+ symlink_name = info->symlink_name;
+
+ Iter_monitor_callback_acc(md, access, name);
+
+abort:
+//exit:
+ return;
+
+}
+*/
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Monitor_callback_child_acc()
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::Monitor_callback_child_acc(
+ GnomeVFSAsyncHandle * _handle,
+ GList * _results,
+ gpointer _data)
+{
+ MonitorData * md = NULL;
+ GList * list = NULL;
+ GnomeVFSGetFileInfoResult * result = NULL;
+ GnomeVFSFileInfo * info = NULL;
+
+ char * name = NULL;
+ eFileType type = eTypeUnknown;
+ eFileAccess access = eAccessUN;
+ gboolean is_symlink = FALSE;
+ gchar * symlink_name = NULL;
+ //.........................................................................
+ // #warning [*] Model::GnomeVFS::Monitor_callback_acc() : GList delete ? NO !
+ MONITOR_INF("Model::GnomeVFS::Monitor_callback_acc()");
+
+ md = (MonitorData*)_data;
+ g_return_if_fail( md );
+
+ list = g_list_first(_results);
+ if ( ! list )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_acc():empty result list");
+ goto abort;
+ }
+
+ // GnomeVFSGetFileInfoResult :
+ //
+ // GnomeVFSURI * uri;
+ // GnomeVFSResult result;
+ // GnomeVFSFileInfo * file_info;
+ //
+ result = (GnomeVFSGetFileInfoResult*)(list->data);
+
+ if ( result->result != GNOME_VFS_OK )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_acc():async call failure [%s]", SVFSRESULT(result->result));
+ goto abort;
+ }
+
+ info = (GnomeVFSFileInfo*)(result->file_info);
+ if ( ! info )
+ {
+ MONITOR_ERR("Model::GnomeVFS::Monitor_callback_acc():file info is NULL");
+ goto abort;
+ }
+
+ name = info->name;
+ type = Type_from_GnomeVFSFileType(info->type);
+ access = Access_from_GnomeVFSFilePermissions(info->permissions);
+ is_symlink = GNOME_VFS_FILE_INFO_SYMLINK(info);
+ symlink_name = info->symlink_name;
+
+ Iter_monitor_callback_child_acc(md, access, name);
+
+abort:
+//exit:
+
+ return;
+
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # Model Wrappers #
+// ## ##
+// ### ###
+// ###########################################################################
+
+//=============================================================================
+// GnomeVFS::iter_check_if_empty
+//=============================================================================
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::iter_check_if_empty(
+ AsyncCallerData * _acd,
+ const Uri _uri)
+{
+ GnomeVFSAsyncEnumerateChildren * vaec = NULL;
+ //.........................................................................
+ //vaec = new GnomeVFSAsyncEnumerateChildren(_acd, _uri, 1, TRUE);
+ vaec = GCMD_STRUCT_NEW(GnomeVFSAsyncEnumerateChildren, _acd, _uri, 1, TRUE);
+
+ // Launch gvfs async op !
+ // uri ref_count is not incremented
+ gnome_vfs_async_load_directory_uri(
+ vaec->handle_ptr(),
+ vaec->gnomevfs_uri(),
+ (GnomeVFSFileInfoOptions)
+ (
+ GNOME_VFS_FILE_INFO_DEFAULT |
+ GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS |
+ GNOME_VFS_FILE_INFO_FOLLOW_LINKS
+ ),
+ GCMDGTKFOLDVIEW_GVFS_ITEMS_PER_NOTIFICATION,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ Iter_enumerate_children_callback,
+ (gpointer)vaec);
+}
+
+//=============================================================================
+// GnomeVFS::iter_enumerate_children
+//=============================================================================
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::iter_enumerate_children(
+ AsyncCallerData * _acd,
+ const Uri _uri)
+{
+ GnomeVFSAsyncEnumerateChildren * vaec = NULL;
+ //.........................................................................
+ vaec = GCMD_STRUCT_NEW(GnomeVFSAsyncEnumerateChildren, _acd, _uri, -1, TRUE);
+
+ // Launch gvfs async op !
+ // uri ref_count is not incremented
+ gnome_vfs_async_load_directory_uri(
+ vaec->handle_ptr(),
+ vaec->gnomevfs_uri(),
+ (GnomeVFSFileInfoOptions)
+ (
+ GNOME_VFS_FILE_INFO_DEFAULT |
+ GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS |
+ GNOME_VFS_FILE_INFO_FOLLOW_LINKS
+ ),
+ GCMDGTKFOLDVIEW_GVFS_ITEMS_PER_NOTIFICATION,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ GnomeVFS::Iter_enumerate_children_callback,
+ (gpointer)vaec);
+}
+
+//=============================================================================
+// GnomeVFS::iter_file_info
+//=============================================================================
+void
+GnomeCmdConnectionTreeview::Model::GnomeVFS::iter_get_file_info(
+ AsyncCallerData * _acd,
+ const Uri _uri)
+{
+ GnomeVFSAsyncGetFileInfo * gfi = NULL;
+ GList * list = NULL;
+ //.........................................................................
+ gfi = GCMD_STRUCT_NEW(GnomeVFSAsyncGetFileInfo, _acd, _uri);
+ list = g_list_append(list, gfi->gnomevfs_uri());
+ //GCMD_INF_vfs("als :[%03i] [0x%16x][0x%16x][%03i] Launch", hi, ga, ls, max_result);
+
+ // Launch gvfs async op !
+ // uri ref_count is not incremented
+
+ gnome_vfs_async_get_file_info(
+ gfi->handle_ptr(),
+ list,
+ (GnomeVFSFileInfoOptions)
+ (
+ GNOME_VFS_FILE_INFO_DEFAULT |
+ GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS |
+ GNOME_VFS_FILE_INFO_FOLLOW_LINKS
+ ),
+ GNOME_VFS_PRIORITY_DEFAULT,
+ GnomeVFS::Iter_get_file_info_callback,
+ (gpointer)gfi);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-model.cc b/src/foldview/gnome-cmd-connection-treeview-model.cc
new file mode 100644
index 0000000..17d447f
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-model.cc
@@ -0,0 +1,2363 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-model.cc
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : Model
+
+ Parent : GnomeCmdConnectionTreeview
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+// ***************************************************************************
+// Defines
+// ***************************************************************************
+
+// ***************************************************************************
+// static
+// ***************************************************************************
+static gboolean _USE_GIO_ = GCMDGTKFOLDVIEW_USE_GIO;
+static gboolean _ALLOW_MONITORING_ = GCMDGTKFOLDVIEW_ALLOW_MONITORING;
+static const gchar * _STRING_NOT_AVAILABLE_ = "* String not available *";
+
+GtkTreeIter GnomeCmdConnectionTreeview::Model::Iter_zero = { 0,0,0,0 };
+
+const gchar* GnomeCmdConnectionTreeview::Model::Msg_names[] =
+{
+ "eAddDummyChild" ,
+ "eAddChild" ,
+
+ "eDel" ,
+
+ "eSetReadable" ,
+ "eSetNotReadable"
+};
+const gchar* GnomeCmdConnectionTreeview::Model::Msg_name(eMsgType _type)
+{
+ switch ( _type )
+ {
+ case eAddDummyChild : return Msg_names[0];
+ case eAddChild : return Msg_names[1];
+
+ case eDel : return Msg_names[2];
+
+ case eSetReadable : return Msg_names[3];
+ case eSetNotReadable : return Msg_names[4];
+
+ default : return _STRING_NOT_AVAILABLE_;
+ }
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # All structs are in this file #
+// # | #
+// ## V ##
+// ### ###
+// ###########################################################################
+//#include "gnome-cmd-connection-treeview-model.structs.snippet.h"
+
+// ###########################################################################
+//
+// new, ...
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::Model::Model(
+ GnomeCmdConnectionTreeview::Control * _control)
+{
+ raz_pointers();
+ init_instance(_control);
+}
+GnomeCmdConnectionTreeview::Model::~Model()
+{
+ dispose();
+ finalize();
+}
+
+void
+GnomeCmdConnectionTreeview::Model::raz_pointers()
+{
+ a_control = NULL;
+ d_treestore = NULL;
+}
+void
+GnomeCmdConnectionTreeview::Model::init_instance(
+ Control *_control)
+{
+ a_control = _control;
+
+ (sLogger.log_function(eLogGcmd, Logger::eLogInf))(sLogger.channel(eLogGcmd)->get_header(), "TEST");
+
+ // log infos on config
+ GCMD_INF("Model::create():Using %s library for filesystem access",
+ _USE_GIO_ ? "GIO" : "GnomeVFS");
+
+
+ GCMD_INF("Model::create():Monitoring is %s",
+ _ALLOW_MONITORING_ ? "ENABLED" : "DISABLED");
+
+ d_treestore = gnome_cmd_foldview_treestore_new();
+
+ // dont do sink on a widget that will be parented !!!
+ // else all the unref mechanism will be broken, and dispose & finalize
+ // will never be called, or you will run in segfaults when unref
+ //g_object_ref_sink(a_treestore);
+}
+
+
+void GnomeCmdConnectionTreeview::Model::dispose()
+{
+ GCMD_INF("GnomeCmdConnectionTreeview::Model::dispose()");
+
+ GCMD_INF("GnomeCmdConnectionTreeview::Model::dispose::treestore refcount = %03i", d_treestore->refcount());
+ g_object_unref(d_treestore);
+
+ d_treestore = NULL;
+}
+
+void GnomeCmdConnectionTreeview::Model::finalize()
+{
+ GCMD_INF("GnomeCmdConnectionTreeview::Model::finalize()");
+
+ //-delete d_quickstack;
+}
+
+// ###########################################################################
+//
+// Divers
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::Model::IterInfo::eFields operator | (
+ GnomeCmdConnectionTreeview::Model::IterInfo::eFields a,
+ GnomeCmdConnectionTreeview::Model::IterInfo::eFields b)
+{
+ return (GnomeCmdConnectionTreeview::Model::IterInfo::eFields)( (guint32)a | (guint32)b );
+}
+
+
+
+gchar*
+GnomeCmdConnectionTreeview::Model::collate_key_new_from_utf8(
+ const gchar* _utf8_str)
+{
+ return g_utf8_collate_key(_utf8_str, g_utf8_strlen(_utf8_str, -1));
+}
+
+// ###########################################################################
+//
+// GtkTreeModelIface wrappers
+//
+// ###########################################################################
+// ===========================================================================
+// get_iter
+// ===========================================================================
+gboolean GnomeCmdConnectionTreeview::Model::get_iter(
+ GtkTreePath *path,
+ GtkTreeIter *iter)
+{
+ return GnomeCmdFoldviewTreestore::get_iter(
+ treemodel(),
+ iter,
+ path);
+}
+
+// ===========================================================================
+// get value for iter
+// ===========================================================================
+void GnomeCmdConnectionTreeview::Model::get_value(GtkTreeIter *in, gint column, GValue *value)
+{
+ GnomeCmdFoldviewTreestore::get_value(treemodel(), in, column, value);
+}
+
+// ===========================================================================
+// Count childs of an iter
+// ===========================================================================
+gint GnomeCmdConnectionTreeview::Model::iter_n_children(GtkTreeIter *parent)
+{
+ return GnomeCmdFoldviewTreestore::iter_n_children(treemodel(), parent);
+}
+
+// ###########################################################################
+//
+// Custom methods
+//
+// ###########################################################################
+
+// ===========================================================================
+// get the TreeRow for an iter
+// ===========================================================================
+GnomeCmdConnectionTreeview::Model::Row*
+GnomeCmdConnectionTreeview::Model::iter_get_treerow(
+ GtkTreeIter * _iter)
+{
+ TreestoreData * _data = NULL;
+ //.........................................................................
+
+ if ( ! treestore()->ext_get_data(_iter, &_data) )
+ return NULL;
+
+ return (Row*)_data;
+}
+// ===========================================================================
+// get the TreeRow for an iter
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_get_treerow(
+ GtkTreeIter * _iter,
+ Row ** _row_ptr)
+{
+ GnomeCmdFoldviewTreestore::DataInterface * _data = NULL;
+ //.........................................................................
+
+ if ( ! treestore()->ext_get_data(_iter, &_data) )
+ return FALSE;
+
+ *_row_ptr = (Row*)_data;
+ return TRUE;
+}
+// ===========================================================================
+// set the TreeRow for an iter
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_set_treerow(
+ GtkTreeIter * _iter,
+ Row * _row)
+{
+ g_return_val_if_fail( _iter, FALSE );
+ g_return_val_if_fail( _row, FALSE );
+
+ treestore()->ext_set_data(_iter, _row);
+ return TRUE;
+}
+// ===========================================================================
+// iter_is_expanded / collapsed
+// given an iter, return its display status in the GtkTreeView
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_is_expanded(
+ GtkTreeIter * _iter)
+{
+ GtkTreePath * gtk_path = NULL;
+ gboolean b = FALSE;
+ //.........................................................................
+ gtk_path = GnomeCmdFoldviewTreestore::get_path(treemodel(), _iter);
+ if ( ! gtk_path )
+ return FALSE;
+
+ b = ( control()->row_state(gtk_path) == eRowStateExpanded );
+ gtk_tree_path_free(gtk_path);
+ return b;
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_is_collapsed(
+ GtkTreeIter * _iter)
+{
+ return (! iter_is_expanded(_iter));
+}
+// ===========================================================================
+// given an iter, return its display string in GtkTreeview
+// ===========================================================================
+const gchar*
+GnomeCmdConnectionTreeview::Model::iter_get_display_string(GtkTreeIter *iter)
+{
+ Row * r = NULL;
+ GValue v = {0};
+ //.........................................................................
+ gtk_tree_model_get_value(treemodel(), iter, 0, &v);
+
+ r = (Row*)g_value_get_pointer(&v);
+
+ return r->utf8_name_display();
+}
+// ===========================================================================
+// given an iter, return a mallocated GnomeVFSURI
+// ===========================================================================
+const GnomeCmdConnectionTreeview::Uri
+GnomeCmdConnectionTreeview::Model::iter_get_uri(GtkTreeIter *final)
+{
+ Row * r = NULL;
+ GValue v = {0};
+ //.........................................................................
+
+ GnomeCmdFoldviewTreestore::get_value(treemodel(), final, 0, &v);
+ r = (Row*)g_value_get_pointer(&v);
+
+ // new uri
+ return r->uri_utf8();
+}
+// ===========================================================================
+// given an iter, return its root iter
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_get_root(
+ GtkTreeIter *in_any,
+ GtkTreeIter *out_root)
+{
+ return treestore()->ext_get_root(in_any, out_root);
+}
+
+// ===========================================================================
+// given an iter, return its gtk-style path
+// ===========================================================================
+gchar*
+GnomeCmdConnectionTreeview::Model::iter_get_path_str_new(GtkTreeIter* in)
+{
+ return treestore()->ext_get_gtk_path_str_new(in);
+}
+
+// ===========================================================================
+// Checks if an iter has a given uid
+// ===========================================================================
+/*
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_has_uid(
+ GtkTreeIter* in,
+ gint uid)
+{
+ //.........................................................................
+
+ return ( treestore()->iter_get_uid() == uid );
+}
+*/
+// ===========================================================================
+// Checks is 2 iters points on the same node
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_same(
+ GtkTreeIter* iter1,
+ GtkTreeIter* iter2)
+{
+ return ( iter1->user_data == iter2->user_data );
+}
+// ===========================================================================
+// Checks is an iter is a root iter
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_is_root(
+ GtkTreeIter* iter)
+{
+ return treestore()->ext_is_root(iter);
+}
+
+// ===========================================================================
+// Return an iter's depth
+// ===========================================================================
+gint
+GnomeCmdConnectionTreeview::Model::iter_depth(
+ GtkTreeIter* iter)
+{
+ return treestore()->ext_iter_depth(iter);
+}
+
+// ===========================================================================
+// iter_add_tree()
+// ===========================================================================
+//
+// Add a tree starting from an iter
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_add_tree(
+GtkTreeIter *iter_in,
+GtkTreeIter *iter_tree_out)
+{
+ Row * rw = NULL;
+ //.........................................................................
+ // get the value to copy
+ treestore()->ext_get_data(iter_in, (TreestoreData**)&rw);
+
+ return iter_add_tree(
+ rw->uri_utf8(), rw->utf8_name_display(), rw->utf8_symlink_target_uri(),
+ rw->access(), rw->is_link(),
+ control()->is_samba(), control()->is_local(), control()->host_redmond(),
+ iter_tree_out);
+}
+// ===========================================================================
+// add_tree()
+// ===========================================================================
+//
+// Add a tree starting from a GnomeCmdCon & GnomeCmdPath
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_add_tree(
+ Uri _utf8_uri,
+ const gchar* _utf8_display_name,
+ Uri _utf8_symlink_target_uri,
+ eFileAccess _access,
+ gboolean _is_symlink,
+ gboolean _is_samba,
+ gboolean _is_local,
+ gboolean _host_redmond,
+ GtkTreeIter * _iter_tree_out)
+{
+ Row * rt = NULL;
+ //.........................................................................
+ rt = new Row(
+ eRowRoot, _utf8_uri, _utf8_display_name, _utf8_symlink_target_uri,
+ _access, _is_symlink,
+ _is_samba, _is_local, _host_redmond);
+
+ // add it to the store
+ iter_add_child(NULL, _iter_tree_out, rt);
+
+ return TRUE;
+}
+
+// ===========================================================================
+// iter_add_child()
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_add_child(
+ GtkTreeIter * _parent, // in
+ GtkTreeIter * _child, // out
+ Row * _row_child)
+{
+ // add the child to the treestore
+ treestore()->ext_add_child(_parent, _child, _row_child);
+
+ // if the child is not a dummy child, start monitoring
+ if ( ! _row_child->is_dummy() )
+ { //iter_monitor_start(_child);
+ } // _GWR_UNCOMMENT_
+ else
+ GCMD_ERR("USE iter_dummy_child_add instead of iter_add_child with a dummy");
+
+ return TRUE;
+}
+
+// ===========================================================================
+// iter_dummy_child_add()
+// ===========================================================================
+//
+// For adding the dummy, we dont call iter_add_child(), since it would start
+// monitoring. Instead we call treestore()->ext_add_child.
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_dummy_child_add(
+ GtkTreeIter * _iter_parent, // in
+ GtkTreeIter * _iter_dummy) // out
+{
+ gint n_parent = 0;
+
+ Row * rw_parent = NULL;
+ Row * rw_dummy = NULL;
+ //.........................................................................
+ n_parent = iter_n_children(_iter_parent);
+ if ( n_parent != 0 )
+ {
+ GCMD_ERR("Model::iter_dummy_child_add():parent has already children (%03i)", n_parent);
+ return FALSE;
+ }
+
+ if ( ! iter_get_treerow(_iter_parent, &rw_parent) )
+ {
+ GCMD_ERR("Model::iter_dummy_child_add():could not get parent TreeRow");
+ return FALSE;
+ }
+
+ rw_dummy = new Row(eRowDummy, rw_parent);
+
+ // calling treestore directly, no monitoring
+ treestore()->ext_add_child(_iter_parent, _iter_dummy, rw_dummy);
+
+ return TRUE;
+}
+
+// ===========================================================================
+// iter_dummy_child_remove()
+// ===========================================================================
+//
+// We simply call iter_remove(), with some verifications.
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_dummy_child_remove(
+ GtkTreeIter * _iter_parent)
+{
+ gint n_parent = 0;
+
+ GtkTreeIter iter_child = Iter_zero;
+ Row * rw_child = NULL;
+ //.........................................................................
+ n_parent = iter_n_children(_iter_parent);
+ if ( n_parent != 1 )
+ {
+ GCMD_ERR("Model::iter_dummy_child_remove():parent has not exactly one child (%03i)", n_parent);
+ return FALSE;
+ }
+
+ if ( ! GnomeCmdFoldviewTreestore::iter_children(treemodel(), &iter_child, _iter_parent) )
+ {
+ GCMD_ERR("Model::iter_dummy_child_remove():could not get child iter");
+ return FALSE;
+ }
+
+ if ( ! iter_get_treerow(&iter_child, &rw_child) )
+ {
+ GCMD_ERR("Model::iter_dummy_child_remove():could not get child TreeRow");
+ return FALSE;
+ }
+
+ if ( ! rw_child->is_dummy() )
+ {
+ GCMD_ERR("Model::iter_dummy_child_remove():child is not a dummy");
+ return FALSE;
+ }
+
+ if ( treestore()->ext_iter_sterile_remove(&iter_child) < 0 )
+ return FALSE;
+
+ return TRUE;
+}
+
+// ===========================================================================
+// iter_dummy_child_replace()
+// ===========================================================================
+//
+// It seems that we can append rows during text_expand_row signal, but not // _GWR_GTK_
+// remove rows. So instead of removing [DUMMY], we replace its value...
+//
+void
+GnomeCmdConnectionTreeview::Model::iter_dummy_child_replace(
+ GtkTreeIter * _iter_parent,
+ GtkTreeIter * _iter_child,
+ Row * _rw_child_new)
+{
+ Row * rw_dummy = NULL;
+ gint n = 0;
+ //.........................................................................
+ n = iter_n_children(_iter_parent);
+ if ( n !=1 )
+ {
+ GCMD_ERR("Model::iter_dummy_child_replace():parent has %03i children", n);
+ return;
+ }
+
+ if ( !GnomeCmdFoldviewTreestore::iter_children(treemodel(), _iter_child, _iter_parent) )
+ {
+ GCMD_ERR("Model::iter_dummy_child_replace():could not get first child");
+ return;
+ }
+
+ rw_dummy = iter_get_treerow(_iter_child);
+ if ( ! rw_dummy )
+ {
+ GCMD_ERR("Model::iter_dummy_child_replace():could not get first child's treerow");
+ return;
+ }
+ if ( ! rw_dummy->is_dummy() )
+ {
+ GCMD_ERR("Model::iter_dummy_child_replace():first child's treerow is not dummy");
+ return;
+ }
+
+ // we dont stop monitoring on child, since it is a dummy child, thus not monitored
+
+ // replace child's dummy treerow by the new one, signal will be emitted
+ treestore()->ext_set_data(_iter_child, _rw_child_new);
+
+ // start monitoring on child
+ //iter_monitor_start(_iter_child); // _GWR_UNCOMMENT_
+}
+
+// ===========================================================================
+// iter_dummy_child_check()
+// ===========================================================================
+//
+// Check if an iter has a dummy child
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_dummy_child_check(
+ GtkTreeIter * _iter_parent)
+{
+ GtkTreeIter iter_child = Iter_zero;
+ Row * rw_child = NULL;
+ //.........................................................................
+ if ( iter_n_children(_iter_parent) != 1 )
+ return FALSE;
+
+ if ( ! GnomeCmdFoldviewTreestore::iter_children(treemodel(), &iter_child, _iter_parent) )
+ {
+ GCMD_ERR("Model::iter_dummy_child_check():could not get child iter");
+ return FALSE;
+ }
+
+ if ( ! iter_get_treerow(&iter_child, &rw_child) )
+ {
+ GCMD_ERR("Model::iter_dummy_child_check():could not get child TreeRow");
+ return FALSE;
+ }
+
+ return rw_child->is_dummy();
+}
+
+// ===========================================================================
+// iter_dummy_child_check()
+// ===========================================================================
+//
+// Check if an iter has a dummy child
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_remove(
+ GtkTreeIter * _iter)
+{
+ gint n = 0;
+ eRowState state = eRowStateUnknown;
+ GtkTreePath * gtk_path = NULL;
+ //.........................................................................
+ GCMD_WNG("iter_remove");
+
+ // get the # of children
+ n = iter_n_children(_iter);
+
+ // get the GtkTreePath
+ gtk_path = GnomeCmdFoldviewTreestore::get_path(treemodel(), _iter);
+ if ( ! gtk_path )
+ goto lab_failure;
+
+ // get the view state of the parent
+ state = control()->row_state(gtk_path);
+
+ //.........................................................................
+ // iter is sterile : goto remove_sterile
+ if ( n == 0 )
+ goto remove_sterile;
+
+ //.........................................................................
+ // iter is fertile, and is expanded
+ if ( state == eRowStateExpanded )
+ {
+ // It is a hack ! Let GtkTreeView update its cache by collapsing !
+ // We dont have to manually delete each row and signals on them !
+ if ( ! control()->row_collapse(gtk_path) ) // __GWR__HACK__
+ {
+ GCMD_ERR("Model::iter_remove():iter could not be collapsed");
+ goto lab_failure;
+ }
+
+ // We dont return here, since the iter is in the following state !
+ }
+
+ //.........................................................................
+ // iter is fertile, and is not expanded. Silently remove all children.
+ // After that, we are in the following case.
+ iter_collapsed_remove_children(_iter);
+
+ //.........................................................................
+ // iter is sterile :remove it, and send "removed row" signal. But first
+ // stop monitoring
+remove_sterile:
+ //iter_monitor_stop(_iter); // _GWR_UNCOMMENT_
+
+ if ( treestore()->ext_iter_sterile_remove(_iter) < 0 )
+ goto lab_failure;
+
+lab_exit:
+ if ( gtk_path )
+ gtk_tree_path_free(gtk_path);
+ return TRUE;
+
+lab_failure:
+ if ( gtk_path )
+ gtk_tree_path_free(gtk_path);
+ return FALSE;
+}
+
+// ===========================================================================
+// iter_collapsed_remove_children()
+// ===========================================================================
+//
+// Remove all children of a _COLLAPSED_ iter
+//
+gint GnomeCmdConnectionTreeview::Model::iter_collapsed_remove_children(GtkTreeIter *parent)
+{
+ return treestore()->ext_iter_remove_children_no_signal_row_deleted(parent);
+}
+
+// ===========================================================================
+// iter_remove_all()
+// ===========================================================================
+//
+// Remove all children i.e. clear the treestore
+//
+void GnomeCmdConnectionTreeview::Model::iter_remove_all()
+{
+ treestore()->ext_clear();
+}
+
+// ###########################################################################
+//
+// Match functions
+//
+// ###########################################################################
+
+//=============================================================================
+// Match iter by its data's uid
+//=============================================================================
+/*
+gboolean
+GnomeCmdConnectionTreeview::Model::Match_function_uid(
+ GnomeCmdFoldviewTreestore::Data* data,
+ gint uid)
+{
+ g_assert(FALSE);
+ //return ( ((TreeRow*)data)->uid() != uid ? FALSE : TRUE );
+ return TRUE;
+}
+*/
+//=============================================================================
+// Match iter by its data's collate key
+//=============================================================================
+//
+// GnomeCmdFoldviewTreestore::Data has access to collate keys
+//
+
+// ###########################################################################
+//
+// Files functions
+//
+// ###########################################################################
+
+//=============================================================================
+// iter_files_file_filter()
+//=============================================================================
+//
+// Check if a file can be added
+//
+// This is an adaptation of :
+// gboolean GnomeCmdFileList::file_is_wanted(GnomeCmdFile *f)
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_files_file_filter(
+ File * _file)
+{
+ GnomeVFSFileType type = GNOME_VFS_FILE_TYPE_DIRECTORY;
+ //.........................................................................
+ g_return_val_if_fail ( _file != NULL, FALSE );
+
+ if ( !_file->is_dir() && !_file->is_symlink() )
+ {
+ FILES_ERR("Model::iter_files_file_filter:not a directory, nor a symlink");
+ return FALSE;
+ }
+
+ if ( _file->is_symlink() )
+ type = GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK;
+
+ //.........................................................................
+ if (strcmp (_file->name_utf8(), ".") == 0)
+ {
+ FILES_INF("Model::iter_files_file_filter:dot");
+ return FALSE;
+ }
+ if (strcmp (_file->name_utf8(), "..") == 0)
+ {
+ FILES_INF("Model::iter_files_file_filter:dot dot");
+ return FALSE;
+ }
+ if (gnome_cmd_data.hide_type(type) )
+ {
+ FILES_INF("Model::iter_files_file_filter:hidden type");
+ return FALSE;
+ }
+ if (_file->name_utf8()[0] == '.' && gnome_cmd_data.filter_settings.hidden)
+ {
+ FILES_INF("Model::iter_files_file_filter:hidden file");
+ return FALSE;
+ }
+ if (gnome_cmd_data.filter_settings.backup && patlist_matches(gnome_cmd_data_get_backup_pattern_list (), _file->name_utf8()) )
+ {
+ FILES_INF("Model::iter_files_file_filter:backup");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// ===========================================================================
+// iter_files_add_at_least_one()
+// ===========================================================================
+//
+// Check if at least on file from a gvfs_async_load_subdirs can be added
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_files_add_at_least_one(
+ GList * _list)
+{
+ GList * list = NULL;
+ FoldviewFile * file = NULL;
+ //.........................................................................
+
+ list = g_list_first(_list);
+
+ while (list )
+ {
+ file = (File*)list->data;
+
+ if ( iter_files_file_filter(file) )
+ return TRUE;
+
+ list = g_list_next(list);
+ }
+ return FALSE;
+}
+
+// ===========================================================================
+// iter_files_add_file()
+// ===========================================================================
+//
+// Add one file
+//
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_files_add_file(
+ GtkTreeIter * _iter_parent,
+ GtkTreeIter * _iter_child,
+ FoldviewFile * _file,
+ gboolean _check_for_doubloon,
+ gboolean _replace_first_child)
+{
+ gchar * utf8_collate_key_file = NULL;
+ Row * row_parent = NULL;
+ Row * row_child = NULL;
+ //.........................................................................
+ g_return_val_if_fail( _iter_parent, FALSE );
+ g_return_val_if_fail( _iter_child, FALSE );
+ g_return_val_if_fail( _file, FALSE );
+
+ // filter
+ if ( ! iter_files_file_filter(_file) )
+ return FALSE;
+
+ // doubloons
+ if ( _check_for_doubloon )
+ {
+ utf8_collate_key_file = collate_key_new_from_utf8(_file->name_utf8());
+
+ if ( treestore()->ext_match_child_str(_iter_parent, _iter_child, utf8_collate_key_file) )
+ {
+ g_free(utf8_collate_key_file);
+ return FALSE;
+ }
+
+ g_free(utf8_collate_key_file);
+ }
+
+ row_parent = iter_get_treerow(_iter_parent);
+ if ( ! row_parent )
+ return FALSE;
+
+ // build the TreeRow
+ row_child = new Row(eRowStd, row_parent, _file);
+
+ // add it !
+ if ( _replace_first_child )
+ iter_dummy_child_replace(_iter_parent, _iter_child, row_child);
+ else
+ iter_add_child(_iter_parent, _iter_child, row_child);
+
+ return TRUE;
+}
+
+// ###########################################################################
+//
+// Refresh
+//
+// ###########################################################################
+//
+// Rescan all subiters of an iter for
+//
+// - checking filesystem modifications
+// - taking care of display criteria modifications
+//
+// We need 2 async ops on each iter :
+//
+// 1. We first need to do a get_file_info call on the iter, since
+// enumerate_children dont tell us anything about it...
+//
+// 2. Call enumerate_children on the iter
+//
+
+// ===========================================================================
+// iter_refresh_action()
+// ===========================================================================
+//
+// Branch on different actions, depending on file new / old readability, and
+// iter expanded / collapsed status ( called "state" )
+//
+// An iter state is summarized by 3 letters :
+//
+// a-b-c
+// | | |
+// | | +---------------+
+// | | |
+// | | c ( collapsed ) / e ( expanded )
+// | |
+// | +---------+
+// | |
+// | new readability : y / n
+// |
+// old readability : y / n
+//
+// All readabilty switches can be handled by the iter_readable_set / unset
+// functions already written for monitoring events.
+//
+// All readability equalities can not be handled by monitoring code, and have
+// specific treatment ( = new code = true refresh code )
+//
+void
+GnomeCmdConnectionTreeview::Model::iter_refresh_action(
+ GtkTreeIter * _iter,
+ TreestorePath * _path,
+ gboolean _old_readable,
+ gboolean _new_readable,
+ gboolean _collapsed)
+{
+ if ( _new_readable )
+ {
+ if ( _old_readable )
+ {
+ if ( _collapsed )
+ goto lab_y_y_c;
+ else
+ goto lab_y_y_e;
+ }
+ else
+ {
+ if ( _collapsed )
+ goto lab_n_y_c;
+ else
+ goto lab_n_y_e;
+ }
+ }
+ else
+ {
+ if ( _old_readable )
+ {
+ if ( _collapsed )
+ goto lab_y_n_c;
+ else
+ goto lab_y_n_e;
+ }
+ else
+ {
+ if ( _collapsed )
+ goto lab_n_n_c;
+ else
+ goto lab_n_n_e;
+ }
+ }
+
+ REFRESH_ERR("Model::ira():*** MACHINE PB ***");
+ goto lab_abort;
+
+ if ( TRUE ) // _GWR_FOLD_
+ {
+ //.........................................................................
+lab_y_y_c:
+ // See if iter has children, for showing / hiding the GtkTreeView arrow
+ REFRESH_INF("Model::ira():Readable - Readable - Collapsed")
+ iter_check_if_empty(_iter);
+ goto lab_exit;
+ //.........................................................................
+lab_y_y_e:
+ // most complicated case, true refresh ( see iter_refresh_children_callback )
+ // ( In fact there is a simple method, inspired from the _GTK_HACK_ of
+ // iter_remove : collapse the GtkTreeView, silently delete all children, call
+ // iter_expand, and finally expand the GtkTreeView - but the many collapsing
+ // and expanding would make look the foldview like an animated GIF - or
+ // a christmas tree :)
+ REFRESH_INF("Model::ira():Readable - Readable - Expanded")
+ iter_enumerate_children(_iter, Iter_refresh_children_callback);
+ goto lab_exit;
+ //.........................................................................
+lab_n_y_c:
+ REFRESH_INF("Model::ira():NOT Readable - Readable - Collapsed")
+ control()->message_fifo_push( GCMD_STRUCT_NEW(MsgSetReadable, _path) );
+ goto lab_exit;
+ //.........................................................................
+lab_n_y_e:
+ // most complicated case, etc...
+ REFRESH_INF("Model::ira():NOT Readable - Readable - Expanded")
+ iter_enumerate_children(_iter, Iter_refresh_children_callback);
+ //.........................................................................
+lab_y_n_c:
+lab_y_n_e:
+ REFRESH_INF("Model::ira():Readable - Not Readable - ...")
+ control()->message_fifo_push( GCMD_STRUCT_NEW(MsgSetNotReadable, _path) );
+ goto lab_exit;
+ //.........................................................................
+lab_n_n_c:
+ // do nothing
+ REFRESH_INF("Model::ira():NOT Readable - NOT Readable - Collapsed")
+ goto lab_exit;
+ //.........................................................................
+lab_n_n_e:
+ // Program Logic Error : an iter can not be Not Readable and Expanded
+ REFRESH_ERR("Model::ira():PLE: NOT Readable - NOT Readable - Expanded")
+ goto lab_abort;
+ //.........................................................................
+lab_exit:
+lab_abort:
+ return;
+
+ }
+}
+
+// ===========================================================================
+// Iter_refresh_callback()
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::Iter_refresh_callback(
+ AsyncCore * _ac)
+{
+ AsyncGetFileInfo * gfi = NULL;
+ AsyncCallerData * acd = NULL;
+ Model * THIS = NULL;
+
+ IterInfo info;
+
+ GtkTreeIter iter = Iter_zero;
+
+ eFileAccess old_access = eAccessUN;
+ eFileAccess new_access = eAccessUN;
+ gboolean expanded = FALSE;
+ gboolean collapsed = FALSE;
+ //.........................................................................
+ Lock(); // _GDK_LOCK_
+
+ gfi = (AsyncGetFileInfo*)_ac;
+ acd = gfi->caller_data();
+ THIS = acd->model();
+
+ //.........................................................................
+ //
+ // Step #1 : try to retrieve the iter & row for parent
+ //
+ if ( ! info.gather(THIS, acd->path(), IterInfo::eExp) )
+ {
+ REFRESH_WNG("Model::irc:Gather failed");
+ goto lab_abort;
+ }
+ REFRESH_INF("Model::irc:Refreshing [%s]", info.row()->utf8_name_display());
+
+ //.........................................................................
+ //
+ // Step #2 : some vars
+ //
+
+ // current file access
+ new_access = gfi->access();
+ // old file access
+ old_access = info.row()->access();
+
+ if ( ( new_access == eAccessUN ) || ( old_access == eAccessUN ) )
+ {
+ REFRESH_ERR("Model::irc:Row has unknown access mode [old:%02i new:%02i]",
+ old_access, new_access);
+ goto lab_abort;
+ }
+
+ // iter state ( old iter state, maybe not the same as the
+ // current file access )
+ expanded = info.expanded();
+ collapsed = ! expanded;
+
+ //.........................................................................
+ //
+ // Step #3 : Branch on different actions
+ //
+ THIS->iter_refresh_action(
+ info.iter(),
+ info.path(),
+ Access_readable(old_access),
+ Access_readable(new_access),
+ collapsed);
+
+lab_abort:
+ delete acd;
+ Unlock();
+ return;
+}
+
+// ===========================================================================
+// Iter_refresh_children_callback()
+// ===========================================================================
+//
+// Here we know that :
+//
+// - Iter has been refreshed by Iter_refresh_callback
+//
+// - The status of the iter was y-y-e
+//
+void
+GnomeCmdConnectionTreeview::Model::Iter_refresh_children_callback(
+ AsyncCore * _ac)
+{
+ AsyncEnumerateChildren * aec = NULL;
+ AsyncCallerData * acd = NULL;
+ Model * THIS = NULL;
+
+ IterInfo info_parent;
+
+
+ IterInfo info_child;
+ GtkTreeIter iter_child = Iter_zero;
+ GtkTreeIter * itemp = NULL;
+
+ File * file = NULL;
+
+ gboolean b = FALSE;
+ gboolean b_persistent = FALSE;
+
+ GList * list = NULL;
+ GList * temp = NULL;
+ GList * iters_to_delete = NULL;
+ GList * iters_persistent = NULL;
+
+ //.........................................................................
+ Lock(); // _GDK_LOCK_
+
+ aec = (AsyncEnumerateChildren*)_ac;
+ acd = aec->caller_data();
+ THIS = acd->model();
+
+ //.........................................................................
+ //
+ // Step #1 : Verify that parent iter is ?-y-e
+ //
+ if ( ! info_parent.gather(THIS, acd->path(), IterInfo::eRead | IterInfo::eExp) )
+ {
+ REFRESH_WNG("Model::ircc():gather failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ if ( ! info_parent.readable() )
+ {
+ REFRESH_WNG("Model::ircc():Parent iter is NOT Readable");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ if ( ! info_parent.expanded() )
+ {
+ REFRESH_WNG("Model::ircc():Parent iter is NOT Expanded");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ REFRESH_TKI("Model::ircc():Parent [%s]", info_parent.row()->utf8_name_display());
+
+ //.........................................................................
+ //
+ // Step #2 : Check errors on async result
+ //
+ // In fact, we should handle all error cases, and eventually continue // _GWR_TODO_
+ // the process on some children...
+ //
+ if ( aec->error() )
+ {
+ REFRESH_WNG("Model::ircc():async_enumerate_children failed [%s]", aec->error_str());
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #3.1 : Reduce async file list by filtering according
+ // to display settings
+ //
+ //REFRESH_INF("Model::ircc(): --- filter ---");
+ //REFRESH_INF("Model::ircc():filter:%03i files", aec->list_card());
+
+ list = g_list_first(aec->list());
+ while ( list )
+ {
+ file = (File*)(list->data);
+
+ if ( ! THIS->iter_files_file_filter(file) )
+ {
+ //REFRESH_INF("Model::ircc():filter:-[%s]", file->name_utf8());
+
+ // remember next
+ temp = list->next;
+
+ // delete current Glist element and file struct
+ aec->list_remove(list);
+
+ // recall next
+ list = temp;
+ }
+ else
+ {
+ //REFRESH_INF("Model::ircc():filter:+[%s]", file->name_utf8());
+
+ // we will need this in 3.2
+ file->compute_ck_utf8_name();
+ list = list->next;
+ }
+ }
+
+ //REFRESH_INF("Model::ircc():filter:%03i files", aec->list_card());
+
+ //.........................................................................
+ //
+ // Step #3.2 : - Persistent iters :
+ // - delete corresponding files from async list ; this way
+ // only new files remain in it.
+ // - memorize them ( for "async recursivity" )
+ //
+ // - Iters tah have to be deleted :
+ // - memorize them
+ //
+ //REFRESH_INF("Model::ircc(): --- compare ---");
+
+ // alloc the memorization lists
+ iters_to_delete = g_list_alloc();
+ iters_persistent = g_list_alloc();
+
+ // + loop on GtkTreeModel iters
+ b = GnomeCmdFoldviewTreestore::iter_children(THIS->treemodel(), &iter_child, info_parent.iter());
+
+ // PLV : empty readable, expanded iter : failure
+ if ( !b )
+ {
+ REFRESH_ERR("Model::ircc():Parent iter is readable, expanded, but empty");
+ goto lab_exit_false;
+ }
+
+ while ( b )
+ {
+ //REFRESH_INF("Model::ircc():node [%08x]", iter_child.user_data);
+
+ // we want to use the row of the child
+ info_child.reset();
+ if ( ! info_child.gather(THIS, &iter_child, IterInfo::eNothing) )
+ {
+ REFRESH_ERR("Model::ircc():Gather (eNothing) failed");
+ goto lab_exit_false;
+ }
+
+ // When messages lag, user can expand before Counter Program goes here. // _GWR_BUG_#01_
+ // And the frst child is "...Working...", that will be deleted.
+ // And parent will be shown as empty.
+ // So we test here
+ if ( info_child.row()->is_dummy() )
+ {
+ REFRESH_WNG("Model::ircc():first child is a dummy child ( _GWR_BUG_#01_ )");
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ REFRESH_TKI("Model::ircc():compare:iter [%s]", info_child.row()->utf8_name_display());
+
+ // + loop on async list
+ b_persistent = FALSE;
+ list = g_list_first(aec->list());
+
+ while ( list && (! b_persistent) )
+ {
+ file = (File*)(list->data);
+
+ // ck match : set persistent
+ if ( ! strcmp(file->ck_utf8_name(), info_child.row()->utf8_collate_key(eCollateKeyRaw)) )
+ {
+ REFRESH_TKI("Model::ircc(): file [%s] Match", file->name_utf8());
+
+ // async list : delete element & file struct
+ temp = list->next;
+ aec->list_remove(list);
+ list = temp;
+
+ // store a copy of iter_child in iters_persistent
+ itemp = g_try_new0(GtkTreeIter, 1);
+ GCMD_ITER_COPY(itemp, &iter_child);
+ iters_persistent = g_list_append(iters_persistent, (gpointer)itemp);
+
+ // mark this iter as persistent
+ b_persistent = TRUE;
+ }
+ else
+ {
+ //REFRESH_TKI("Model::ircc(): file [%s]", file->name_utf8());
+ list = list->next;
+ }
+ }
+ // - loop on async list
+
+ // iter is not persistent -> work is done , just log something
+ if ( b_persistent )
+ {
+ REFRESH_TKI("Model::ircc(): iter [%s] =", info_child.row()->utf8_name_display());
+ }
+ // iter is not persistent -> store it in a list for further deletion
+ else
+ {
+ REFRESH_TKI("Model::ircc(): iter [%s] -", info_child.row()->utf8_name_display());
+
+ // store a copy of the path of iter_child in iters_to_delete
+ iters_to_delete = g_list_append( iters_to_delete, (gpointer)(info_child.path()->dup()) );
+ }
+
+ b = GnomeCmdFoldviewTreestore::iter_next(THIS->treemodel(), &iter_child);
+ }
+ // - loop on GtkTreeModel iters
+
+ //.........................................................................
+ //
+ // Step #4 : Send messages for deleting iters marked to be deleted
+ //
+ list = g_list_first(iters_to_delete)->next; // first is zero
+ while (list)
+ {
+ //THIS->iter_remove( (GtkTreeIter*)(list->data) );
+ //g_free( (GtkTreeIter*)(list->data) );
+
+ THIS->control()->message_fifo_push
+ (
+ GCMD_STRUCT_NEW
+ (
+ Model::MsgDel,
+ (TreestorePath*)(list->data)
+ )
+ );
+ g_free(list->data);
+
+ list = g_list_next(list);
+ }
+ g_list_free(iters_to_delete);
+
+ //.........................................................................
+ //
+ // Step #5 : Send messages for creating new iters from async list
+ //
+ list = g_list_first(aec->list());
+
+ while ( list )
+ {
+ file = (File*)(list->data);
+
+ //row_new_child = new Row(eRowStd, info_parent.row(), file);
+ //THIS->iter_add_child(info_parent.iter(), &iter_child, row_new_child);
+
+ THIS->control()->message_fifo_push
+ (
+ GCMD_STRUCT_NEW
+ (
+ Model::MsgAddChild,
+ info_parent.path(),
+ file
+ )
+ );
+ list = g_list_next(list);
+ }
+
+ //.........................................................................
+ //
+ // Step #6 : Refresh persistent iters
+ // ( here is the "async recursive call" )
+ //
+ list = g_list_first(iters_persistent)->next; // first is zero
+ while (list)
+ {
+ THIS->iter_refresh( (GtkTreeIter*)(list->data) );
+ g_free( (GtkTreeIter*)(list->data) );
+ list = g_list_next(list);
+ }
+ g_list_free(iters_persistent);
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+lab_exit_false:
+ delete acd;
+ Unlock(); // _GDK_LOCK_
+ return;
+}
+
+// ===========================================================================
+// iter_refresh()
+// ===========================================================================
+//
+// Main call for refreshing from an iter
+//
+void
+GnomeCmdConnectionTreeview::Model::iter_refresh(
+ GtkTreeIter * _iter)
+{
+ AsyncCallerData * acd = NULL;
+ GtkTreeIter child = Iter_zero;
+ Row * row = NULL;
+ //.........................................................................
+ //REFRESH_INF("Model::iter_sort():called");
+
+ // iter given : refresh this iter
+ if ( _iter )
+ {
+ // treerow
+ row = iter_get_treerow(_iter);
+ g_return_if_fail( row );
+
+ // create a struct for knowing what to do with GVFS answers
+ acd = GCMD_STRUCT_NEW(AsyncCallerData, this, Iter_refresh_callback, row->path()->dup());
+
+ _USE_GIO_ ? a_GIO.iter_get_file_info(acd, row->uri_utf8()) :
+ a_GnomeVFS.iter_get_file_info(acd, row->uri_utf8()) ;
+
+ return;
+ }
+
+ // iter not given : refresh all root nodes
+ if ( ! treestore()->iter_children(treemodel(), &child, NULL) )
+ return;
+
+ do
+ {
+ // treerow
+ row = iter_get_treerow(&child);
+ g_return_if_fail( row );
+
+ // create a struct for knowing what to do with GVFS answers
+ acd = GCMD_STRUCT_NEW(AsyncCallerData, this, Iter_refresh_callback, row->path()->dup());
+
+ _USE_GIO_ ? a_GIO.iter_get_file_info(acd, row->uri_utf8()) :
+ a_GnomeVFS.iter_get_file_info(acd, row->uri_utf8()) ;
+ }
+ while ( treestore()->iter_next(treemodel(), &child) );
+
+}
+
+
+// ###########################################################################
+//
+// Sorting
+//
+// ###########################################################################
+
+// ===========================================================================
+// iter_sort()
+// ===========================================================================
+//
+// Main call for sorting from an iter
+//
+void
+GnomeCmdConnectionTreeview::Model::iter_sort(
+ GtkTreeIter * _iter)
+{
+ GtkTreeIter child = Iter_zero;
+ Row * row = NULL;
+ //.........................................................................
+ //SORT_INF("Model::iter_sort():called");
+
+ // iter given : sort from this iter
+ if ( _iter )
+ {
+ // treerow
+ row = iter_get_treerow(_iter);
+ g_return_if_fail( row );
+
+ control()->sorting_list_add( GCMD_STRUCT_NEW( MsgSort_Insertion, row->path(), this ) );
+
+ return;
+ }
+
+ // iter not given : sort from all root nodes
+ if ( ! treestore()->iter_children(treemodel(), &child, NULL) )
+ return;
+
+ do
+ {
+ // treerow
+ row = iter_get_treerow(&child);
+ g_return_if_fail( row );
+
+ control()->sorting_list_add( GCMD_STRUCT_NEW( MsgSort_Insertion, row->path(), this ) );
+ }
+ while ( treestore()->iter_next(treemodel(), &child) );
+}
+
+
+// ###########################################################################
+//
+// Check if empty
+//
+// ###########################################################################
+//
+// What we do here :
+//
+// - Find all subdirs
+// - If at least one, add a dummy child so GtkTreeview will show a little
+// arrow allowing expansion.
+// - If no subdir, remove dummy child
+//
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Check if empty : async callback
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void
+GnomeCmdConnectionTreeview::Model::Iter_check_if_empty_callback(
+ AsyncCore * _ac)
+{
+ AsyncEnumerateChildren * aec = NULL;
+ AsyncCallerData * cd = NULL;
+ Model * THIS = NULL;
+
+ IterInfo info;
+ //.........................................................................
+ Lock(); // _GDK_LOCK_
+
+ aec = (AsyncEnumerateChildren*)_ac;
+ cd = aec->caller_data();
+ THIS = cd->model();
+
+ //.........................................................................
+ //
+ // Step #1 : Try to retrieve the iter & row for parent
+ //
+ // If error, that means that the path doesnt guide to an iter, so the iter
+ // has been deleted from model. So just abort.
+ //
+ if ( ! info.gather(THIS, cd->path(), IterInfo::eNothing) )
+ {
+ CHECK_WNG("Model::Iter_check_if_empty_callback():Gather Failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Check async error code
+ //
+ if ( aec->error() )
+ {
+ CHECK_WNG("Model::Iter_expanded_from_ui_callback():Async op failed [%s]", aec->error_str());
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAsyncMismatchICIEC, info.path()) );
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #3 : If something to add, send message
+ //
+ if ( THIS->iter_files_add_at_least_one(aec->list()) )
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAddDummyChild, cd->path()) );
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+lab_exit_false:
+ // delete user data
+ delete cd;
+ Unlock(); // _GDK_LOCK_
+ return;
+ }
+
+// ===========================================================================
+// Check if empty : public call
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::iter_check_if_empty(
+ GtkTreeIter * _iter)
+{
+ AsyncCallerData * acd = NULL;
+ Row * row = NULL;
+ //.........................................................................
+
+ // treerow
+ row = iter_get_treerow(_iter);
+ g_return_if_fail( row );
+
+ // create a struct for knowing what to do with async answers
+ acd = GCMD_STRUCT_NEW(AsyncCallerData, this, Iter_check_if_empty_callback, row->path()->dup());
+
+ _USE_GIO_ ? a_GIO.iter_check_if_empty(acd, row->uri_utf8()) :
+ a_GnomeVFS.iter_check_if_empty(acd, row->uri_utf8()) ;
+}
+
+// ###########################################################################
+//
+// Expand
+//
+// ###########################################################################
+//
+// - Remove the [DUMMY] item if present ( no dummy doesnt imply no subdirs ;
+// things can change between two users clicks... )
+// - Add the subdirs
+//
+
+// ===========================================================================
+// Expand : async callback
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::Iter_expanded_from_ui_callback(
+ AsyncCore * _ac)
+{
+ AsyncEnumerateChildren * aec = NULL;
+ AsyncCallerData * cd = NULL;
+ Model * THIS = NULL;
+
+ IterInfo info;
+
+ GnomeCmdFoldviewTreestore::Path * path_parent = NULL;
+
+ GtkTreeIter iter_parent = GnomeCmdConnectionTreeview::Model::Iter_zero;
+ GtkTreeIter iter_child = GnomeCmdConnectionTreeview::Model::Iter_zero;
+
+ GList * list = NULL;
+ File * file = NULL;
+ //.........................................................................
+ Lock(); // _GDK_LOCK_
+
+ aec = (AsyncEnumerateChildren*)_ac;
+ cd = aec->caller_data();
+ THIS = cd->model();
+ path_parent = cd->path();
+
+ //.........................................................................
+ //
+ // Step #1 : Test iter -> must be dummy-childed ( PLV )
+ //
+ if ( ! info.gather(THIS, path_parent, IterInfo::eFCID) )
+ {
+ EXPAND_WNG("Model::Iter_expanded_from_ui_callback():Gather Failed");
+ Error_Msg_Failure(); goto lab_exit_false;
+ }
+
+ if ( ! info.first_child_is_dummy() )
+ {
+ EXPAND_WNG("Model::Iter_expanded_from_ui_callback():Test failed");
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAsyncMismatchIEFUC, path_parent) );
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Check async error code
+ //
+ if ( aec->error() )
+ {
+ EXPAND_WNG("Model::Iter_expanded_from_ui_callback():Async op failed [%s]", aec->error_str());
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAsyncMismatchIEFUC, path_parent) );
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #3 : add files
+ //
+ list = g_list_first(aec->list());
+ do
+ {
+ file = (File*)list->data;
+
+ //EXPAND_INF("Model::iec():pushing [%s]", file->name_utf8());
+
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAddChild, path_parent, file) );
+ list = g_list_next(list);
+ }
+ while ( list );
+
+ //.........................................................................
+ //
+ // Step #4 : Check if directories added are empty / not empty
+ // -> will be done in message_add_child()
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+lab_exit_false:
+ // delete user data
+ delete cd;
+ Unlock(); // _GDK_LOCK_
+ return;
+}
+
+// ===========================================================================
+// Expand : public call
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::iter_expanded_from_ui(
+ GtkTreeIter * _iter,
+ gboolean _replace_dummy)
+{
+ gint n = 0;
+ AsyncCallerData * acd = NULL;
+ Row * row = NULL;
+ //.........................................................................
+
+ // Ensure that there is only one subitem ( the "...not empty..." one )
+ n = iter_n_children(_iter);
+
+ if ( n != 1 )
+ {
+ EXPAND_ERR("ccie :control_iter_expand:parent has %i children", n);
+ return;
+ }
+
+ // treerow
+ row = iter_get_treerow(_iter);
+ g_return_if_fail( row );
+
+ // create a struct for knowing what to do with async answers
+ acd = GCMD_STRUCT_NEW(AsyncCallerData, this, Iter_expanded_from_ui_callback, row->path()->dup());
+
+ _USE_GIO_ ? a_GIO.iter_enumerate_children(acd, row->uri_utf8()) :
+ a_GnomeVFS.iter_enumerate_children(acd, row->uri_utf8());
+}
+
+// ###########################################################################
+//
+// Enumerate children
+//
+// ###########################################################################
+//
+// Enumerate children on iter
+//
+
+// ===========================================================================
+// iter_enumerate_children()
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::iter_enumerate_children(
+ GtkTreeIter * _iter,
+ AsyncCallerCallback _callback)
+{
+ AsyncCallerData * acd = NULL;
+ Row * row = NULL;
+ //.........................................................................
+
+ // treerow
+ row = iter_get_treerow(_iter);
+ g_return_if_fail( row );
+
+ // create a struct for knowing what to do with async answers
+ acd = GCMD_STRUCT_NEW(AsyncCallerData, this, _callback, row->path()->dup());
+
+ _USE_GIO_ ? a_GIO.iter_enumerate_children(acd, row->uri_utf8()) :
+ a_GnomeVFS.iter_enumerate_children(acd, row->uri_utf8());
+}
+
+// ###########################################################################
+//
+// Collapse
+//
+// ###########################################################################
+//
+// Item collapsed
+//
+// - Remove all subdirs
+// - Add [DUMMY] ( we have been callapsed, so there were subdirs in there )
+// This is useful, because when re-expanding, directory will be re-scanned
+// and thus we'll be more accurate.
+//
+// With monitoring, it is now unuseful. But It save memory. So I keep It.
+//
+
+// ===========================================================================
+// Collapse : public call
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::Model::iter_collapsed_from_ui(
+ GtkTreeIter * _iter)
+{
+ Row * row_parent = NULL;
+
+ gint removed = 0;
+
+ GtkTreeIter child = Iter_zero;
+ //.........................................................................
+ row_parent = iter_get_treerow(_iter);
+ g_return_if_fail( row_parent );
+
+ removed = iter_collapsed_remove_children(_iter);
+ //GCMD_INF("control::iter_collapsed:removed %03i children", removed);
+
+ // we have been collapsed, so we had children ; so re-add dummy child
+ iter_dummy_child_add(_iter, &child);
+}
+
+// ###########################################################################
+//
+// first tree
+//
+// ###########################################################################
+//
+// This method is called only once, at the creation of the
+// GnomeCmdConnectionTreeview object.
+//
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Add_first_tree_callback()
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GnomeCmdConnectionTreeview::Model::Add_first_tree_callback(
+ AsyncCore * _ac)
+{
+ AsyncGetFileInfo * gfi = NULL;
+ AsyncCallerData * cd = NULL;
+ Model * THIS = NULL;
+
+ IterInfo info;
+
+ TreestorePath * path = NULL;
+
+ GtkTreeIter iter = GnomeCmdConnectionTreeview::Model::Iter_zero;
+
+ File * file = NULL;
+ //.........................................................................
+ Lock(); // _GDK_LOCK_
+
+ gfi = (AsyncGetFileInfo*)_ac;
+ cd = gfi->caller_data();
+ THIS = cd->model();
+ path = cd->path();
+ //.........................................................................
+ //
+ // Step #1 : Check async error code
+ //
+ if ( gfi->error() )
+ {
+ GCMD_ERR("Model::Add_first_tree_callback():Async op failed [%s]", gfi->error_str());
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAsyncMismatchAFT, path) );
+ Error_Msg_Abort(); goto lab_exit_false;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : Set good infos on the iter ( build a file )
+ //
+ if ( gfi->is_symlink() )
+ file = new FoldviewLink(gfi->name(), gfi->uri_symlink_target(), gfi->access());
+ // it is a directory
+ else
+ file = new FoldviewDir(gfi->name(), gfi->access());
+
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgAddFirstTree, path, file) );
+
+ delete file;
+
+ //.........................................................................
+ //
+ // Exit
+ //
+lab_exit_true:
+lab_exit_false:
+ // delete user data
+ delete cd;
+ Unlock(); // _GDK_LOCK_
+ return;
+}
+
+// ===========================================================================
+// add_first_tree()
+// ===========================================================================
+//
+// Although we add an iter to the model, we dont lock it ; indeed, the model
+// is empty at this moment :)
+//
+void
+GnomeCmdConnectionTreeview::Model::add_first_tree(
+ const Uri _uri,
+ const gchar * _alias)
+{
+ Row * row = NULL;
+ GtkTreeIter iter_child = Iter_zero;
+ AsyncCallerData * acd = NULL;
+ //.........................................................................
+
+ // create the first iter
+ row = new Row(eRowRoot, _uri, _alias, NULL,
+ eAccessRW, FALSE,
+ control()->is_samba(), control()->is_local(), control()->host_redmond());
+ iter_add_child(NULL, &iter_child, row);
+
+ // create a struct for knowing what to do with async answer
+ acd = GCMD_STRUCT_NEW(AsyncCallerData, this, Add_first_tree_callback, treestore()->ext_path_from_iter(&iter_child));
+
+ _USE_GIO_ ? a_GIO.iter_get_file_info(acd, _uri) :
+ a_GnomeVFS.iter_get_file_info(acd, _uri) ;
+}
+
+// ###########################################################################
+//
+// Monitoring
+//
+// ###########################################################################
+
+// ===========================================================================
+// Monitoring : start monitoring an iter
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_monitor_start(
+ GtkTreeIter * _iter)
+{
+ Row * rw = NULL;
+ //.........................................................................
+ g_return_val_if_fail( _iter, FALSE );
+
+ if ( ! _ALLOW_MONITORING_ )
+ return TRUE;
+
+ // row
+ rw = iter_get_treerow(_iter);
+ g_return_val_if_fail( rw, FALSE );
+
+ // verify that iter is not a dummy
+ if ( rw->is_dummy() )
+ {
+ MONITOR_ERR("GnomeCmdConnectionTreeview::Model::iter_monitor_start():[%s] is dummy", rw->utf8_name_display());
+ }
+
+ // verify that iter is not still monitored
+ if ( rw->monitoring_started() )
+ {
+ MONITOR_ERR("GnomeCmdConnectionTreeview::Model::iter_monitor_start():[%s] already monitored", rw->utf8_name_display());
+ return FALSE;
+ }
+
+ if ( rw->monitoring_start(this, rw) )
+ {
+ MONITOR_INF("GnomeCmdConnectionTreeview::Model::iter_monitor_start():Success [%s]" ,rw->utf8_name_display());
+
+ return TRUE;
+ }
+
+ MONITOR_ERR("GnomeCmdConnectionTreeview::Model::iter_monitor_start():Failure [%s], calling stop", rw->utf8_name_display());
+
+ return iter_monitor_stop(_iter);
+}
+
+// ===========================================================================
+// Monitoring : stop monitoring an iter
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::iter_monitor_stop(
+ GtkTreeIter * _iter)
+{
+ Row * rw = NULL;
+ //.........................................................................
+ g_return_val_if_fail( _iter, FALSE );
+
+ if ( ! _ALLOW_MONITORING_ )
+ return TRUE;
+
+ // row
+ rw = iter_get_treerow(_iter);
+ g_return_val_if_fail( rw, FALSE );
+
+ // verify that iter is monitored
+ if ( ! rw->monitoring_started() )
+ {
+ MONITOR_ERR("GnomeCmdConnectionTreeview::Model::iter_monitor_stop():[%s] not monitored", rw->utf8_name_display());
+ return FALSE;
+ }
+
+ // stop monitoring
+ if ( rw->monitoring_stop() )
+ {
+ MONITOR_INF("GnomeCmdConnectionTreeview::Model::iter_monitor_stop():[%s] stopped", rw->utf8_name_display());
+ return TRUE;
+ }
+
+ // error
+ MONITOR_ERR("GnomeCmdConnectionTreeview::Model::iter_monitor_stop():[%s] monitor was not stopped correctly", rw->utf8_name_display());
+ return FALSE;
+}
+
+// ===========================================================================
+// Iter_monitor_callback_del()
+// ===========================================================================
+//
+// Monitoring callback : self deleted
+//
+// We cant have the type of the file, since it is deleted. So just search
+// with the collate key.
+//
+void
+GnomeCmdConnectionTreeview::Model::Iter_monitor_callback_del(
+ MonitorData * _md)
+{
+ Model * THIS = NULL;
+ GnomeCmdFoldviewTreestore * treestore = NULL;
+ GtkTreeModel * treemodel = NULL;
+ Row * row = NULL;
+
+ GtkTreeIter iter = Iter_zero;
+ //.........................................................................
+ MONITOR_INF("Model::Iter_monitor_callback_del()");
+
+ THIS = _md->a_model;
+ row = _md->a_row;
+
+ treestore = THIS->treestore();
+ treemodel = THIS->treemodel();
+
+ Lock(); // _GDK_LOCK_
+
+ if ( ! treestore->ext_iter_from_path(row->path(), &iter) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_del():could not retrieve iter from Path [%s]", row->uri_utf8());
+ goto exit;
+ }
+
+ // remove the iter
+ THIS->iter_remove(&iter); // _GWR_SEND_MSG_
+
+exit:
+ Unlock(); // _GDK_LOCK_
+}
+
+// ===========================================================================
+// Iter_monitor_callback_child_del()
+// ===========================================================================
+//
+// Monitoring callback : child deleted
+//
+// If a child iter is deleted, we have 2 cases :
+//
+// - The child is displayed ( represented by an iter ) : so it will be
+// self-callbacked for delete, we do nothing.
+//
+// - The child is not displayed ( no iter representing it ) :
+// The parent iter is thus collapsed, and have a dummy ( c.f. program's logic )
+// With must test if the deleted child was the last in the directory represented
+// by the parent iter. In this case, the little expandarrow must disappear from
+// the GtkTreeView. We do that by initiating a new check_if_empty async call.
+
+void
+GnomeCmdConnectionTreeview::Model::Iter_monitor_callback_child_del(
+ MonitorData * _md,
+ const gchar * _name_debug)
+{
+ Model * THIS = NULL;
+ GnomeCmdFoldviewTreestore * treestore = NULL;
+ GtkTreeModel * treemodel = NULL;
+ Row * row = NULL;
+
+ GtkTreeIter iter_parent = Iter_zero;
+ Row * row_parent = NULL;
+ //.........................................................................
+ MONITOR_INF("Model::Iter_monitor_callback_child_del()");
+
+ THIS = _md->a_model;
+ row = _md->a_row;
+
+ treestore = THIS->treestore();
+ treemodel = THIS->treemodel();
+
+ Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1 : Get parent iter & data
+ //
+ if ( ! treestore->ext_iter_from_path(row->path(), &iter_parent) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_del():could not retrieve parent iter from Path [??? / %s]", _name_debug);
+ goto exit;
+ }
+
+ if ( ! treestore->ext_get_data(&iter_parent, (GnomeCmdFoldviewTreestore::DataInterface**)&row_parent) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_del():could not retrieve parent iter's TreeRow [??? / %s]", _name_debug);
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : parent is expanded : abort
+ //
+ if ( THIS->iter_is_expanded(&iter_parent) )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_del():parent is expanded, skipping [%s / %s]", row_parent->utf8_name_display(), _name_debug);
+ goto abort;
+ }
+
+ //.........................................................................
+ //
+ // Step #3 : parent is collapsed : verify that it has only a dummy ( logic verif )
+ //
+ if ( ! THIS->iter_dummy_child_check(&iter_parent) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_del():parent has no dummy [%s / %s]", row_parent->utf8_name_display(), _name_debug);
+ goto abort;
+ }
+
+ //.........................................................................
+ //
+ // Step #4 : launch a check_if_empty async call on our collapsed,
+ // dummychilded parent iter
+ //
+ THIS->iter_check_if_empty(&iter_parent);
+
+abort:
+exit:
+ Unlock(); // _GDK_LOCK_
+}
+
+// ===========================================================================
+// Iter_monitor_callback_child_new()
+// ===========================================================================
+//
+// Monitoring callback : child created
+//
+void
+GnomeCmdConnectionTreeview::Model::Iter_monitor_callback_child_new(
+ MonitorData * _md,
+ File * _file)
+{
+ Model * THIS = NULL;
+ GnomeCmdFoldviewTreestore * treestore = NULL;
+ Row * row = NULL;
+
+ Row * row_parent = NULL;
+ GtkTreeIter iter_parent = Iter_zero;
+ GtkTreePath * gtk_path_parent = NULL;
+ gboolean b_parent_exp = FALSE;
+ gboolean b_parent_emp = FALSE;
+
+ Row * row_child = NULL;
+ GtkTreeIter iter_child = Iter_zero;
+ //.........................................................................
+ MONITOR_INF("Model::Iter_monitor_callback_child_new()");
+
+ THIS = _md->a_model;
+ row = _md->a_row;
+ treestore = THIS->treestore();
+
+ Lock(); // _GDK_LOCK_
+
+ if ( ! treestore->ext_iter_from_path(row->path(), &iter_parent) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_new():could not retrieve parent iter [ %s / %s]", row->uri_utf8(), _file->name_utf8());
+ goto exit;
+ }
+
+ if ( ! THIS->iter_get_treerow(&iter_parent, &row_parent) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_new():parent treerow is NULL [ %s / %s]", row->uri_utf8(), _file->name_utf8());
+ goto exit;
+ }
+
+ // parent status
+ gtk_path_parent = treestore->get_path(THIS->treemodel(), &iter_parent);
+ b_parent_exp = (THIS->control()->row_state(gtk_path_parent) == eRowStateExpanded);
+ gtk_tree_path_free(gtk_path_parent);
+ b_parent_emp = ( THIS->iter_n_children(&iter_parent) == 0 );
+
+ // parent expanded : add new child
+ if ( b_parent_exp )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_new():parent EXP_xxx : adding new child [ %s / %s]", row_parent->utf8_name_display(), _file->name_utf8());
+
+ row_child = new Row(eRowStd, row_parent, _file);
+
+ if ( ! THIS->iter_add_child(&iter_parent, &iter_child, row_child) )
+ MONITOR_ERR("Model::Iter_monitor_callback_child_new():could not add child iter [ %s / %s]", row_parent->utf8_name_display(), _file->name_utf8());
+
+ goto exit;
+ }
+
+ // parent not expanded, and empty : add dummy child
+ if ( b_parent_emp )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_new():parent NEXP_EMPTY : adding dummy child [ %s / %s]", row_parent->utf8_name_display(), _file->name_utf8());
+
+ if ( ! THIS->iter_dummy_child_add(&iter_parent, &iter_child) )
+ MONITOR_ERR("Model::Iter_monitor_callback_child_new():could not add dummy child iter [ %s / %s]", row_parent->utf8_name_display(), _file->name_utf8());
+
+ goto exit;
+ }
+
+ // parent not expanded, and not empty : skip
+ MONITOR_INF("Model::Iter_monitor_callback_child_new():parent NEX_NEMPTY : skipping [ %s / %s]", row_parent->utf8_name_display(), _file->name_utf8());
+
+exit:
+ Unlock(); // _GDK_LOCK_
+ return;
+}
+
+// ===========================================================================
+// Iter_monitor_callback_child_acc()
+// ===========================================================================
+//
+// Monitoring callback : child directory access changed
+//
+void
+GnomeCmdConnectionTreeview::Model::Iter_monitor_callback_child_acc(
+ MonitorData * _md,
+ eFileAccess _access,
+ const gchar * _child_name)
+{
+ Model * THIS = NULL;
+ GnomeCmdFoldviewTreestore * treestore = NULL;
+ GtkTreeModel * treemodel = NULL;
+
+ Row * row_parent = NULL;
+ Row * row_child = NULL;
+
+ GtkTreeIter iter_parent = Iter_zero;
+ GtkTreeIter iter_child = Iter_zero;
+
+ const gchar * ck_child = NULL;
+
+ gboolean was_readable = FALSE;
+ gboolean is_readable = FALSE;
+ //.........................................................................
+ MONITOR_INF("Model::Iter_monitor_callback_child_acc()");
+
+ THIS = _md->a_model;
+ row_parent = _md->a_row;
+
+ treestore = THIS->treestore();
+ treemodel = THIS->treemodel();
+
+ Lock(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1.1 : Get the parent iter
+ //
+ if ( ! treestore->ext_iter_from_path(row_parent->path(), &iter_parent) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_acc():could not retrieve parent iter [%s]", row_parent->utf8_name_display());
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #1.2 : Verifications on parent
+ //
+ if ( ! THIS->iter_is_expanded(&iter_parent) )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_acc():parent is not expanded, skipping [%s]", row_parent->utf8_name_display());
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #2.1 : Get the child iter + data
+ //
+
+ // get the child
+ ck_child = g_utf8_collate_key_for_filename(_child_name, -1);
+
+ if ( ! treestore->ext_match_child_str(&iter_parent, &iter_child, ck_child ) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_acc():could not retrieve child iter [%s] of parent iter [%s]", _child_name, row_parent->utf8_name_display());
+ g_free((void*)ck_child);
+ goto exit;
+ }
+
+ g_free((void*)ck_child);
+
+ // get the child's data
+ if ( ! treestore->ext_get_data(&iter_child, (GnomeCmdFoldviewTreestore::DataInterface**)&row_child) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_acc():could not retrieve child iter's TreeRow [%s]", _child_name);
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #2.2 : verification that child file access has changed
+ //
+ if ( row_child->access() == _access )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_acc():child access didnt change [%s]", row_child->utf8_name_display());
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #3 : Action !
+
+ // convenience booleans
+ was_readable = row_child->readable();
+ is_readable = Access_readable(_access);
+
+ // #4.1 readable -> NOT readable
+ if ( was_readable && ( !is_readable ) )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_acc():readable -> NOT readable [%s]", row_child->utf8_name_display());
+ //THIS->iter_readable_unset(&iter_child);
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgSetNotReadable, row_child->path()) );
+ }
+
+ // #4.2 NOT readable -> readable
+ if ( ( !was_readable ) && is_readable )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_acc():NOT readable -> readable [%s]", row_child->utf8_name_display());
+ //THIS->iter_readable_set(&iter_child);
+ THIS->control()->message_fifo_push( GCMD_STRUCT_NEW(MsgSetReadable, row_child->path()) );
+ }
+
+ // #4.3 other changes, dont mind & exit
+
+exit:
+ Unlock(); // _GDK_LOCK_
+}
+
+// ###########################################################################
+//
+// Lock
+//
+// ###########################################################################
+
+GStaticMutex Mutex = G_STATIC_MUTEX_INIT;
+
+// ===========================================================================
+// Lock()
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::Lock()
+{
+ //pid_t tid = syscall(SYS_gettid);
+ //GCMD_INF("Model:: +++ Lock() +++");
+ gdk_threads_enter();
+ //g_static_mutex_lock(&Mutex);
+ return TRUE;
+}
+
+
+// ===========================================================================
+// Unlock()
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::Model::Unlock()
+{
+ //pid_t tid = syscall(SYS_gettid);
+ //GCMD_INF("Model:: --- Unlock() ---");
+ //g_static_mutex_unlock(&Mutex);
+ gdk_threads_leave();
+ return TRUE;
+}
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-model.snippet.h b/src/foldview/gnome-cmd-connection-treeview-model.snippet.h
new file mode 100644
index 0000000..e869823
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-model.snippet.h
@@ -0,0 +1,402 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-model.snippet.h
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : Model
+
+ Parent : GnomeCmdConnectionTreeView
+
+ This file is directly inluded in gnome-cmd-connection-treeview.h
+
+ ###########################################################################
+*/
+
+// ***************************************************************************
+// #define
+// ***************************************************************************
+// ===========================================================================
+//
+// ===========================================================================
+
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview::Model
+//
+// ###########################################################################
+struct Model
+{
+ // ***********************************************************************
+ // * *
+ // * Enums, ... *
+ // * *
+ // ***********************************************************************
+ private: enum eCollateKeys
+ {
+ eCollateKeyRaw = 0x00,
+ eCollateKeyCaseInsensitive = 0x01,
+
+ eCollateKeyCard = 0x02
+ };
+
+ public: enum eRowType
+ {
+ eRowStd = 0x00 ,
+ eRowRoot = 0x01 ,
+ eRowDummy = 0x02
+ };
+
+ public: enum eRowStatus
+ {
+ eStatusOK = 0x00 ,
+ eStatusPB1 = 0x01 ,
+ eStatusPB2 = 0x02
+ };
+ // ***********************************************************************
+ // * *
+ // * Structs *
+ // * *
+ // ***********************************************************************
+
+ // =======================================================================
+ // All structs declarations, in the good order, for crossed references
+ // in this header ( see UML clas diagram for infos )
+ // =======================================================================
+ private:
+ // Template class to add GnomeVFS common fields to a struct
+ template<typename T> struct GnomeVFSAsyncTpl;
+
+ private:
+ struct SortModule;
+ struct SortModuleInsertion;
+
+ public:
+ struct IterInfo;
+
+ public:
+ struct File;
+ struct Directory;
+ struct Symlink;
+
+ private:
+ struct Refresh;
+ struct RefreshList;
+
+ private:
+ struct AsyncCallerData;
+ struct AsyncCore;
+ struct AsyncGetFileInfo;
+ struct GioAsyncGetFileInfo;
+ typedef GnomeVFSAsyncTpl<AsyncGetFileInfo> GnomeVFSAsyncGetFileInfo;
+ struct AsyncEnumerateChildren;
+ struct GioAsyncEnumerateChildren;
+ typedef GnomeVFSAsyncTpl<AsyncEnumerateChildren> GnomeVFSAsyncEnumerateChildren;
+
+ typedef void (*AsyncCallerCallback)(AsyncCore*);
+
+ private:
+ struct TreeRowInterface;
+ struct TreeRowStd;
+ struct TreeRowRoot;
+ struct TreeRowDummy;
+
+ private:
+ struct MonitorData;
+ struct MonitorInterface;
+ struct Monitor;
+ struct GioMonitor;
+ struct GnomeVFSMonitor;
+ struct GioMonitorHelper;
+
+ public: // cos of View::Treeview
+ struct Row;
+
+ private:
+ struct GnomeVFS;
+ struct GIO;
+
+ private:
+ typedef GnomeCmdFoldviewTreestore::Path TreestorePath;
+ typedef GnomeCmdFoldviewTreestore::DataInterface TreestoreData;
+
+ typedef File FoldviewFile;
+ typedef Directory FoldviewDir;
+ typedef Symlink FoldviewLink;
+
+ // =======================================================================
+ // All structs definitions are in this file
+ // |
+ // v
+ // =======================================================================
+ #include "gnome-cmd-connection-treeview-model-struct.snippet.h"
+
+ // ***********************************************************************
+ // * *
+ // * Members *
+ // * *
+ // ***********************************************************************
+ // =======================================================================
+ // static
+ // =======================================================================
+ public:
+ static GtkTreeIter Iter_zero;
+ static const gchar* Msg_names[];
+ static const gchar* Msg_name(eMsgType);
+
+ // =======================================================================
+ // divers
+ // =======================================================================
+ private:
+ gchar * collate_key_new_from_utf8(const gchar* utf8_str);
+
+ // =======================================================================
+ // core members
+ // =======================================================================
+ private:
+ Control * a_control;
+
+ GnomeCmdFoldviewTreestore * d_treestore;
+ struct GIO a_GIO;
+ struct GnomeVFS a_GnomeVFS;
+ // =======================================================================
+ // divers
+ // =======================================================================
+ // ***********************************************************************
+ // * *
+ // * Methods *
+ // * *
+ // ***********************************************************************
+ // =======================================================================
+ // new, ...
+ // =======================================================================
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ void raz_pointers();
+ void init_instance(Control*);
+
+ public:
+ Model(GnomeCmdConnectionTreeview::Control*);
+ ~Model();
+
+ void dispose();
+ void finalize();
+ // =======================================================================
+ // accessors
+ // =======================================================================
+ public:
+ inline Control * control() { return a_control; }
+ inline GnomeCmdFoldviewTreestore * treestore() { return d_treestore; }
+ inline GtkTreeModel * treemodel() { return GTK_TREE_MODEL(d_treestore); }
+ inline GtkTreeSortable * treesortable() { return GTK_TREE_SORTABLE(d_treestore);}
+
+ // =======================================================================
+ // NO LOCK : GtkTreeModelIface impl
+ // =======================================================================
+ public:
+ gboolean get_iter (GtkTreePath *path /*in*/, GtkTreeIter *iter /*out*/);
+ void get_value (GtkTreeIter *in, gint column, GValue *value);
+ gint iter_n_children (GtkTreeIter *parent);
+ // =======================================================================
+ // NO LOCK : GtkTreeModelIface extensions
+ // =======================================================================
+ public:
+ Row * iter_get_treerow (GtkTreeIter*);
+ gboolean iter_get_treerow (GtkTreeIter*, Row**);
+ gboolean iter_set_treerow (GtkTreeIter*, Row*);
+
+ gboolean iter_is_expanded (GtkTreeIter*);
+ gboolean iter_is_collapsed (GtkTreeIter*);
+ gboolean iter_collapse (GtkTreeIter*);
+
+ const gchar * iter_get_display_string (GtkTreeIter*);
+ const Uri iter_get_uri (GtkTreeIter *iter);
+ gboolean iter_get_root (GtkTreeIter* in_any, GtkTreeIter *out_root);
+ gchar * iter_get_path_str_new (GtkTreeIter* in);
+ gboolean iter_has_uid (GtkTreeIter* in, gint uid);
+ gboolean iter_same (GtkTreeIter*, GtkTreeIter*);
+ gboolean iter_is_root (GtkTreeIter*);
+ gint iter_depth (GtkTreeIter*);
+
+ gboolean iter_add_tree (GtkTreeIter *iter_in ,GtkTreeIter *iter_tree_out);
+ gboolean iter_add_tree ( Uri _utf8_uri, const gchar* _utf8_display_name, Uri _utf8_symlink_target_uri,
+ eFileAccess _access, gboolean _is_symlink,
+ gboolean _is_samba, gboolean _is_local, gboolean _host_redmond,
+ GtkTreeIter* _iter_tree_out);
+
+ gboolean iter_add_child (GtkTreeIter *parent /*in*/, GtkTreeIter *child /*out*/, Row*);
+
+ // The dummy child of an iter :
+ // - indicates that there are subdirectories under the iter
+ // - let GtkTreeView show a little arrow on collapsed iters,
+ // allowing expanding by user-click
+ // - preserve from keeping in memory iters that are not
+ // displayed. ( Ex : /usr/lib )
+ gboolean iter_dummy_child_add (GtkTreeIter *parent /*in*/, GtkTreeIter *child /*out*/);
+ gboolean iter_dummy_child_remove (GtkTreeIter *parent);
+ void iter_dummy_child_replace(GtkTreeIter *_iter_parent /*in*/, GtkTreeIter *_iter_child /*out*/, Row* _rw_child_new);
+ gboolean iter_dummy_child_check (GtkTreeIter *_iter_parent);
+
+ gboolean iter_remove(GtkTreeIter*);
+ gint iter_collapsed_remove_children(GtkTreeIter *parent);
+ void iter_remove_all();
+ // =======================================================================
+ // NO LOCK : Model methods using files
+ // =======================================================================
+ public:
+ //gboolean iter_files_file_already_present (GtkTreeIter *iter, File *file);
+ gboolean iter_files_file_filter (File * _file);
+ gboolean iter_files_add_at_least_one (GList*);
+
+ gboolean iter_files_add_file(
+ GtkTreeIter * iter_parent, /// in
+ GtkTreeIter * iter_child, /// out
+ File * file,
+ gboolean check_for_doubloon,
+ gboolean replace_first_child);
+ gboolean iter_files_replace(
+ GtkTreeIter * iter, /// in
+ File * file);
+ // =======================================================================
+ // Refresh
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : Refresh main call
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void iter_refresh (GtkTreeIter*);
+ // void iter_refresh_children (GtkTreeIter*);
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // LOCKER : Refresh callbacks
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ // GList * iter_refresh_store_R (GList*, GtkTreeIter *iter);
+ void iter_refresh_action (GtkTreeIter*, TreestorePath*, gboolean, gboolean, gboolean);
+ static void Iter_refresh_callback (AsyncCore*);
+ static void Iter_refresh_children_callback (AsyncCore*);
+ //static gboolean Iter_refresh_launch_async_ops (gpointer);
+ // =======================================================================
+ // Sort
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : Sort main call
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void iter_sort (GtkTreeIter*);
+ // =======================================================================
+ // Check if empty
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : check if empty main call
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void iter_check_if_empty (GtkTreeIter*);
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // LOCKER : check if empty callback
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ static void Iter_check_if_empty_callback (AsyncCore*);
+ // =======================================================================
+ // Expanded from ui
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : expanded from ui main call
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void iter_expanded_from_ui (GtkTreeIter *iter, gboolean _replace_dummy);
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // LOCKER : expanded from ui callback
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ static void Iter_expanded_from_ui_callback (AsyncCore*);
+ // =======================================================================
+ // Enumerate children
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : enumerate children main call
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ void iter_enumerate_children(GtkTreeIter* , AsyncCallerCallback);
+ // =======================================================================
+ // Collapsed from ui
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : collapsed from ui main call
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void iter_collapsed_from_ui(GtkTreeIter *iter);
+ // =======================================================================
+ // iter_new_tree
+ // =======================================================================
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // NO LOCK : iter_new_tree
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void add_first_tree(const Uri, const gchar*);
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // LOCKER : iter_new_tree
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ static void Add_first_tree_callback(AsyncCore*);
+ // =======================================================================
+ // Monitoring
+ // =======================================================================
+ public:
+ gboolean iter_monitor_start (GtkTreeIter* _iter);
+ gboolean iter_monitor_stop (GtkTreeIter* _iter);
+
+ private:
+ static void Iter_monitor_callback_del (MonitorData*);
+ static void Iter_monitor_callback_child_del(MonitorData*, const gchar* _name_debug);
+ static void Iter_monitor_callback_child_new(MonitorData*, File*);
+ //static void Iter_monitor_callback_acc (MonitorData*, eFileAccess, const gchar *_name_debug);
+ static void Iter_monitor_callback_child_acc(MonitorData*, eFileAccess, const gchar *_name_debug);
+ // =======================================================================
+ // Lock
+ // =======================================================================
+ public:
+ static gboolean Lock();
+ static gboolean Unlock();
+
+
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-view.cc b/src/foldview/gnome-cmd-connection-treeview-view.cc
new file mode 100644
index 0000000..8669e18
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-view.cc
@@ -0,0 +1,800 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-view.cc
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : View
+
+ Parent : GnomeCmdConnectionTreeview
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview::View::HeadBand
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::View::HeadBand::HeadBand(
+ GnomeCmdConnectionTreeview::View * _view)
+{
+ raz_pointers();
+ init_instance(_view);
+}
+GnomeCmdConnectionTreeview::View::HeadBand::~HeadBand()
+{
+}
+
+void
+GnomeCmdConnectionTreeview::View::HeadBand::raz_pointers()
+{
+ a_view = NULL;
+
+ d_hbox_main = NULL;
+ d_button_connection_image = NULL;
+ d_entry_path = NULL;
+ d_alignement_padder = NULL;
+ d_button_refresh = NULL;
+ d_button_sort = NULL;
+ d_button_show_hide = NULL;
+ d_button_close = NULL;
+}
+
+void
+GnomeCmdConnectionTreeview::View::HeadBand::init_instance(
+ View * _view)
+{
+ g_return_if_fail( _view );
+
+ a_view = _view;
+
+ d_hbox_main = gtk_hbox_new(FALSE, 0);
+ d_button_connection_image = gtk_button_new();
+ d_entry_path = gtk_entry_new();
+ d_alignement_padder = gtk_alignment_new(1.0f, 1.0f, 1.0f, 1.0f);
+ d_button_refresh = gtk_button_new();
+ d_button_sort = gtk_button_new();
+ d_button_show_hide = gtk_button_new();
+ d_button_close = gtk_button_new();
+
+ //.........................................................................
+ //
+ // Path entry setup
+ //
+ gtk_entry_set_has_frame(GTK_ENTRY(d_entry_path), TRUE);
+ gtk_entry_set_alignment(GTK_ENTRY(d_entry_path), 0.0f);
+ gtk_entry_set_editable(GTK_ENTRY(d_entry_path), FALSE);
+ gtk_entry_set_text(GTK_ENTRY(d_entry_path), view()->control()->connection()->alias);
+ //.........................................................................
+ //
+ // Buttons setup
+ //
+ gtk_button_set_image(GTK_BUTTON(d_button_connection_image), gtk_image_new_from_pixbuf(gnome_cmd_con_get_open_pixmap(view()->control()->connection())->pixbuf));
+ gtk_button_set_image(GTK_BUTTON(d_button_refresh), gtk_image_new_from_pixbuf(GnomeCmdConnectionTreeview::s_gdk_pixbuf[eIconGtkRefresh]));
+ gtk_button_set_image(GTK_BUTTON(d_button_sort), gtk_image_new_from_pixbuf(GnomeCmdConnectionTreeview::s_gdk_pixbuf[eIconGtkSortDescending]));
+ gtk_button_set_image(GTK_BUTTON(d_button_show_hide), gtk_image_new_from_pixbuf(GnomeCmdConnectionTreeview::s_gdk_pixbuf[eIconFolderOpened]));
+ gtk_button_set_image(GTK_BUTTON(d_button_close), gtk_image_new_from_pixbuf(GnomeCmdConnectionTreeview::s_gdk_pixbuf[eIconGtkClose]));
+
+ g_signal_connect(d_button_refresh, "clicked", G_CALLBACK(Control::Signal_button_refresh_clicked), (gpointer)this);
+ g_signal_connect(d_button_sort, "clicked", G_CALLBACK(Control::Signal_button_sort_clicked), (gpointer)this);
+ g_signal_connect(d_button_show_hide,"clicked", G_CALLBACK(Control::Signal_button_show_hide_clicked),(gpointer)this);
+ g_signal_connect(d_button_close, "clicked", G_CALLBACK(Control::Signal_button_close_clicked), (gpointer)this);
+
+ //.........................................................................
+ //
+ // Packing
+ //
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_connection_image, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_entry_path, TRUE , TRUE , 0);
+ //gtk_box_pack_start(GTK_BOX(d_hbox_main), d_alignement_padder, TRUE , TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_refresh, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_sort, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_show_hide, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_close, FALSE, FALSE, 0);
+}
+
+void
+GnomeCmdConnectionTreeview::View::HeadBand::show()
+{
+ gtk_widget_show_all(d_hbox_main);
+}
+void
+GnomeCmdConnectionTreeview::View::HeadBand::hide()
+{
+ gtk_widget_hide_all(d_hbox_main);
+}
+
+void
+GnomeCmdConnectionTreeview::View::HeadBand::set_image_closed()
+{
+ gtk_button_set_image(GTK_BUTTON(d_button_show_hide), gtk_image_new_from_pixbuf(GnomeCmdConnectionTreeview::s_gdk_pixbuf[eIconFolderClosed]));
+}
+
+void
+GnomeCmdConnectionTreeview::View::HeadBand::set_image_opened()
+{
+ gtk_button_set_image(GTK_BUTTON(d_button_show_hide), gtk_image_new_from_pixbuf(GnomeCmdConnectionTreeview::s_gdk_pixbuf[eIconFolderOpened]));
+}
+
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview::View::Treeview
+//
+// ###########################################################################
+GnomeCmdConnectionTreeview::View::Treeview::Treeview(
+ View * _view,
+ GtkTreeModel * _treemodel)
+{
+ raz_pointers();
+ init_instance(_view, _treemodel);
+}
+GnomeCmdConnectionTreeview::View::Treeview::~Treeview()
+{
+}
+
+void
+GnomeCmdConnectionTreeview::View::Treeview::raz_pointers()
+{
+ a_view = NULL;
+
+ d_scrolled_window = NULL;
+ d_treeview = NULL;
+}
+
+void
+GnomeCmdConnectionTreeview::View::Treeview::init_instance(
+ View * _view,
+ GtkTreeModel * _treemodel)
+{
+ GtkTreeViewColumn *col0 = NULL;
+ GtkTreeViewColumn *col1 = NULL;
+ GtkCellRenderer *renderer = NULL;
+ //.........................................................................
+ g_return_if_fail( _view );
+ g_return_if_fail( _treemodel );
+ a_view = _view;
+
+ a_treemodel = _treemodel;
+
+ d_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+ d_treeview = gtk_tree_view_new();
+
+ //.........................................................................
+ //
+ // Scrolled window setup
+ //
+ gtk_scrolled_window_set_policy
+ ( GTK_SCROLLED_WINDOW (d_scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC );
+
+ //.........................................................................
+ //
+ // GtkTreeView setup
+ //
+ if ( TRUE )
+ {
+ //
+ // treeview
+ //
+
+ // Drag & Drop
+
+ // void gtk_tree_view_enable_model_drag_source(
+ // GtkTreeView *tree_view,
+ // GdkModifierType start_button_mask,
+ // const GtkTargetEntry *targets,
+ // gint n_targets,
+ // GdkDragAction actions);
+ //
+ // typedef struct
+ // {
+ // gchar *target;
+ // guint flags;
+ // guint info;
+ // }
+ // GtkTargetEntry;
+ //
+ // typedef enum
+ // {
+ // GTK_TARGET_SAME_APP = 1 << 0, //< nick=same-app >
+ // GTK_TARGET_SAME_WIDGET = 1 << 1 //< nick=same-widget >
+ // }
+ // GtkTargetFlags;
+
+ //GtkTargetEntry drag_source_entry[2] =
+ // {
+ // { (gchar*)"text/plain", 0, 0X30 },
+ // { (gchar*)"text/plain", 0, 0X31 }
+ // };
+
+ //gtk_tree_view_enable_model_drag_source(
+ // treeview(),
+ // GDK_BUTTON1_MASK,
+ // drag_source_entry,
+ // 2,
+ // GDK_ACTION_PRIVATE );
+
+ //g_signal_connect(m_treeview, "drag-begin", G_CALLBACK (signal_drag_begin), (gpointer)this);
+
+ // create columns
+ col0 = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(col0, _("Folders"));
+ gtk_tree_view_column_set_visible(col0,TRUE);
+
+ col1 = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(col1, _("Access Rights"));
+ gtk_tree_view_column_set_visible(col1,FALSE);
+
+ // column 0 : create pixbuf renderer
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(col0, renderer, FALSE);
+ g_object_set(renderer, "xalign", 0.0, NULL);
+ gtk_tree_view_column_set_cell_data_func(col0, renderer, CellRendererPixbuf, (gpointer)this, NULL);
+
+ // column 0 : create text renderer
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(col0, renderer, FALSE);
+ g_object_set(renderer, "xalign", 0.0, NULL);
+ gtk_tree_view_column_set_cell_data_func(col0, renderer, CellRendererTxt, (gpointer)this, NULL);
+
+ gtk_tree_view_append_column(GTK_TREE_VIEW(d_treeview), col0);
+
+ // connect signals
+ g_signal_connect(d_treeview, "test_expand_row", G_CALLBACK(signal_test_expand_row), (gpointer)this);
+ g_signal_connect(d_treeview, "row_expanded", G_CALLBACK(signal_row_expanded), (gpointer)this);
+ g_signal_connect(d_treeview, "row_collapsed", G_CALLBACK(signal_row_collapsed), (gpointer)this);
+
+ g_signal_connect(d_treeview, "button-press-event", G_CALLBACK(signal_button_press_event), (gpointer)this);
+
+ g_signal_connect(d_treeview, "cursor-changed", G_CALLBACK(signal_cursor_changed), (gpointer)this);
+
+ // some settings
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(d_treeview), FALSE);
+ gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(d_treeview), TRUE);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(d_treeview), treemodel());
+
+ // contextual menu
+ // since we do a dynamic menu, and there is no menu_shell_remove()
+ // function in gtk, we must create it on the fly, during the
+ // callback for single-right-click
+ }
+ //.........................................................................
+ //
+ // Packing
+ //
+ gtk_container_add(GTK_CONTAINER(d_scrolled_window), d_treeview);
+}
+
+void
+GnomeCmdConnectionTreeview::View::Treeview::show()
+{
+ gtk_widget_show_all(d_scrolled_window);
+}
+void
+GnomeCmdConnectionTreeview::View::Treeview::hide()
+{
+ gtk_widget_hide_all(d_scrolled_window);
+}
+void
+GnomeCmdConnectionTreeview::View::Treeview::update_style()
+{
+}
+
+// ***************************************************************************
+// cells renderers
+// ***************************************************************************
+void
+GnomeCmdConnectionTreeview::View::Treeview::CellRendererPixbuf(
+ GtkTreeViewColumn * _col,
+ GtkCellRenderer * _renderer,
+ GtkTreeModel * _model,
+ GtkTreeIter * _iter,
+ gpointer _udata)
+{
+ gint icon;
+ Treeview * tv = NULL;
+ Model::Row * row = NULL;
+ GValue v = {0};
+ //.........................................................................
+ tv = (GnomeCmdConnectionTreeview::View::Treeview*)_udata;
+
+ GnomeCmdFoldviewTreestore::get_value(_model, _iter, 0, &v);
+ row = (Model::Row*)g_value_get_pointer(&v);
+
+ icon = row->icon();
+ g_object_set(_renderer, "pixbuf", GnomeCmdConnectionTreeview::s_gdk_pixbuf[(eIcon)icon], NULL);
+}
+
+void
+GnomeCmdConnectionTreeview::View::Treeview::CellRendererTxt(
+ GtkTreeViewColumn * _col,
+ GtkCellRenderer * _renderer,
+ GtkTreeModel * _model,
+ GtkTreeIter * _iter,
+ gpointer _udata)
+{
+ Model::Row * row = NULL;
+ GValue v = {0};
+ //.........................................................................
+ GnomeCmdFoldviewTreestore::get_value(_model, _iter, 0, &v);
+ row = (Model::Row*)g_value_get_pointer(&v);
+
+ g_object_set(_renderer, "text", row->utf8_name_display() , NULL);
+}
+
+// ***************************************************************************
+// row state / actions
+// ***************************************************************************
+GnomeCmdConnectionTreeview::eRowState
+GnomeCmdConnectionTreeview::View::Treeview::row_state(
+ GtkTreePath * _path)
+{
+ return ( gtk_tree_view_row_expanded(treeview(), _path) ?
+ eRowStateExpanded :
+ eRowStateCollapsed );
+}
+gboolean
+GnomeCmdConnectionTreeview::View::Treeview::row_collapse(
+ GtkTreePath * _path)
+{
+ return gtk_tree_view_collapse_row(treeview(), _path);
+}
+
+// ***************************************************************************
+// gtk+ callbacks
+// ***************************************************************************
+// ===========================================================================
+// row selection
+// ===========================================================================
+void
+GnomeCmdConnectionTreeview::View::Treeview::signal_cursor_changed(
+ GtkTreeView *tree_view,
+ gpointer user_data)
+{
+ GtkTreeSelection *tree_sel = NULL;
+ gint tree_sel_card = 0;
+
+ GtkTreeIter iter_selected = Model::Iter_zero;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //GCMD_INF("signal_cursor_changed");
+
+ // get path to currently selected iter
+ tree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+ if ( ! tree_sel )
+ {
+ GCMD_ERR("View::signal_cursor_changed:gtk_tree_view_get_selection failed");
+ }
+
+ // Note: gtk_tree_selection_count_selected_rows() does not
+ // exist in gtk+-2.0, only in gtk+ >= v2.2 !
+ tree_sel_card = gtk_tree_selection_count_selected_rows(tree_sel);
+
+ if ( tree_sel_card == 1 )
+ {
+ if ( gtk_tree_selection_get_selected( tree_sel, NULL, &iter_selected) )
+ {
+
+ }
+ else
+ {
+ GCMD_WNG("View::signal_cursor_changed:gtk_tree_selection_get_selected failed");
+ }
+ }
+ else
+ {
+ GCMD_ERR("View::signal_cursor_changed");
+ }
+}
+
+// ===========================================================================
+// row expand / collapse
+// ===========================================================================
+// row about to be expanded : FALSE = allow , TRUE = deny
+gboolean
+GnomeCmdConnectionTreeview::View::Treeview::signal_test_expand_row(
+ GtkTreeView * _tree_view,
+ GtkTreeIter * _iter,
+ GtkTreePath * _path,
+ gpointer _udata)
+{
+ Treeview * tv = NULL;
+ //.........................................................................
+ //GCMD_INF("view:signal [test_expand_row]");
+
+ tv = (Treeview*)_udata;
+
+ tv->view()->control()->iter_expanded_from_ui(_iter, TRUE);
+
+ // Allow expansion
+ return FALSE;
+}
+
+void
+GnomeCmdConnectionTreeview::View::Treeview::signal_row_expanded(
+ GtkTreeView * _tree_view,
+ GtkTreeIter * _iter,
+ GtkTreePath * _path,
+ gpointer _udata)
+{
+ //GCMD_INF("view:signal [row_expanded]");
+}
+
+void
+GnomeCmdConnectionTreeview::View::Treeview::signal_row_collapsed(
+ GtkTreeView * _tree_view,
+ GtkTreeIter * _iter,
+ GtkTreePath * _path,
+ gpointer _udata)
+{
+ Treeview * tv = NULL;
+ //.........................................................................
+ //GCMD_INF("view:signal [row_collapsed]");
+
+ tv = (Treeview*)_udata;
+
+ tv->view()->control()->iter_collapsed_from_ui(_iter);
+}
+
+// ===========================================================================
+// Drag n Drop
+// ===========================================================================
+//GnomeCmdConnectionTreeview::View::Treeview::signal_drag_begin(
+// GtkWidget *widget,
+// GdkDragContext *drag_context,
+// gpointer user_data)
+//{
+// GCMD_INF("View:signal_drag_begin");
+//}
+
+// ===========================================================================
+// Buttons clicks
+// ===========================================================================
+gboolean
+GnomeCmdConnectionTreeview::View::Treeview::signal_button_press_event(
+ GtkWidget *tree_view,
+ GdkEventButton *event,
+ gpointer _udata)
+{
+ // signal handled : return TRUE
+ // signal not handled : return FALSE
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ Treeview * THIS = NULL;
+ GtkTreePath * path_clicked = NULL;
+
+ GtkTreeIter iter_selected = Model::Iter_zero;
+ GtkTreePath * path_selected = NULL;
+
+ GtkTreeSelection * tree_sel = NULL;
+ gint tree_sel_card = 0;
+
+ View::ctx_menu_data * ctxdata = NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ THIS = (Treeview*)_udata;
+
+ // get path to iter over which the user clicked, and the iter too
+ gtk_tree_view_get_path_at_pos(
+ GTK_TREE_VIEW(tree_view),
+ (gint) event->x,
+ (gint) event->y,
+ &path_clicked, NULL, NULL, NULL);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // get path to currently selected iter
+ tree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+ if ( ! tree_sel )
+ {
+ GCMD_ERR("View::signal_button_press_event:gtk_tree_view_get_selection failed");
+ return FALSE;
+ }
+
+ // Note: gtk_tree_selection_count_selected_rows() does not
+ // exist in gtk+-2.0, only in gtk+ >= v2.2 !
+ tree_sel_card = gtk_tree_selection_count_selected_rows(tree_sel);
+
+ if ( tree_sel_card == 1 )
+ {
+ if ( gtk_tree_selection_get_selected( tree_sel, NULL, &iter_selected) )
+ {
+ path_selected = GnomeCmdFoldviewTreestore::get_path(
+ gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)),
+ &iter_selected);
+
+ if ( !path_selected )
+ {
+ GCMD_WNG("View::signal_button_press_event:gtk_tree_model_get_path failed");
+ }
+ }
+ else
+ {
+ GCMD_WNG("View::signal_button_press_event:gtk_tree_selection_get_selected failed");
+ return FALSE;
+ }
+ }
+
+ //.........................................................................
+ // single left click
+ if ( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 1 ) )
+ {
+ // The GtkTreeSelection will be updated only
+ // in the next loop of gtk_main(), and when calling sync(),
+ // the path_selected is still the old selected item, not the
+ // clicked one.
+
+ // So in the sync() function, we use path_clicked instead of
+ // path_selected
+
+ // And this doesnt work - next gtk_main loop too
+ //gtk_tree_selection_unselect_all(tree_sel);
+ //gtk_tree_selection_select_path(tree_sel, path_clicked);
+
+ ctxdata = new ctx_menu_data();
+ ctxdata->a_treeview = THIS;
+ ctxdata->a_time = event->time;
+ ctxdata->a_event_x = event->x;
+ ctxdata->a_event_y = event->y;
+ ctxdata->a_button = event->button;
+ ctxdata->d_path_selected = path_selected;
+ ctxdata->d_path_clicked = path_clicked;
+
+ return THIS->click_left_single(ctxdata);
+ }
+
+ //.........................................................................
+ // single right click : ctx menu
+ if ( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 3 ) )
+ {
+ ctxdata = new ctx_menu_data();
+ ctxdata->a_treeview = THIS;
+ ctxdata->a_time = event->time;
+ ctxdata->a_event_x = event->x;
+ ctxdata->a_event_y = event->y;
+ ctxdata->a_button = event->button;
+ ctxdata->d_path_selected = path_selected;
+ ctxdata->d_path_clicked = path_clicked;
+
+ return THIS->context_menu_pop(ctxdata);
+ }
+
+ //.........................................................................
+ // double left click
+ if ( ( event->type == GDK_2BUTTON_PRESS ) && ( event->button == 1 ) )
+ {
+ ctxdata = new ctx_menu_data();
+ ctxdata->a_treeview = THIS;
+ ctxdata->a_time = event->time;
+ ctxdata->a_event_x = event->x;
+ ctxdata->a_event_y = event->y;
+ ctxdata->a_button = event->button;
+ ctxdata->d_path_selected = path_selected;
+ ctxdata->d_path_clicked = path_clicked;
+
+ return THIS->click_left_double(ctxdata);
+ }
+
+ if ( path_clicked )
+ gtk_tree_path_free(path_clicked);
+
+ // signal was not handled
+ return FALSE;
+}
+
+gboolean GnomeCmdConnectionTreeview::View::Treeview::click_left_single(ctx_menu_data *ctxdata)
+{
+ //GnomeCmdConnectionTreeview::Control_sync_update(NULL, ctxdata); // _GWR_STANDBY_
+ delete ctxdata;
+ // tell gtk to continue signal treatment, else treeview wont
+ // expand / collapse anymore if that was the arrow that was clicked
+ return FALSE;
+}
+
+gboolean GnomeCmdConnectionTreeview::View::Treeview::click_left_double(ctx_menu_data *ctxdata)
+{
+ Control::Set_active_tab(NULL, ctxdata);
+
+ return TRUE;
+}
+
+// ===========================================================================
+// Contextual menu
+// ===========================================================================
+gboolean GnomeCmdConnectionTreeview::View::Treeview::context_menu_pop(ctx_menu_data *ctxdata)
+{
+ ctxdata->a_treeview->view()->control()->context_menu_pop(ctxdata);
+
+ return TRUE;
+}
+
+
+
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview::View
+//
+// ###########################################################################
+
+// ***************************************************************************
+//
+// Constructor, ...
+//
+// ***************************************************************************
+GnomeCmdConnectionTreeview::View::View(
+ GnomeCmdConnectionTreeview::Control * _control,
+ GtkTreeModel * _treemodel)
+{
+ raz_pointers();
+ init_instance(_control, _treemodel);
+}
+GnomeCmdConnectionTreeview::View::~View()
+{
+ delete d_headband;
+ delete d_treeview;
+}
+
+void
+GnomeCmdConnectionTreeview::View::raz_pointers()
+{
+ a_control = NULL;
+
+ d_vbox_main = NULL;
+ d_headband = NULL;
+ d_treeview = NULL;
+
+ a_treeview_showed = TRUE;
+}
+
+void
+GnomeCmdConnectionTreeview::View::init_instance(
+ GnomeCmdConnectionTreeview::Control * _control,
+ GtkTreeModel * _treemodel)
+{
+ g_return_if_fail( _control );
+ //g_return_if_fail( _treemodel );
+
+ a_control = _control;
+
+ d_vbox_main = gtk_vbox_new(FALSE, 0);
+
+ d_headband = GCMD_STRUCT_NEW(HeadBand, this);
+ d_treeview = GCMD_STRUCT_NEW(Treeview, this, _treemodel);
+
+ //.........................................................................
+ //
+ // Packing
+ //
+ gtk_box_pack_start(GTK_BOX(d_vbox_main), d_headband->widget(), FALSE, TRUE , 0);
+ gtk_box_pack_start(GTK_BOX(d_vbox_main), d_treeview->widget(), TRUE , TRUE , 0);
+}
+
+
+void
+GnomeCmdConnectionTreeview::View::show()
+{
+ gtk_widget_show_all(d_vbox_main);
+}
+void
+GnomeCmdConnectionTreeview::View::hide()
+{
+ gtk_widget_hide_all(d_vbox_main);
+}
+
+void
+GnomeCmdConnectionTreeview::View::update_style()
+{
+}
+void
+GnomeCmdConnectionTreeview::View::show_treeview()
+{
+ if ( treeview_showed() )
+ {
+ GCMD_ERR("View::hide_treeview():already shown");
+ return;
+ }
+
+ gtk_box_pack_start(GTK_BOX(d_vbox_main), d_treeview->widget(), TRUE , TRUE , 0);
+ g_object_unref(d_treeview->widget());
+
+ headband()->set_image_opened();
+
+ a_treeview_showed = TRUE;
+}
+void
+GnomeCmdConnectionTreeview::View::hide_treeview()
+{
+ if ( ! treeview_showed() )
+ {
+ GCMD_ERR("View::hide_treeview():already hidden");
+ return;
+ }
+
+ g_object_ref(d_treeview->widget());
+ gtk_container_remove(GTK_CONTAINER(d_vbox_main), d_treeview->widget());
+
+ headband()->set_image_closed();
+
+ a_treeview_showed = FALSE;
+}
+
+
+
+
+GnomeCmdConnectionTreeview::eIcon
+GnomeCmdConnectionTreeview::View::Icon_from_type_access(
+ eFileType type,
+ eFileAccess access)
+{
+ if ( type == eTypeDirectory )
+ {
+ if ( Access_readable(access) )
+ return GnomeCmdConnectionTreeview::eIconDirReadWrite;
+ else
+ return GnomeCmdConnectionTreeview::eIconDirReadOnly;
+
+ //switch ( access )
+ //{
+ // case eAccessRW : return GcmdGtkFoldview::View::eIconDirReadWrite; break;
+ // case eAccessRO : return GcmdGtkFoldview::View::eIconDirReadOnly; break;
+ // case eAccessFB : return GcmdGtkFoldview::View::eIconDirForbidden; break;
+ // default : return GcmdGtkFoldview::View::eIconUnknown; break;
+ //}
+ }
+
+ if ( type == eTypeSymlink )
+ {
+ if ( Access_readable(access) )
+ return GnomeCmdConnectionTreeview::eIconSymlinkToDirReadWrite;
+ else
+ return GnomeCmdConnectionTreeview::eIconSymlinkToDirReadOnly;
+
+ //switch ( access )
+ //{
+ // case eAccessRW : return GcmdGtkFoldview::View::eIconSymlinkToDirReadWrite; break;
+ // case eAccessRO : return GcmdGtkFoldview::View::eIconSymlinkToDirReadOnly; break;
+ // case eAccessFB : return GcmdGtkFoldview::View::eIconSymlinkToDirForbidden; break;
+ // default : return GcmdGtkFoldview::View::eIconUnknown; break;
+ //}
+ }
+
+ return eIconUnknown;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview-view.snippet.h b/src/foldview/gnome-cmd-connection-treeview-view.snippet.h
new file mode 100644
index 0000000..3bd3fd9
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview-view.snippet.h
@@ -0,0 +1,323 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview-view.snippet.h
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : View
+
+ Parent : GnomeCmdConnectionTreeView
+
+ This file is directly inluded in gnome-cmd-connection-treeview.h
+
+ ###########################################################################
+*/
+
+// ***************************************************************************
+// #define
+// ***************************************************************************
+// ===========================================================================
+//
+// ===========================================================================
+
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview::View
+//
+// ###########################################################################
+struct View
+{
+ // ***********************************************************************
+ // * *
+ // * Enums, ... *
+ // * *
+ // ***********************************************************************
+ // =======================================================================
+ //
+ // =======================================================================
+ public:
+ // ***********************************************************************
+ // * *
+ // * Structs *
+ // * *
+ // ***********************************************************************
+ public:
+ struct HeadBand;
+ struct Treeview;
+ // =======================================================================
+ // Context menu
+ // =======================================================================
+ public:
+ struct ctx_menu_data
+ {
+ Treeview * a_treeview;
+ GtkTreePath * d_path_clicked;
+ GtkTreePath * d_path_selected;
+ guint32 a_time;
+ gint a_event_x;
+ gint a_event_y;
+ guint a_button;
+
+ ~ctx_menu_data()
+ {
+ if ( d_path_selected )
+ {
+ gtk_tree_path_free(d_path_selected);
+ }
+ if ( d_path_clicked )
+ {
+ gtk_tree_path_free(d_path_clicked);
+ }
+ }
+
+ void *operator new(size_t size) { return g_new0(ctx_menu_data, 1); }
+ void operator delete(void *p) { g_free(p); }
+ };
+
+ // =======================================================================
+ // HeadBand
+ // =======================================================================
+ public:
+ struct HeadBand
+ {
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ View * a_view;
+
+ GtkWidget * d_hbox_main;
+ GtkWidget * d_button_connection_image;
+ GtkWidget * d_entry_path;
+ GtkWidget * d_alignement_padder;
+ GtkWidget * d_button_refresh;
+ GtkWidget * d_button_sort;
+ GtkWidget * d_button_show_hide;
+ GtkWidget * d_button_close;
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ inline View * view() { return a_view; }
+ inline GtkWidget * widget() { return d_hbox_main; }
+
+ void show();
+ void hide();
+ void update_style();
+
+ void set_image_closed();
+ void set_image_opened();
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ void raz_pointers();
+ void init_instance(GnomeCmdConnectionTreeview::View*);
+
+ public:
+ HeadBand(GnomeCmdConnectionTreeview::View*);
+ ~HeadBand();
+
+ void dispose();
+ void finalize();
+ };
+ // =======================================================================
+ // Treeview
+ // =======================================================================
+ public:
+ struct Treeview
+ {
+ friend class View;
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ View * a_view;
+
+ GtkTreeModel * a_treemodel;
+
+ GtkWidget * d_scrolled_window;
+ GtkWidget * d_treeview;
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ inline View * view() { return a_view; }
+ private:
+ inline GtkTreeView * treeview() { return GTK_TREE_VIEW(d_treeview); }
+ inline GtkTreeModel * treemodel() { return a_treemodel; }
+ //.....................................................................
+ public:
+ inline GtkWidget * widget() { return d_scrolled_window; }
+
+ void show();
+ void hide();
+ void update_style();
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ void raz_pointers();
+ void init_instance(GnomeCmdConnectionTreeview::View*, GtkTreeModel*);
+
+ public:
+ Treeview(GnomeCmdConnectionTreeview::View*, GtkTreeModel*);
+ ~Treeview();
+ void dispose();
+ void finalize();
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ static void CellRendererPixbuf(
+ GtkTreeViewColumn *col,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+
+ static void CellRendererTxt(
+ GtkTreeViewColumn *col,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ eRowState row_state(GtkTreePath* _path);
+ gboolean row_collapse(GtkTreePath* _path);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ static void signal_cursor_changed (GtkTreeView* tree_view, gpointer);
+ static gboolean signal_test_expand_row (GtkTreeView*, GtkTreeIter*, GtkTreePath*, gpointer);
+ static void signal_row_expanded (GtkTreeView*, GtkTreeIter*, GtkTreePath*, gpointer);
+ static void signal_row_collapsed (GtkTreeView*, GtkTreeIter*, GtkTreePath*, gpointer);
+ //.....................................................................
+ static gboolean signal_button_press_event(GtkWidget*, GdkEventButton*, gpointer);
+ static gboolean click_left_single(ctx_menu_data*);
+ static gboolean click_left_double(ctx_menu_data*);
+ //.....................................................................
+ static gboolean context_menu_pop(ctx_menu_data*);
+
+ private:
+ GtkTreeSelection * selection()
+ {
+ return gtk_tree_view_get_selection(treeview());
+ }
+ gint selection_count()
+ {
+ // Note: gtk_tree_selection_count_selected_rows() does not
+ // exist in gtk+-2.0, only in gtk+ >= v2.2 !
+ return gtk_tree_selection_count_selected_rows(selection());
+ }
+ };
+ // ***********************************************************************
+ // * *
+ // * Members *
+ // * *
+ // ***********************************************************************
+ private:
+ Control * a_control;
+
+ GtkWidget * d_vbox_main;
+ GcmdStruct<HeadBand> * d_headband;
+ GcmdStruct<Treeview> * d_treeview;
+
+ gboolean a_treeview_showed;
+
+ // =======================================================================
+ // divers
+ // =======================================================================
+
+
+ // ***********************************************************************
+ // * *
+ // * Methods *
+ // * *
+ // ***********************************************************************
+
+ // =======================================================================
+ // accessors, ...
+ // =======================================================================
+ public:
+ inline Control * control() { return a_control; }
+ inline HeadBand * headband() { return d_headband; }
+ inline Treeview * treeview() { return d_treeview; }
+ inline GtkWidget * widget() { return d_vbox_main; }
+ inline gboolean treeview_showed() { return a_treeview_showed; }
+
+ void show();
+ void hide();
+ void update_style();
+
+ void show_treeview();
+ void hide_treeview();
+ // =======================================================================
+ // new, ...
+ // =======================================================================
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ void raz_pointers();
+ void init_instance(GnomeCmdConnectionTreeview::Control*, GtkTreeModel*);
+
+ public:
+ View(GnomeCmdConnectionTreeview::Control*, GtkTreeModel*);
+ ~View();
+ void dispose();
+ void finalize();
+ // =======================================================================
+ // wrappers
+ // =======================================================================
+ public:
+ inline GtkTreeSelection * selection() { return treeview()->selection(); }
+ inline gint selection_count() { return treeview()->selection_count(); }
+ inline eRowState row_state(GtkTreePath* _path) { return treeview()->row_state(_path); }
+ inline gboolean row_collapse(GtkTreePath* _path) { return treeview()->row_collapse(_path); }
+ // =======================================================================
+ // dives
+ // =======================================================================
+ public:
+ static eIcon Icon_from_type_access(eFileType, eFileAccess);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ // For menu editing simplicity
+ private:
+ gboolean context_menu_pop(ctx_menu_data*);
+ gboolean click_left_single(ctx_menu_data *ctxdata);
+ gboolean click_left_double(ctx_menu_data *ctxdata);
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-connection-treeview.cc b/src/foldview/gnome-cmd-connection-treeview.cc
new file mode 100644
index 0000000..a253c3f
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview.cc
@@ -0,0 +1,262 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview.cc
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : GnomeCmdConnectionTreeview
+
+ ###########################################################################
+*/
+#include "gnome-cmd-connection-treeview.h"
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview
+//
+// ###########################################################################
+
+GdkPixbuf * GnomeCmdConnectionTreeview::s_gdk_pixbuf[GnomeCmdConnectionTreeview::eIconCard];
+gboolean GnomeCmdConnectionTreeview::s_gdk_pixbuf_loaded = FALSE;
+
+gchar * GnomeCmdConnectionTreeview::Collate_key_dot = NULL;
+gchar * GnomeCmdConnectionTreeview::Collate_key_dotdot = NULL;
+gchar * GnomeCmdConnectionTreeview::Collate_key_uri_01 = NULL;
+
+// ***************************************************************************
+//
+// Constructor, ...
+//
+// ***************************************************************************
+GnomeCmdConnectionTreeview::GnomeCmdConnectionTreeview(
+ GcmdGtkFoldview * _foldview,
+ GnomeCmdCon * _con)
+{
+ // UPS rocks :)
+ GnomeVFSURI * u = NULL;
+ GnomeCmdPath * p = NULL;
+ gchar * s = NULL;
+ //.........................................................................
+ g_return_if_fail( _foldview );
+ g_return_if_fail( _con );
+
+ Pixbuf_load_all();
+
+ // static collate keys : static vars are not correctly initialized
+ // in this form :
+ // gchar * GnomeCmdConnectionTreeview::Collate_key_dot = g_utf8_collate_key(_("."), -1);
+ if ( ! Collate_key_dot )
+ {
+ Collate_key_dot = g_utf8_collate_key(_("."), -1);
+ Collate_key_dotdot = g_utf8_collate_key(_(".."), -1);
+ Collate_key_uri_01 = g_utf8_collate_key(_("file:///"), -1);
+ }
+
+ a_foldview = _foldview;
+ a_connection = _con;
+
+ // create the control
+ d_control = GCMD_STRUCT_NEW(Control, this);
+
+ // create the model
+ d_model = GCMD_STRUCT_NEW(Model, d_control);
+
+ // create the view
+ d_view = GCMD_STRUCT_NEW(View, d_control, model()->treemodel());
+
+ // go !
+ if ( gnome_cmd_con_is_local(a_connection) )
+ {
+ p = gnome_cmd_con_create_path(a_connection, "");
+ u = gnome_cmd_con_create_uri(a_connection, p);
+ s = gnome_vfs_uri_to_string(u, GNOME_VFS_URI_HIDE_NONE);
+
+ model()->add_first_tree(s, gnome_cmd_con_get_alias(a_connection));
+
+ GCMD_INF("GnomeCmdConnectionTreeview()::first tree uri [%s]", s);
+
+ g_object_ref_sink(p);
+ g_object_unref(p);
+ gnome_vfs_uri_unref(u);
+ g_free(s);
+ }
+
+
+}
+
+GnomeCmdConnectionTreeview::~GnomeCmdConnectionTreeview()
+{
+ delete d_model;
+ delete d_view;
+ delete d_control;
+}
+
+
+// ***************************************************************************
+//
+// Icons
+//
+// ***************************************************************************
+gboolean
+GnomeCmdConnectionTreeview::Pixbuf_load(
+ GnomeCmdConnectionTreeview::eIcon _icon,
+ const gchar * _filename)
+{
+ GError * g_error = NULL;
+ //.........................................................................
+ s_gdk_pixbuf[_icon] = gdk_pixbuf_new_from_file(_filename, &g_error);
+
+ if ( g_error )
+ {
+ GCMD_ERR("GnomeCmdConnectionTreeview::Pixbuf_load():%s", g_error->message );
+ g_error_free(g_error);
+ return FALSE;
+ }
+ return TRUE;
+}
+gboolean
+GnomeCmdConnectionTreeview::Pixbuf_load_all()
+{
+ if ( s_gdk_pixbuf_loaded )
+ return TRUE;
+
+ Pixbuf_load(eIconUnknown, "../pixmaps/file-type-icons/file_type_unknown.xpm");
+
+ Pixbuf_load(eIconDirReadWrite, "../pixmaps/file-type-icons/file_type_dir.xpm");
+ Pixbuf_load(eIconDirReadOnly, "../pixmaps/file-type-icons/file_type_dir_orange.xpm");
+ Pixbuf_load(eIconDirForbidden, "../pixmaps/file-type-icons/file_type_dir_red.xpm");
+
+ Pixbuf_load(eIconSymlinkToDirReadWrite, "../pixmaps/file-type-icons/file_type_symlink_to_dir_green.xpm");
+ Pixbuf_load(eIconSymlinkToDirReadOnly, "../pixmaps/file-type-icons/file_type_symlink_to_dir_orange.xpm");
+ Pixbuf_load(eIconSymlinkToDirForbidden, "../pixmaps/file-type-icons/file_type_symlink_to_dir_red.xpm");
+
+ Pixbuf_load(eIconDummy, "../pixmaps/file-type-icons/file_type_unknown.xpm");
+ Pixbuf_load(eIconWarning, "../pixmaps/gtk-dialog-warning.png");
+
+ Pixbuf_load(eIconGtkRefresh, "../pixmaps/gtk-refresh.png");
+ Pixbuf_load(eIconGtkSortAscending, "../pixmaps/gtk-sort-ascending.png");
+ Pixbuf_load(eIconGtkSortDescending, "../pixmaps/gtk-sort-descending.png");
+ Pixbuf_load(eIconFolderOpened, "../pixmaps/folder-opened.png");
+ Pixbuf_load(eIconFolderClosed, "../pixmaps/folder-closed.png");
+ Pixbuf_load(eIconGtkClose, "../pixmaps/gtk-close.png");
+
+ s_gdk_pixbuf_loaded = TRUE;
+
+ return TRUE;
+}
+void
+GnomeCmdConnectionTreeview::Pixbuf_unload_all()
+{
+ g_object_unref(s_gdk_pixbuf[eIconUnknown] );
+
+ g_object_unref(s_gdk_pixbuf[eIconDirReadWrite] );
+ g_object_unref(s_gdk_pixbuf[eIconDirReadOnly] );
+ g_object_unref(s_gdk_pixbuf[eIconDirForbidden] );
+
+ g_object_unref(s_gdk_pixbuf[eIconSymlinkToDirReadWrite] );
+ g_object_unref(s_gdk_pixbuf[eIconSymlinkToDirReadOnly] );
+ g_object_unref(s_gdk_pixbuf[eIconSymlinkToDirForbidden] );
+
+ g_object_unref(s_gdk_pixbuf[eIconDummy] );
+ g_object_unref(s_gdk_pixbuf[eIconWarning] );
+
+ g_object_unref(s_gdk_pixbuf[eIconGtkRefresh] );
+ g_object_unref(s_gdk_pixbuf[eIconGtkSortAscending] );
+ g_object_unref(s_gdk_pixbuf[eIconGtkSortDescending] );
+ g_object_unref(s_gdk_pixbuf[eIconFolderOpened] );
+ g_object_unref(s_gdk_pixbuf[eIconFolderClosed] );
+ g_object_unref(s_gdk_pixbuf[eIconGtkClose] );
+}
+
+// ***************************************************************************
+//
+// Connection infos
+//
+// ***************************************************************************
+gboolean
+GnomeCmdConnectionTreeview::is_samba()
+{
+ return ( a_connection->method == CON_SMB );
+}
+gboolean
+GnomeCmdConnectionTreeview::is_local()
+{
+ return ( a_connection->method == CON_LOCAL );
+}
+
+gboolean
+GnomeCmdConnectionTreeview::host_redmond()
+{
+ return FALSE; // _GWR_TODO_
+}
+
+// ***************************************************************************
+//
+// Actions
+//
+// ***************************************************************************
+void
+GnomeCmdConnectionTreeview::set_packing_expansion(gboolean b)
+{
+ foldview()->treeview_set_packing_expansion(this, b);
+}
+
+void
+GnomeCmdConnectionTreeview::close()
+{
+ foldview()->treeview_del(this);
+}
+
+
+// ***************************************************************************
+//
+// Divers
+//
+// ***************************************************************************
+GnomeCmdConnectionTreeview::eFileAccess
+GnomeCmdConnectionTreeview::Access_from_permissions(
+ eFilePerm _p1,
+ eFilePerm _p2)
+{
+ return (eFileAccess)( (guint32)_p1 + (guint32)_p2 );
+}
+
+GnomeCmdConnectionTreeview::eFileAccess
+GnomeCmdConnectionTreeview::Access_from_read_write(
+ gboolean _read,
+ gboolean _write)
+{
+ eFilePerm p1 = ( _read ? ePermRead : ePermNone );
+ eFilePerm p2 = ( _write ? ePermWrite : ePermNone );
+
+ return Access_from_permissions(p1,p2);
+}
+
+gboolean
+GnomeCmdConnectionTreeview::Access_readable(
+ eFileAccess _access)
+{
+ return ( ((guint32)_access & (guint32)ePermRead) != 0 );
+}
diff --git a/src/foldview/gnome-cmd-connection-treeview.h b/src/foldview/gnome-cmd-connection-treeview.h
new file mode 100644
index 0000000..c0bf754
--- /dev/null
+++ b/src/foldview/gnome-cmd-connection-treeview.h
@@ -0,0 +1,287 @@
+/*
+ ###########################################################################
+
+ gnome-cmd-connection-treeview.h
+
+ ---------------------------------------------------------------------------
+
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ ---------------------------------------------------------------------------
+
+ Struct : GnomeCmdConnectionTreeView
+
+ ###########################################################################
+*/
+#ifndef __GNOME_CMD_CONNECTION_TREEVIEW_H__
+#define __GNOME_CMD_CONNECTION_TREEVIEW_H__
+
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+// ...........................................................................
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+// ...........................................................................
+#include "gnome-cmd-includes.h"
+#include "gnome-cmd-con.h"
+// ...........................................................................
+#include "gnome-cmd-foldview-utils.h"
+#include "gnome-cmd-foldview-logger.h"
+#include "gnome-cmd-foldview-quickstack.h"
+#include "gnome-cmd-foldview-treestore.h"
+#include "gnome-cmd-foldview-private.h"
+// ***************************************************************************
+// #define
+// ***************************************************************************
+// ===========================================================================
+// #define : Foldview config
+// ===========================================================================
+#define GCMDGTKFOLDVIEW_ALLOW_MONITORING FALSE
+#define GCMDGTKFOLDVIEW_USE_GIO FALSE
+
+#define GCMDGTKFOLDVIEW_GVFS_ITEMS_PER_NOTIFICATION 30
+
+#define GCMDGTKFOLDVIEW_REFRESH_CYCLE_N_MESSAGES 10
+#define GCMDGTKFOLDVIEW_REFRESH_CYCLE_PERIOD_MS 200
+
+#define GCMDGTKFOLDVIEW_SORTING_CYCLE_PERIOD_MS 60
+
+
+// ###########################################################################
+//
+// GnomeCmdConnectionTreeview
+//
+// ###########################################################################
+struct GnomeCmdConnectionTreeview
+{
+ // ***********************************************************************
+ // * *
+ // * Enums, ... *
+ // * *
+ // ***********************************************************************
+ public : enum eFilePerm
+ {
+ // these permissions are user-relatives ( the user that launched gcmd )
+
+ ePermNone = 0 ,
+ ePermRead = 1 ,
+ ePermWrite = 2 ,
+ };
+
+ public:
+ enum eFileAccess
+ {
+ eAccessFB = 0 ,
+ eAccessRO = 1 ,
+ eAccessWO = 2 ,
+ eAccessRW = 3 ,
+
+ eAccessUN = 4
+ };
+
+ public : enum eFileType
+ {
+ eTypeUnknown = 0 ,
+
+ eTypeDirectory = 1 ,
+ eTypeSymlink = 2
+ };
+
+ public : enum eFileError
+ {
+ eErrorNone = 0,
+ // inspired from GnomeVFS
+ eErrorFileNotFound = 1,
+ eErrorAccessDenied = 2,
+ eErrorCancelled = 3,
+ eErrorTimeout = 4,
+ // added from GIO
+
+
+ eErrorOther = 1024
+ };
+
+ public : enum eRowState
+ {
+ eRowStateUnknown = 0,
+
+ eRowStateCollapsed = 1,
+ eRowStateExpanded = 2
+ };
+
+ typedef gchar *Uri;
+
+ // =======================================================================
+ // Icons
+ // =======================================================================
+ public:
+ enum eIcon
+ {
+ eIconUnknown = 0,
+
+ eIconDirReadWrite = 1,
+ eIconDirReadOnly = 2,
+ eIconDirForbidden = 3,
+
+ eIconSymlinkToDirReadWrite = 4,
+ eIconSymlinkToDirReadOnly = 5,
+ eIconSymlinkToDirForbidden = 6,
+
+ eIconDummy = 7,
+ eIconWarning = 8,
+
+ eIconGtkRefresh = 9,
+
+ eIconGtkSortAscending = 10,
+ eIconGtkSortDescending = 11,
+
+ eIconFolderOpened = 12,
+ eIconFolderClosed = 13,
+
+ eIconGtkClose = 14,
+
+ eIconCard = 15
+ };
+ // ***********************************************************************
+ // * *
+ // * Structs *
+ // * *
+ // ***********************************************************************
+ struct Model;
+ struct View;
+ struct Control;
+
+ #include "gnome-cmd-connection-treeview-model.snippet.h"
+ #include "gnome-cmd-connection-treeview-view.snippet.h"
+ #include "gnome-cmd-connection-treeview-control.snippet.h"
+
+ // ***********************************************************************
+ // * *
+ // * Members *
+ // * *
+ // ***********************************************************************
+ public:
+ static gchar * Collate_key_dot; // ck of "."
+ static gchar * Collate_key_dotdot; // ck of ".."
+ static gchar * Collate_key_uri_01; // ck of "file:///"
+
+ private:
+ static GdkPixbuf * s_gdk_pixbuf[eIconCard];
+ static gboolean s_gdk_pixbuf_loaded;
+
+ GnomeCmdCon * a_connection;
+ GcmdGtkFoldview * a_foldview;
+
+ GcmdStruct<Model> * d_model;
+ GcmdStruct<View> * d_view;
+ GcmdStruct<Control> * d_control;
+
+ // ***********************************************************************
+ // * *
+ // * Methods *
+ // * *
+ // ***********************************************************************
+ // =======================================================================
+ // new, ...
+ // =======================================================================
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ public:
+ GnomeCmdConnectionTreeview(GcmdGtkFoldview*, GnomeCmdCon*);
+ ~GnomeCmdConnectionTreeview();
+ // =======================================================================
+ // accessors
+ // =======================================================================
+ public:
+ inline GcmdGtkFoldview * foldview() { return a_foldview; }
+ inline GnomeCmdCon * connection() { return a_connection; }
+ inline Model * model() { return d_model; }
+ inline View * view() { return d_view; }
+ inline Control * control() { return d_control; }
+ // =======================================================================
+ // wrappers
+ // =======================================================================
+ public:
+ inline GtkWidget * widget() { return d_view->widget(); }
+ inline void show() { d_view->show(); }
+ inline void hide() { d_view->hide(); }
+ inline void update_style() { d_view->update_style(); }
+ // =======================================================================
+ // icons
+ // =======================================================================
+ private:
+ static gboolean Pixbuf_load(GnomeCmdConnectionTreeview::eIcon, const gchar*);
+ static gboolean Pixbuf_load_all();
+ static void Pixbuf_unload_all();
+ // =======================================================================
+ // connection infos
+ // =======================================================================
+ public:
+ gboolean is_samba();
+ gboolean is_local();
+ gboolean host_redmond();
+ // =======================================================================
+ // some stuff
+ // =======================================================================
+ void set_packing_expansion(gboolean);
+ void close();
+ // =======================================================================
+ // divers
+ // =======================================================================
+ static eFileAccess Access_from_permissions (eFilePerm _p1, eFilePerm _p2);
+ static eFileAccess Access_from_read_write (gboolean _read, gboolean _write);
+ static gboolean Access_readable (eFileAccess);
+
+ static inline void Error_Msg_Abort()
+ {
+ MSG_WNG(" * Async mismatch *");
+ }
+
+ static inline void Error_Msg_Failure()
+ {
+ MSG_WNG(" * Failure * ( Please note that failure may be normal async change, ");
+ MSG_WNG(" error handling has to be improved in foldview code )");
+ }
+
+
+};
+
+#endif // __GNOME_CMD_CONNECTION_TREEVIEW_H__
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-foldview-docs.h b/src/foldview/gnome-cmd-foldview-docs.h
new file mode 100644
index 0000000..163969b
--- /dev/null
+++ b/src/foldview/gnome-cmd-foldview-docs.h
@@ -0,0 +1,944 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/*
+
+
+###############################################################################
+ TODO GWR
+###############################################################################
+
+ GcmdFileSelector resize automatically resize the main vertical pane
+ ( FILL / EXPAND gtk settings somewhere ) ?
+
+ Trivial bug as no item is selectionned on foldview 'open in active tab'
+
+ Check all g_list_append / prepend, doc says it works with NULL pointers
+
+ ReEnable double-click
+
+ Separators between multiples trees
+
+ Effective sorting in GtkTreeView
+
+ Test with GIO
+
+ Show broken symlinks
+
+ ..................... facultative / later ............................
+
+ sync file_list when it is not active ( in a hidden tab )
+
+ Bookmarks
+
+ Foldview metadata ( ex : foldview visibility )
+
+ Improve GnomeCmdFoldviewTreestore::Node access by introducing
+ depth info in uids ? seems impossible with actual code...
+
+ .......................................................................
+DONE _GWR_BUG_#01_
+
+DONE Notification from filesystem, GIO based ( half coded )
+ - GIO bug : no self EVENT_DELETE after async op has been
+ done on a monitored GFile
+ - There is another similar bug too
+ -> Monitorig development freezed, I want foldview to be lenny-compatible
+
+DONE AsyncCore errors : detail & display in async callbacks
+ -> made with log enhance
+
+DONE Log enhance
+
+DONE AsyncCore errors : use eIconWarning
+
+DONE - corrected stupid & critical bug in GnomeCmdFoldviewTreestore::iter_next
+ - refresh seems to be OK
+ - monitoring develeoppement stopped ( although quite complete )
+
+DONE Refresh is implemented, monitoring is on stand-by till a decision
+ is taken relatively to GnomeVFS / GIO bugs in Debian Lenny
+
+ .......................................................................
+COMMIT 2a1a27202012327d1da9d20e7deb9892a9e9028d
+
+DONE foldview as a static lib, libfoldview.a - its the only way I found to
+ put foldview sources in a separate directory
+
+ .......................................................................
+COMMIT a406809dfa5cbcc1b9928cb45695bb1928df1578
+
+DONE Notification from filesystem, GnomeVFS based - * it works *
+
+DONE Focus on read permission, deleted write permission display in foldview
+
+DONE A little bit of conception for data stored in the treestore
+
+DONE Split model filesystem access in 2 modules : GIO & GnomeVFS
+
+DONE model : replaced 'struct Refresh' by 'struct AsyncCBData'
+ ( -> removing GcmdFoldview() calls )
+
+DONE moved paths into GnomeCmdFoldviewTreestore
+
+DONE moved uids into GnomeCmdFoldviewTreestore
+
+DONE all pre-requisite code for refresh
+
+DONE reduce number of gnome_vfs_uri_new() calls
+
+DONE removed struct UserLoadSubdir
+
+DONE moved control code in model for expand, collapse, check if empty
+
+DONE 'match' : coded match uid for childs
+
+ .......................................................................
+COMMIT e6eb3e8ab1ed1ea37cdece1e4e835a4a583927e1
+
+DONE 'match' : nearly coded, missing match code in GnomeCmdFoldviewTreestore
+
+DONE 'refresh' : coded until async_ops
+
+DONE 'delete root node' : Finished
+
+ .......................................................................
+COMMIT db15c04d3067ec023bcbe6eee0c86690f4becc86
+
+done coded 'delete root node', popup menu only
+
+DONE eIconUnknown on first add_tree, when creating the foldview
+
+DONE removed GLib warning from gvalue.c, missing a g_value_unset
+
+DONE code cleanup
+
+ .......................................................................
+COMMIT 9ae7289de1ee43f50ef45cdda5d08a2b6ab9f876
+
+DONE changed copyright to copyleft for me, and verified GPL headers for
+ foldview modules
+
+DONE implemented multiple root nodes ( just like nautilus ), which will
+ lead to opening bookmarks in foldview
+
+DONE removed #define __GTS__ , bye bye GtkTreeStore
+
+ .......................................................................
+COMMIT c3e79b41c22091e3e6452130cff1a04948f428d8
+
+DONE init / destroy cleanup : g_object_ref on hided widgets
+
+DONE memory leaks hunt
+
+DONE memory leak : gnome-cmd-foldview-control.cc::814 forgot g_free(str)
+
+DONE memory leak : root node
+
+DONE memory leak : GcmdGtkFldview::Model::destroy implemented
+
+DONE memory leak : gvfs quickstack
+
+DONE correct ESC[30m for terminal after each gwr_print
+
+ .......................................................................
+COMMIT 05bb32e2cfd8eb56bf64e93bc1785ce52f6a100d
+
+DONE symlinks icons show little white pixel when selected its ugly
+ but gcmd's too
+
+DONE foldview correct position on show / hide ( cmdline, buttonbar, ... )
+
+DONE (Finally) gcmd crashes when opening access-denied folder from treeview
+ in tab, after showing an alert
+
+DONE Going crazy with correct theming of treeview with selectionned items,
+ focus between widgets,...
+
+DONE combo connections at startup
+
+DONE gtk_widget_set_sensitive on non-full-functional items of context menu
+
+DONE Check index_ff on qstack_push()
+
+DONE ? mutex on handles : no, gvfs_async calls are queued
+ and since I use gdk_threads_enter/leave, there is no more
+ concurrency between gtk & gvfs
+
+DONE why GVFS_qstack_ff / GVFS_qstack_size is always n-2 / n ??? should be n / n
+ -> because t' affiches ff _avant_ update et qsize au lieu de qsize - 1,
+ stupid, ça fait un décalage de 2
+
+DONE Comments cleanup
+
+DONE Private logging for gvfs ops
+
+DONE Cancel all async ops
+
+DONE Big Bug in checking type of GnomeVFSFileInfo : GNOME_VFS_FILE_TYPE_...
+ are distinct values - it is not a bitfield, triple fuck, spended time
+ on that
+
+###############################################################################
+ TODO EPIOTR
+###############################################################################
+
+DONE in src/gnome-cmd-foldview.h:
+ extern gboolean gnome_cmd_foldview_set_root_1(gchar *text);
+ ...
+ extern GtkWidget *GcmdWidget();
+ 'extern' is superfluous here, please remove it
+
+DONE epiotr.10.07.16.gcmd-foldview
+DONE ua
+
+ epiotr.10.07.22.kill-warnings
+DONE epiotr.10.07.22.gtk_object_ref,unref
+
+DONE epiotr.10.07.24.000? struct-gvfs_async_caller_data
+DONE epiotr.10.07.24.000? struct-gvfs-async
+DONE epiotr.10.07.24.000? struct-gvfs-async-load-subdirs
+DONE epiotr.10.07.24.000? struct-gvfs-async-load-subdirs-subdirs
+
+
+DONE * I've moved view_treeview() to gnome-cmd-user-actions.cc. I'm
+ sending you a patch for that.
+
+DONE * after opening foldview, cmdline is moved from bottom to top -
+ that requires fixing
+
+DONE * move foldview code to src/foldview
+
+DONE * changing your surname from WARDAVOIR -> Wardavoir (this is GNOME
+ standard) ;o)
+
+DONE * remove singleton
+
+ * foldview should respect global settings for case sensitive
+ sorting (gnome_cmd_data.case_sens_sort) and showing hidden dirs
+ (gnome_cmd_data.filter_settings.hidden)
+
+ * when folview is opened for the first time, it should initially
+ expand to the current dir of active pane:
+ main_win->fs(ACTIVE)->get_directory()
+
+ * making your 'earlgrey' repo based on current 'treeview' branch
+
+DONE * please do not fix bugs in 'core' gcmd in 'earlgrey' repo, they
+ may go unnoticed... Please send them directly to me or to
+ gcmd-devel list, they will go into into master and then will get
+ merged into treeview
+
+###############################################################################
+ WIDGET HIERARCHY FOR GcmdGtkFoldview
+###############################################################################
+
+ Sample for "horizontal view" ( all widgets are under main_win->priv->... )
+
+ +-----------------------------------------------------------------------+
+ | |
+ | main_win->priv->vbox |
+ | |
+ | +-------------------------------+-------------------------------+ |
+ | | | | |
+ | | foldview_paned | foldview_paned | |
+ | | ( pane #1 ) | ( pane #2 ) | |
+ | | | | |
+ | | +-----------------------+ | +-----------------------+ | |
+ | | | | | | | | |
+ | | | foldview | | | paned ( pane #1 ) | | |
+ | | | | | | | | |
+ | | | | | | +---------------+ | | |
+ | | | | | | | | | | |
+ | | | | | | | GnomeCmdList | | | |
+ | | | | | | | | | | |
+ | | | | | | +---------------+ | | |
+ | | | | | | | | |
+ | | | | | +-----------------------+ | |
+ | | | | | | | | |
+ | | | | | | paned ( pane #2 ) | | |
+ | | | | | | | | |
+ | | | | | | +---------------+ | | |
+ | | | | | | | | | | |
+ | | | | | | | GnomeCmdList | | | |
+ | | | | | | | | | | |
+ | | | | | | +---------------+ | | |
+ | | | | | | | | |
+ | | +-----------------------+ | +-----------------------+ | |
+ | | | | |
+ | | | | |
+ | +-------------------------------+-------------------------------+ |
+ | |
+ +-----------------------------------------------------------------------+
+
+
+###############################################################################
+ GTK+ DRAG & DROP SYNOPSIS
+###############################################################################
+
+
+ "drag-begin" SRC
+
+ "drag-motion" DST
+ |
+ |
+ +-----------------------+
+ | |
+ | |
+ "drag-drop" "drag-leave" DST
+ |
+ |
+ "drag-data-get" SRC
+ |
+ |
+ "drag-data-received" DST
+ |
+ |
+ "drag-end" SRC
+
+
+ + "drag-failed" SRC
+ "drag-data-delete" SRC
+
+
+
+
+###############################################################################
+ TEMPORARY TRASH-CODE
+###############################################################################
+
+// ===========================================================================
+// iter_collapse()
+// ===========================================================================
+/*
+gboolean
+GcmdGtkFoldview::Model::iter_collapse(
+ GtkTreeIter * _iter)
+{
+ gint n = 0;
+ View::eRowState state = View::eRowStateUnknown;
+ GtkTreePath * gtk_path = NULL;
+ GtkTreeIter iter_dummy = Iter_zero;
+ //.........................................................................
+ //GCMD_INF("iter_remove");
+
+ // get the # of children
+ n = iter_n_children(_iter);
+
+ // get the GtkTreePath
+ gtk_path = GnomeCmdFoldviewTreestore::get_path(treemodel(), _iter);
+ if ( ! gtk_path )
+ return FALSE;
+
+ // get the view state of the parent
+ state = view()->row_state(gtk_path);
+
+ //.........................................................................
+ // iter is sterile : exit
+ if ( n == 0 )
+ goto exit_success;
+
+
+ //.........................................................................
+ // iter is fertile, and is expanded
+ if ( state == View::eRowStateExpanded )
+ {
+ // It is a hack ! Let GtkTreeView update its cache by collapsing !
+ // We dont have to manually delete each row and signals on them !
+ if ( ! view()->row_collapse(gtk_path) ) // __GWR__HACK__
+ {
+ GCMD_ERR("Model::iter_collapse():iter could not be collapsed");
+ goto exit_failure;
+ }
+ // We dont return here, since the iter is in the following state !
+ }
+
+ //.........................................................................
+ // iter is fertile, and is collapsed. Silently remove all children.
+ iter_collapsed_remove_children(_iter);
+
+ iter_dummy_child_add(_iter, &iter_dummy);
+
+exit_success:
+ gtk_tree_path_free(gtk_path);
+ return TRUE;
+
+exit_failure:
+ gtk_tree_path_free(gtk_path);
+ return FALSE;
+}
+*/
+
+// ===========================================================================
+// Add a File as a child of an iter, if the file match
+// criterias
+// ===========================================================================
+/*
+gboolean
+GcmdGtkFoldview::Model::iter_files_add_file(
+ GtkTreeIter * _iter_parent,
+ FoldviewFile * _file,
+ gboolean _check_for_doubloon,
+ gboolean _replace_first_child)
+{
+ gchar * utf8_collate_key_file = NULL;
+ GtkTreeIter iter_child = Iter_zero;
+ Row * row_parent = NULL;
+ Row * row_child = NULL;
+ //.........................................................................
+ g_return_val_if_fail( _iter_parent, FALSE );
+ g_return_val_if_fail( _file, FALSE );
+
+ // filter
+ if ( ! iter_files_file_filter(_file) )
+ return FALSE;
+
+ // doubloons
+ if ( _check_for_doubloon )
+ {
+ utf8_collate_key_file = collate_key_new_from_utf8(_file->name_utf8());
+
+ if ( treestore()->ext_match_child_collate_key(_iter_parent, &iter_child, eCollateKeyRaw, utf8_collate_key_file) )
+ {
+ g_free(utf8_collate_key_file);
+ return FALSE;
+ }
+
+ g_free(utf8_collate_key_file);
+ }
+
+ row_parent = iter_get_treerow(_iter_parent);
+ if ( ! row_parent )
+ return NULL;
+
+ // build the TreeRow
+ row_child = new Row(eRowStd, row_parent, _file);
+
+ // add it !
+ if ( _replace_first_child && ( GnomeCmdFoldviewTreestore::iter_n_children(treemodel(), _iter_parent) == 1 ) )
+ iter_dummy_child_replace(_iter_parent, &iter_child, row_child);
+ else
+ iter_add_child(_iter_parent, &iter_child, row_child);
+
+ return TRUE;
+}
+*/
+
+// ===========================================================================
+// Add files from a GList of Files as childs of iter
+// ===========================================================================
+/*
+void
+GcmdGtkFoldview::Model::iter_files_add_files(
+ GtkTreeIter * _iter_parent,
+ GList * _list,
+ gboolean _check_for_doubloon,
+ gboolean _replace_dummy)
+{
+ GList * list = NULL;
+ FoldviewFile * file = NULL;
+
+ GtkTreeIter iter_child = GcmdGtkFoldview::Model::Iter_zero;
+ //.........................................................................
+
+ // add first children
+ list = g_list_first(_list);
+ g_return_if_fail(list);
+
+ file = (File*)list->data;
+ FILES_INF("Model::ifafs:%s", file->name_utf8());
+ iter_files_add_file(_iter_parent, file, _check_for_doubloon, _replace_dummy);
+ list = g_list_next(list);
+
+ // add other children
+ while ( list )
+ {
+ file = (File*)list->data;
+
+ FILES_INF("Model::ifafs:%s", file->name_utf8());
+ iter_files_add_file(_iter_parent, file, _check_for_doubloon, FALSE);
+
+ list = g_list_next(list);
+ }
+}
+*/
+
+
+ // ===================================================================
+ // Refresh
+ // ===================================================================
+/*
+ private:
+ struct Refresh
+ {
+
+ private:
+ TreestorePath * d_path;
+ Uri d_uri;
+
+ public:
+ void* operator new (size_t size);
+ void operator delete (void *p);
+ Refresh(TreestorePath*, const gchar* = NULL);
+ ~Refresh();
+
+ public:
+ const Uri uri() { return d_uri; }
+ TreestorePath * path() { return d_path; }
+
+ };
+ //.....................................................................
+ struct RefreshList
+ {
+ private:
+ Model * a_model;
+ GList * d_list;
+ GList * a_current;
+
+ public:
+ void* operator new (size_t size);
+ void operator delete (void *p);
+ RefreshList(Model*, GList*);
+ ~RefreshList();
+
+ public:
+ Model * model();
+ void add(Refresh*);
+ void reset();
+ Refresh * getplusplus();
+ };
+*/
+//=============================================================================
+// Model::iter_refresh_store_R()
+//=============================================================================
+//
+// Recursive call for getting all subiters of an iter in the form
+// of a GList of Model::Refresh
+//
+/*
+GList*
+GcmdGtkFoldview::Model::iter_refresh_store_R(
+ GList * _list,
+ GtkTreeIter * _iter_parent)
+{
+ TreestorePath * path = NULL;
+ Refresh * refresh = NULL;
+ GtkTreeIter iter_child = Iter_zero;
+
+ GList * l = NULL;
+
+ Row * row = NULL;
+ //.........................................................................
+ g_return_val_if_fail( _iter_parent, NULL );
+
+ l = _list;
+
+ //
+ // add a new Refresh to the list
+ //
+ path = treestore()->ext_path_from_iter(_iter_parent);
+
+ // treerow
+ row = iter_get_treerow(_iter_parent);
+ if ( ! row )
+ {
+ REFRESH_ERR("Model::iter_refresh_store_R():Could not get treerow for iter");
+ delete path;
+ return l;
+ }
+
+ if ( ! row->is_dummy() )
+ {
+
+ refresh = new Refresh(path, row->uri_utf8());
+ l = g_list_append(l, (gpointer)refresh);
+
+ //
+ // children
+ //
+
+ // no children, return
+ if ( ! GnomeCmdFoldviewTreestore::iter_children(treemodel(), &iter_child, _iter_parent) )
+ return l;
+
+ do
+ {
+ l = iter_refresh_store_R(l, &iter_child);
+ }
+ while ( GnomeCmdFoldviewTreestore::iter_next(treemodel(), &iter_child));
+
+ }
+
+ return l;
+}
+*/
+
+
+// ===========================================================================
+// Iter_refresh_launch_async_ops()
+// ===========================================================================
+//
+// Launch the async ops at regular interval, until all async ops have been
+// launched.
+//
+// The RefreshList has to be reseted before the first call, by the caller.
+/*
+gboolean
+GcmdGtkFoldview::Model::Iter_refresh_launch_async_ops(
+ gpointer _data)
+{
+ RefreshList * rlist = NULL;
+ Model * THIS = NULL;
+
+ Refresh * refresh = NULL;
+ AsyncCallerData * acd = NULL;
+
+ gint j = 0;
+ //.........................................................................
+ rlist = (RefreshList*)_data;
+ THIS = rlist->model();
+
+loop:
+ // continue from we stopped
+ refresh = rlist->getplusplus();
+
+ // end of list reached, aborting g_timeout by returning FALSE
+ if ( ! refresh )
+ {
+ // delete the list, mallocated datas are destroyed in callbacks
+ delete rlist;
+ return FALSE;
+ }
+
+ REFRESH_INF("Model::Iter_refresh_launch_async_ops():Launching async ops on %s", refresh->uri());
+
+ acd = new AsyncCallerData(rlist->model(), Iter_refresh_children_callback, refresh->path()->dup());
+
+ _USE_GIO_ ?
+ THIS->a_GIO.iter_enumerate_children (acd, refresh->uri()) :
+ THIS->a_GnomeVFS.iter_enumerate_children(acd, refresh->uri()) ;
+
+ // refresh is not useful anymore
+ delete refresh;
+
+ // cycle limit reached, return
+ if ( ( ++j ) == GCMDGTKFOLDVIEW_REFRESH_CYCLE_N_ITEMS )
+ return TRUE;
+
+ goto loop;
+}
+*/
+
+/*
+void
+GcmdGtkFoldview::Model::iter_refresh_children(
+ GtkTreeIter * _iter)
+{
+ GList * list = NULL;
+ GList * temp = NULL;
+ RefreshList * rlist = NULL;
+ //.........................................................................
+ // get all iters in a list
+ //
+ list = iter_refresh_store_R(list, _iter);
+
+ // tree is empty !
+ if ( !list )
+ {
+ REFRESH_INF("Model::iter_refresh():called on an empty tree");
+ return;
+ }
+
+ list = g_list_first(list);
+
+ // dump !
+ REFRESH_INF("Model::iter_refresh():dumping items");
+ temp = list;
+ do
+ {
+ REFRESH_INF(" | %s", ((Refresh*)temp->data)->uri() );
+ temp = g_list_next(temp);
+ }
+ while ( temp != NULL );
+
+ //.........................................................................
+ // launch async ops - we use a timer, thus gcmd can 'digest' the list
+ //
+
+ // RefreshList
+ rlist = new RefreshList(this, list);
+ rlist->reset();
+
+ // guint g_timeout_add(
+ // guint interval,
+ // GSourceFunc function,
+ // gpointer data);
+ //
+ // interval : the time between calls to the function, in milliseconds (1/1000ths of a second)
+ // function : function to call
+ // data : data to pass to function
+ // Returns : the ID (greater than 0) of the event source.
+ //
+ // gboolean (*GSourceFunc) (gpointer data);
+
+ // launch the timer
+ g_timeout_add(
+ GCMDGTKFOLDVIEW_REFRESH_CYCLE_PERIOD_MS,
+ Iter_refresh_launch_async_ops,
+ (gpointer)rlist);
+}
+*/
+
+/*
+// ===========================================================================
+// Iter_monitor_callback_acc()
+// ===========================================================================
+//
+// Monitoring callback : directory access changed
+//
+void
+GcmdGtkFoldview::Model::Iter_monitor_callback_acc(
+ MonitorData * _md,
+ eFileAccess _access,
+ const gchar * _name_debug)
+{
+ GcmdGtkFoldview::Model * THIS = NULL;
+ GnomeCmdFoldviewTreestore * treestore = NULL;
+ GtkTreeModel * treemodel = NULL;
+ Row * row = NULL;
+
+ GtkTreeIter iter = Iter_zero;
+ gboolean was_readable = FALSE;
+ gboolean is_readable = FALSE;
+ //.........................................................................
+ MONITOR_INF("Model::Iter_monitor_callback_acc()");
+
+ THIS = _md->a_model;
+ row = _md->a_row;
+
+ treestore = THIS->treestore();
+ treemodel = THIS->treemodel();
+
+ gdk_threads_enter(); // _GDK_LOCK_
+
+ //.........................................................................
+ //
+ // Step #1 : Get iter + data
+ //
+ if ( ! treestore->ext_iter_from_path(row->path(), &iter) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_acc():could not retrieve iter from Path [%s]", _name_debug);
+ goto exit;
+ }
+
+ if ( ! treestore->ext_get_data(&iter, (GnomeCmdFoldviewTreestore::DataInterface**)&row) )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_acc():could not retrieve parent iter's TreeRow [%s]", _name_debug);
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #2 : verification that file access has changed
+ //
+ if ( row->access() == _access )
+ {
+ MONITOR_ERR("Model::Iter_monitor_callback_child_acc():access didnt change [%s]", row->utf8_name_display());
+ goto exit;
+ }
+
+ //.........................................................................
+ //
+ // Step #3 : convenience booleans
+ //
+ was_readable = row->readable();
+ is_readable = Access_readable(_access);
+
+ //.........................................................................
+ //
+ // Step #4 : stuff
+ //
+
+ // 4.1 readable -> NOT readable
+ if ( was_readable && ( !is_readable ) )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_acc():readable -> NOT readable [%s]", row->utf8_name_display());
+ }
+
+ // 4.2 NOT readable -> readable
+ if ( ( !was_readable ) && is_readable )
+ {
+ MONITOR_INF("Model::Iter_monitor_callback_child_acc():NOT readable -> readable [%s]", row->utf8_name_display());
+ }
+
+ // 4.3 other changes, exit
+
+exit:
+ gdk_threads_leave(); // _GDK_LOCK_
+}
+*/
+
+/*
+// ===========================================================================
+// iter_readable_set()
+// ===========================================================================
+//
+// Set an iter readable
+// ( do logic verifications & launch check_if_empty )
+//
+gboolean
+GcmdGtkFoldview::Model::iter_readable_set(
+ GtkTreeIter * _iter)
+{
+ IterInfo info;
+ //.........................................................................
+ //GCMD_INF("iter_readable_set");
+ g_return_val_if_fail( _iter, FALSE );
+
+ //.........................................................................
+ // Logic verifications
+ //
+
+ info.gather(this, _iter, IterInfo::eExp | IterInfo::eChildren);
+ // iter must be collapsed, and have no child
+ if ( ! info.collapsed() || info.children() )
+ {
+ GCMD_ERR("Model::iter_readable_set():Test failed");
+ return FALSE;
+ }
+
+ // iter already readable : return
+ if ( info.row()->readable() )
+ {
+ GCMD_WNG("Model::iter_readable_set():already readable [%s]", info.row()->utf8_name_display());
+ return TRUE;
+ }
+
+ //.........................................................................
+ // All is ok
+
+ // change data
+ info.row()->readable(TRUE);
+
+ // inform treview that row has changed
+ treestore()->ext_data_changed(_iter);
+
+ // launch check if empty
+ iter_check_if_empty(_iter);
+
+ return TRUE;
+}
+*/
+
+/*
+// ===========================================================================
+// iter_readable_unset()
+// ===========================================================================
+//
+// Set an iter not-readable
+// ( do logic verifications & launch check_if_empty )
+//
+gboolean
+GcmdGtkFoldview::Model::iter_readable_unset(
+ GtkTreeIter * _iter)
+{
+ Row * row = NULL;
+ gint n = 0;
+ GtkTreePath * gtk_path = NULL;
+ //.........................................................................
+ //GCMD_INF("iter_readable_unset");
+ g_return_val_if_fail( _iter, FALSE );
+
+ //.........................................................................
+ // Logic verifications
+ // Cant use iter_test, because we need the GtkTreePath
+ //
+
+ // Row
+ if ( ! iter_get_treerow(_iter, &row) )
+ {
+ GCMD_ERR("Model::iter_readable_unset():could not get Row");
+ return FALSE;
+ }
+
+ // Already not-readable
+ if ( ! row->readable() )
+ {
+ GCMD_WNG("Model::iter_readable_unset():already not-readable [%s]", row->utf8_name_display());
+ return TRUE;
+ }
+
+ // get the # of children
+ n = iter_n_children(_iter);
+
+ // get the GtkTreePath
+ gtk_path = GnomeCmdFoldviewTreestore::get_path(treemodel(), _iter);
+ if ( ! gtk_path )
+ {
+ GCMD_ERR("Model::iter_readable_unset():could not get GtkTreePath [%s]", row->utf8_name_display());
+ return FALSE;
+ }
+
+ //.........................................................................
+ // if no children, unset directly
+ if ( n == 0 )
+ goto iter_sterile;
+
+ //.........................................................................
+ // iter is fertile, and expanded : collapse it
+ if ( iter_is_expanded(_iter) )
+ {
+ // It is a hack ! Let GtkTreeView update its cache by collapsing !
+ // We dont have to manually delete each row and signals on them !
+ if ( ! view()->row_collapse(gtk_path) ) // __GWR__HACK__
+ {
+ GCMD_ERR("Model::iter_readable_unset():iter could not be collapsed");
+ goto exit_failure;
+ }
+
+ // We dont return here, since the iter is in the following state !
+ }
+
+ //.........................................................................
+ // iter is fertile, and collapsed : silently remove children
+ iter_collapsed_remove_children(_iter);
+
+ //.........................................................................
+ // Unset the sterile iter
+iter_sterile:
+
+ // change data
+ row->readable(FALSE);
+
+ // inform treview that row has changed
+ treestore()->ext_data_changed(_iter);
+
+//exit_success:
+ gtk_tree_path_free(gtk_path);
+ return TRUE;
+
+exit_failure:
+ gtk_tree_path_free(gtk_path);
+ return FALSE;
+}
+*/
+
+
diff --git a/src/foldview/gnome-cmd-foldview-logger.cc b/src/foldview/gnome-cmd-foldview-logger.cc
new file mode 100644
index 0000000..cf669fb
--- /dev/null
+++ b/src/foldview/gnome-cmd-foldview-logger.cc
@@ -0,0 +1,159 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "gnome-cmd-foldview-logger.h"
+
+#include <stdio.h>
+
+// ****************************************************************************
+//
+// Static
+//
+// ****************************************************************************
+Logger::LogFunction Logger::Log_function[6] =
+ {
+ &Logger::Inf,
+ &Logger::Wng,
+ &Logger::Err,
+ &Logger::Tki,
+ &Logger::Tkw,
+ &Logger::Tke
+ };
+
+static char s1 [1024];
+static char s2 [1024];
+
+/*
+ Prompt color format : <ESC>[{attr};{fg};{bg}m
+
+ {attr} needs to be one of the following :
+
+ 0 Reset All Attributes (return to normal mode)
+ 1 Bright (usually turns on BOLD)
+ 2 Dim
+ 3 Underline
+ 5 Blink
+ 7 Reverse
+ 8 Hidden
+
+ {fg} needs to be one of the following :
+
+ 30 Black
+ 31 Red
+ 32 Green
+ 33 Yellow
+ 34 Blue
+ 35 Magenta
+ 36 Cyan
+ 37 White
+
+ {bg} needs to be one of the following:
+
+ 40 Black
+ 41 Red
+ 42 Green
+ 43 Yellow
+ 44 Blue
+ 45 Magenta
+ 46 Cyan
+ 47 White
+
+*/
+
+void Logger::Inf(const char* _header, const char* _format, ...)
+{
+ va_list val;
+ //.........................................................................
+ va_start(val, _format); vsprintf(s1, _format, val); va_end(val);
+ sprintf(s2, "\033[0;32mINF:\033[0m%s:%s", _header, s1);
+ printf("%s\n", s2);
+};
+void Logger::Wng(const char* _header, const char* _format, ...)
+{
+ va_list val;
+ //.........................................................................
+ va_start(val, _format); vsprintf(s1, _format, val); va_end(val);
+ sprintf(s2, "\033[0;35mWNG:\033[0m%s:%s", _header, s1);
+ printf("%s\n", s2);
+};
+void Logger::Err(const char* _header, const char* _format, ...)
+{
+ va_list val;
+ //.........................................................................
+ va_start(val, _format); vsprintf(s1, _format, val); va_end(val);
+ sprintf(s2, "\033[0;31mERR:\033[0m%s:%s", _header, s1);
+ printf("%s\n", s2);
+};
+
+void Logger::Tki(const char* _header, const char* _format, ...)
+{
+ va_list val;
+ //.........................................................................
+ va_start(val, _format); vsprintf(s1, _format, val); va_end(val);
+ sprintf(s2, "\033[0;33mTKI:\033[0m%s:%s", _header, s1);
+ printf("%s\n", s2);
+};
+void Logger::Tkw(const char* _header, const char* _format, ...)
+{
+ va_list val;
+ //.........................................................................
+ va_start(val, _format); vsprintf(s1, _format, val); va_end(val);
+ sprintf(s2, "\033[1;33mTKW:\033[0m%s:%s", _header, s1);
+ printf("%s\n", s2);
+};
+void Logger::Tke(const char* _header, const char* _format, ...)
+{
+ va_list val;
+ //.........................................................................
+ va_start(val, _format); vsprintf(s1, _format, val); va_end(val);
+ sprintf(s2, "\033[7;33mTKE:\033[0m%s:%s", _header, s1);
+ printf("%s\n", s2);
+};
+
+
+
+
+
+// ****************************************************************************
+//
+// All the rest
+//
+// ****************************************************************************
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-foldview-logger.h b/src/foldview/gnome-cmd-foldview-logger.h
new file mode 100644
index 0000000..56df380
--- /dev/null
+++ b/src/foldview/gnome-cmd-foldview-logger.h
@@ -0,0 +1,194 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GCMDGTKFOLDVIEW_LOGGER_H__
+#define __GCMDGTKFOLDVIEW_LOGGER_H__
+
+#include "gnome-cmd-foldview-utils.h"
+
+#include <glib.h>
+
+// ***************************************************************************
+// Logging
+// ***************************************************************************
+
+// ===========================================================================
+// Logger
+// ===========================================================================
+struct Logger
+{
+ //=========================================================================
+ // Types
+ //=========================================================================
+ public:
+ typedef void (*LogFunction)(const char* _header, const char* _format, ...);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ enum eLogFlavour
+ {
+ eLogInf = 0,
+ eLogWng = 1,
+ eLogErr = 2,
+
+ eLogTki = 3,
+ eLogTkw = 4,
+ eLogTke = 5
+ };
+ //=========================================================================
+ // Structs
+ //=========================================================================
+ private:
+ struct Channel
+ {
+ private:
+ gint a_index;
+ LogFunction a_log_function[6];
+ gchar * d_header;
+
+ public:
+ Channel()
+ {
+ a_index = -1;
+ a_log_function[eLogInf] = &NoLog;
+ a_log_function[eLogWng] = &NoLog;
+ a_log_function[eLogErr] = &NoLog;
+ a_log_function[eLogTki] = &NoLog;
+ a_log_function[eLogTkw] = &NoLog;
+ a_log_function[eLogTke] = &NoLog;
+ d_header = NULL;
+ }
+ ~Channel()
+ {
+ if ( d_header )
+ g_free(d_header);
+ }
+
+ inline void set_header(const gchar* _header)
+ {
+ d_header = g_strdup(_header);
+ }
+ inline const gchar* get_header()
+ {
+ return d_header;
+ }
+ inline LogFunction log_function(eLogFlavour _flavour)
+ {
+ return a_log_function[_flavour];
+ }
+ inline void unmute(eLogFlavour _flavour)
+ {
+ a_log_function[_flavour] = Log_function[_flavour];
+ }
+ inline void mute(eLogFlavour _flavour)
+ {
+ a_log_function[_flavour] = &NoLog;
+ }
+ };
+ //=========================================================================
+ // New, ...
+ //=========================================================================
+ public:
+ Logger(gint _channel_card)
+ {
+ a_channel_card = _channel_card;
+ d_channel = (Channel**)g_try_malloc0( sizeof(Channel*) * _channel_card );
+ }
+ ~Logger()
+ {
+ gint i = 0;
+ //.....................................................................
+ for( i = 0 ; i != channel_card() ; i++ )
+ if ( channel(i) )
+ delete (GcmdStruct<Channel>*)channel(i);
+
+ g_free(d_channel);
+ }
+
+ //=========================================================================
+ // Members
+ //=========================================================================
+ private:
+ static LogFunction Log_function[6];
+
+ gint a_channel_card;
+ Channel ** d_channel;
+ //=========================================================================
+ // Methods
+ //=========================================================================
+ private:
+ static void Inf (const char* _header, const char* _format, ...);
+ static void Wng (const char* _header, const char* _format, ...);
+ static void Err (const char* _header, const char* _format, ...);
+ static void Tki (const char* _header, const char* _format, ...);
+ static void Tkw (const char* _header, const char* _format, ...);
+ static void Tke (const char* _header, const char* _format, ...);
+ static inline void NoLog (const char* _header, const char* _format, ...) {}
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+
+ inline LogFunction log_function(gint _channel, eLogFlavour _flavour)
+ {
+ return channel(_channel)->log_function(_flavour);
+ }
+
+ inline gint channel_card()
+ {
+ return a_channel_card;
+ }
+
+ inline Channel * channel(gint _channel)
+ {
+ return d_channel[_channel];
+ }
+
+ inline const gchar * header(gint _channel)
+ {
+ return channel(_channel)->get_header();
+ }
+
+ inline void channel_mute (gint _channel, eLogFlavour _flavour) { channel(_channel)->mute(_flavour); }
+ inline void channel_unmute (gint _channel, eLogFlavour _flavour) { channel(_channel)->unmute(_flavour); }
+
+ inline gboolean channel_create(gint _channel, const gchar* _header, guint8 _b8)
+ {
+ g_return_val_if_fail( _channel >= 0, FALSE );
+ g_return_val_if_fail( _channel <= channel_card(), FALSE );
+ g_return_val_if_fail( ! channel(_channel), FALSE );
+
+ d_channel[_channel] = GCMD_STRUCT_NEW(Channel);
+ d_channel[_channel]->set_header(_header);
+
+ if ( _b8 & 0x20 ) d_channel[_channel]->unmute(eLogInf);
+ if ( _b8 & 0x10 ) d_channel[_channel]->unmute(eLogWng);
+ if ( _b8 & 0x08 ) d_channel[_channel]->unmute(eLogErr);
+ if ( _b8 & 0x04 ) d_channel[_channel]->unmute(eLogTki);
+ if ( _b8 & 0x02 ) d_channel[_channel]->unmute(eLogTkw);
+ if ( _b8 & 0x01 ) d_channel[_channel]->unmute(eLogTke);
+
+ return TRUE;
+ }
+
+};
+
+
+
+#endif //__GCMDGTKFOLDVIEW_LOGGER_H__
diff --git a/src/foldview/gnome-cmd-foldview-private.h b/src/foldview/gnome-cmd-foldview-private.h
index 0297745..bffbf9d 100644
--- a/src/foldview/gnome-cmd-foldview-private.h
+++ b/src/foldview/gnome-cmd-foldview-private.h
@@ -1,4 +1,10 @@
/*
+ ###########################################################################
+
+ gnome-cmd-foldview-private.h
+
+ ---------------------------------------------------------------------------
+
GNOME Commander - A GNOME based file manager
Copyright (C) 2001-2006 Marcus Bjurman
Copyright (C) 2007-2010 Piotr Eljasiak
@@ -17,882 +23,229 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-#ifndef __GCMDGTKFOLDVIEW_PRIVATE_H__
-#define __GCMDGTKFOLDVIEW_PRIVATE_H__
-
-/******************************************************************************
-
- C++
- Contain variadic macros
-
- ---------------------------------------------------------------------------
- TODO GWR
-
- GcmdFileSelector resize automatically resize the main vertical pane
- ( FILL / EXPAND gtk settings somewhere ) ?
-
- Trivial bug as no item is selectionned on foldview showing
-
- ..................... facultative / later ............................
-
- sync file_list when it is not active ( in a hidden tab )
-
- Bookmarks
-
- Notification from filesystem ( very hard to do, we're really going
- multithread ) -> gdk_threads_enter will be enough I think
-
-DONE init / destroy cleanup : g_object_ref on hided widgets
-
-DONE memory leaks hunt
-
-DONE memory leak : gnome-cmd-foldview-control.cc::814 forgot g_free(str)
-
-DONE memory leak : root node
-
-DONE memory leak : GcmdGtkFldview::Model::destroy implemented
-
-DONE memory leak : gvfs quickstack
-
-DONE correct ESC[30m for terminal after each gwr_print
-
- .......................................................................
-COMMIT 05bb32e2cfd8eb56bf64e93bc1785ce52f6a100d
-
-DONE symlinks icons show little white pixel when selected its ugly
- but gcmd's too
-
-DONE foldview correct position on show / hide ( cmdline, buttonbar, ... )
-
-DONE (Finally) gcmd crashes when opening access-denied folder from treeview
- in tab, after showing an alert
-
-DONE Going crazy with correct theming of treeview with selectionned items,
- focus between widgets,...
-
-DONE combo connections at startup
-
-DONE gtk_widget_set_sensitive on non-full-functional items of context menu
-
-DONE Check index_ff on qstack_push()
-
-DONE ? mutex on handles : no, gvfs_async calls are queued
- and since I use gdk_threads_enter/leave, there is no more
- concurrency between gtk & gvfs
-
-DONE why GVFS_qstack_ff / GVFS_qstack_size is always n-2 / n ??? should be n / n
- -> because t' affiches ff _avant_ update et qsize au lieu de qsize - 1,
- stupid, ça fait un décalage de 2
-
-DONE Comments cleanup
-
-DONE Private logging for gvfs ops
-
-DONE Cancel all async ops
-
-DONE Big Bug in checking type of GnomeVFSFileInfo : GNOME_VFS_FILE_TYPE_...
- are distinct values - it is not a bitfield, triple fuck, spended time
- on that
-
- ---------------------------------------------------------------------------
- TODO EPIOTR
-
-DONE in src/gnome-cmd-foldview.h:
- extern gboolean gnome_cmd_foldview_set_root_1(gchar *text);
- ...
- extern GtkWidget *GcmdWidget();
- 'extern' is superfluous here, please remove it
-
-DONE epiotr.10.07.16.gcmd-foldview
-DONE ua
-
- epiotr.10.07.22.kill-warnings
-DONE epiotr.10.07.22.gtk_object_ref,unref
-
-DONE epiotr.10.07.24.000? struct-gvfs_async_caller_data
-DONE epiotr.10.07.24.000? struct-gvfs-async
-DONE epiotr.10.07.24.000? struct-gvfs-async-load-subdirs
-DONE epiotr.10.07.24.000? struct-gvfs-async-load-subdirs-subdirs
-
-
-DONE * I've moved view_treeview() to gnome-cmd-user-actions.cc. I'm
- sending you a patch for that.
-
-DONE * after opening foldview, cmdline is moved from bottom to top -
- that requires fixing
-
- * foldview should respect global settings for case sensitive
- sorting (gnome_cmd_data.case_sens_sort) and showing hidden dirs
- (gnome_cmd_data.filter_settings.hidden)
-
- * when folview is opened for the first time, it should initially
- expand to the current dir of active pane:
- main_win->fs(ACTIVE)->get_directory()
-
-
-
-*******************************************************************************
- HELPERS LOGGERS
- ===============
-
-* gnome-cmd-file.h
-gint gnome_cmd_file_get_ref_count(GnomeCmdFile* file);
-void gnome_cmd_file_log(gchar *str, GnomeCmdFile *File);
-gint gnome_cmd_file_get_ref_count(GnomeCmdFile* file)
-{
- return file->priv->ref_cnt;
-}
-
-* gnome-cmd-file.cc
-void gnome_cmd_file_log(gchar *str, GnomeCmdFile *file)
-{
- gchar temp[1024];
-
- sprintf(temp, "fil:[0x%08x %3s][%03i-%03i] [h:xxxxxxxx] [mu:xxx] [%s] [%s]\n",
- file,
- g_object_is_floating(file) ? "FLO" : "REF",
- ((GInitiallyUnowned*)file)->ref_count,
- gnome_cmd_file_get_ref_count(file),
- GNOME_CMD_FILE_INFO(file)->uri != NULL ? GNOME_CMD_FILE_INFO(file)->uri->text : "no uri",
- str);
-
- printf(temp);
-}
-
-* gnome-cmd-dir.h
-void gnome_cmd_dir_log(const gchar *str, GnomeCmdDir *dir);
-
-* gnome-cmd-dir.cc
-void gnome_cmd_dir_log(const gchar *str, GnomeCmdDir *dir)
-{
- gchar temp[1024];
-
- if ( ! dir )
- {
- sprintf(temp, "dir:NULL [%s]\n", str);
- return;
- }
-
- sprintf(temp, "dir:[0x%08x %3s][%03i-%03i] [h:0x%08x] [mu:xxx] [%s] [%s]\n",
- dir,
- g_object_is_floating(dir) ? "FLO" : "REF",
- ((GInitiallyUnowned*)dir)->ref_count,
- gnome_cmd_file_get_ref_count(GNOME_CMD_FILE(dir)),
- gnome_cmd_dir_get_handle(dir),
- //dir->priv->monitor_users,
- GNOME_CMD_FILE_INFO(dir)->uri != NULL ? GNOME_CMD_FILE_INFO(dir)->uri->text : "no uri",
- str);
-
- printf(temp);
-}
-
-* gnome-cmd-file-list.cc
-static void on_dir_list_failed (GnomeCmdDir *dir, GnomeVFSResult result, GnomeCmdFileList *fl)
-{
- gnome_cmd_dir_log("on_dir_list_failed 00", dir);
-
- DEBUG('l', "on_dir_list_failed\n");
-
- if (result != GNOME_VFS_OK)
- gnome_cmd_show_message (NULL, _("Directory listing failed."), gnome_vfs_result_to_string (result));
-
- gnome_cmd_dir_log("on_dir_list_failed 01", dir);
-
- g_signal_handlers_disconnect_matched (fl->cwd, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, fl);
- gnome_cmd_dir_log("on_dir_list_failed 01-1", dir);
- fl->connected_dir = NULL;
- gnome_cmd_dir_log("on_dir_list_failed 01-2", dir);
- gnome_cmd_dir_unref (fl->cwd);
- gnome_cmd_dir_log("on_dir_list_failed 01-3", dir);
- set_cursor_default_for_widget (*fl);
- gnome_cmd_dir_log("on_dir_list_failed 01-4", dir);
- gtk_widget_set_sensitive (*fl, TRUE);
+ ---------------------------------------------------------------------------
- gnome_cmd_dir_log("on_dir_list_failed 02", dir);
+ Main header for GcmdGtkFoldview GObject
- if (fl->lwd && fl->con == gnome_cmd_dir_get_connection (fl->lwd))
- {
- fl->cwd = fl->lwd;
- g_signal_connect (fl->cwd, "list-ok", G_CALLBACK (on_dir_list_ok), fl);
- g_signal_connect (fl->cwd, "list-failed", G_CALLBACK (on_dir_list_failed), fl);
- fl->lwd = NULL;
- }
- else
- g_timeout_add (1, (GSourceFunc) set_home_connection, fl);
-}
-
-void GnomeCmdFileList::set_connection (GnomeCmdCon *new_con, GnomeCmdDir *start_dir)
-{
- g_return_if_fail (GNOME_CMD_IS_CON (new_con));
-
- if (con==new_con)
- {
- //if (!gnome_cmd_con_should_remember_dir (new_con)) //original code buggy // __GWR__MARK__
- if ( gnome_cmd_con_should_remember_dir (new_con))
- set_directory (gnome_cmd_con_get_default_dir (new_con));
- else
- if (start_dir)
- set_directory (start_dir);
- return;
- }
- ...
-
-void GnomeCmdFileList::set_directory(GnomeCmdDir *dir)
-{
- g_return_if_fail (GNOME_CMD_IS_DIR (dir));
-
- gnome_cmd_dir_log("GnomeCmdFileList::set_directory 00", dir);
-
- if (cwd==dir)
- return;
-
- if (realized && dir->state!=DIR_STATE_LISTED)
- {
- gtk_widget_set_sensitive (*this, FALSE);
- set_cursor_busy_for_widget (*this);
- }
-
- gnome_cmd_dir_ref (dir);
-
- if (lwd && lwd!=dir)
- gnome_cmd_dir_unref (lwd);
-
- if (cwd)
- {
- gnome_cmd_dir_cancel_monitoring (cwd);
- lwd = cwd;
- g_signal_handlers_disconnect_matched (lwd, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, this);
- cwd->voffset = gnome_cmd_clist_get_voffset (*this);
- }
-
- cwd = dir;
+ ###########################################################################
+*/
+#ifndef __GCMDGTKFOLDVIEW_PRIVATE_H__
+#define __GCMDGTKFOLDVIEW_PRIVATE_H__
- switch (dir->state)
- {
- case DIR_STATE_EMPTY:
- g_signal_connect (dir, "list-ok", G_CALLBACK (on_dir_list_ok), this);
- g_signal_connect (dir, "list-failed", G_CALLBACK (on_dir_list_failed), this);
- gnome_cmd_dir_log("GnomeCmdFileList::set_directory 01", dir);
- gnome_cmd_dir_list_files (dir, gnome_cmd_con_needs_list_visprog (con));
- gnome_cmd_dir_log("GnomeCmdFileList::set_directory 02", dir);
- break;
-
- case DIR_STATE_LISTING:
- case DIR_STATE_CANCELING:
- g_signal_connect (dir, "list-ok", G_CALLBACK (on_dir_list_ok), this);
- g_signal_connect (dir, "list-failed", G_CALLBACK (on_dir_list_failed), this);
- break;
-
- case DIR_STATE_LISTED:
- on_dir_list_ok (dir, NULL, this);
- gnome_cmd_dir_start_monitoring (dir);
- break;
- }
-
- gnome_cmd_dir_log("GnomeCmdFileList::set_directory 03", dir);
-
- // in the previous 'case', dir->state may have been modified. So include
- // this line in the 'case'
- //gnome_cmd_dir_start_monitoring (dir);
-}
-
-
-
-*******************************************************************************
-
- WIDGET HIERARCHY FOR GTK-FOLDVIEW
- =================================
-
- vbox
- |
- con_hbox
- | |
- | +-----------GtkWidget *con_combo ---------- GtkWidget *vol_label;
- |
- |
- dir_indicator
- |
- scrolled window-------- treeview
- |
- GtkWidget *info_label;
-
-
-*******************************************************************************
-
- WIDGET HIERARCHY FOR GNOME-CMD-FILE-SELECTOR
- ============================================
-
- vbox
- |
- GnomeCmdFileSelector
- |
- |
- +--------------------- GnomeCmdFileList
-
-
-*******************************************************************************
-
- GTK+ DRAG & DROP SYNOPSIS
- =========================
-
-
- "drag-begin" SRC
-
- "drag-motion" DST
- |
- |
- +-----------------------+
- | |
- | |
- "drag-drop" "drag-leave" DST
- |
- |
- "drag-data-get" SRC
- |
- |
- "drag-data-received" DST
- |
- |
- "drag-end" SRC
-
-
- + "drag-failed" SRC
- "drag-data-delete" SRC
-
-******************************************************************************/
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtklabel.h>
-
-//*****************************************************************************
-// Defines
-//*****************************************************************************
-
-// undef this if you want foldview to use a GtkTreestore instead
-// of a GnomeCmdFoldviewTreestore
-//#define USE_GTK_TREESTORE
-
-#ifndef USE_GTK_TREESTORE
- #include "gnome-cmd-foldview-treestore.h"
-#endif
-
-//*****************************************************************************
-// Logging
-//*****************************************************************************
-//#define DEBUG_SHOW_INF
-#define DEBUG_SHOW_WNG
-#define DEBUG_SHOW_ERR
-#define DEBUG_SHOW_VFS
-
-void gwr_print(const char* str);
-
-void gwr_inf(const char* fmt, ...);
-void gwr_wng(const char* fmt, ...);
-void gwr_err(const char* fmt, ...);
-
-void gwr_inf_vfs(const char* fmt, ...);
-void gwr_err_vfs(const char* fmt, ...);
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Facilities logging
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-#define ERR_RET(value,...) \
-{ \
- gwr_err(__VA_ARGS__); \
- return value; \
-}
-
-#define ERR_FAIL(...) \
-{ \
- gwr_err(__VA_ARGS__); \
- exit(1); \
-}
-//---------------------------------------------------------------------------
-#define ERR_VFS_RET(value,...) \
-{ \
- if ( sVFSResult != GNOME_VFS_OK ) \
- { \
- gwr_err_vfs(__VA_ARGS__); \
- return value; \
- } \
-}
-
-#define ERR_VFS_FAIL(value,...) \
-{ \
- if ( sVFSResult != GNOME_VFS_OK ) \
- { \
- gwr_err_vfs(__VA_ARGS__); \
- exit(1); \
- } \
-}
-
-//*****************************************************************************
-// GcmdGtkFoldview
-//*****************************************************************************
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+// ...........................................................................
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+// ...........................................................................
+#include "gnome-cmd-includes.h"
+#include "gnome-cmd-con.h"
+// ...........................................................................
+#include "gnome-cmd-foldview-utils.h"
+#include "gnome-cmd-foldview-logger.h"
+#include "gnome-cmd-foldview-quickstack.h"
+#include "gnome-cmd-foldview-treestore.h"
+// ***************************************************************************
+// #define
+// ***************************************************************************
+
+// ===========================================================================
+// #define : GObject
+// ===========================================================================
#define GCMDGTKFOLDVIEW_TYPE (gcmdgtkfoldview_get_type ())
#define GCMDGTKFOLDVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCMDGTKFOLDVIEW_TYPE, GcmdGtkFoldview))
#define GCMDGTKFOLDVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCMDGTKFOLDVIEW_TYPE, GcmdGtkFoldviewClass))
#define IS_GCMDGTKFOLDVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCMDGTKFOLDVIEW_TYPE))
#define IS_GCMDGTKFOLDVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCMDGTKFOLDVIEW_TYPE))
+// ===========================================================================
+// #define : Foldview config
+// ===========================================================================
+#define GCMDGTKFOLDVIEW_ALLOW_MONITORING FALSE
+#define GCMDGTKFOLDVIEW_USE_GIO FALSE
-#ifdef USE_GTK_TREESTORE
- #define __GTS__
-#endif
+#define GCMDGTKFOLDVIEW_GVFS_ITEMS_PER_NOTIFICATION 30
-struct gvfs_async;
-struct gvfs_file;
+#define GCMDGTKFOLDVIEW_REFRESH_CYCLE_N_MESSAGES 10
+#define GCMDGTKFOLDVIEW_REFRESH_CYCLE_PERIOD_MS 200
-struct GcmdGtkFoldview
-{
- //=========================================================================
- // Widgets and gtk inheritance
- //=========================================================================
- GtkVBox vbox;
-
- //=========================================================================
- // Common data, enum, typedefs
- //=========================================================================
- public:
-
- enum eFileAccess
- {
- // these permissions are user-relatives ( the user that launched gcmd )
- eAccessReadOnly = 0 ,
- eAccessReadWrite = 1 ,
- eAccessForbidden = 2 ,
-
- eAccessInit = 0xFE,
- eAccessUnknown = 0xFF
- };
-
- public:
- static eFileAccess Access_from_permissions (GnomeVFSFilePermissions permissions);
-
- //=========================================================================
- // View
- //=========================================================================
- struct View
- {
- // For fixing the moving gutter of the pane
- gulong a_size_request_handle;
- gint a_size_request_width;
-
- // We have a m_parent member because of callbacks, for calling
- // the controller
- private:
- GtkWidget *a_this;
-
- //---------------------------------------------------------------------
- // other widgets ( we are a composite widget )
- //---------------------------------------------------------------------
- private:
- GtkWidget *m_con_hbox;
- GtkWidget *m_con_combo;
- GtkWidget *m_vol_label;
-
- // __GWR__ Unable to reuse the gnome-cmd-dir-indicator since it is
- // crossed with gnome-cmd-file-selector
- GtkWidget m_dir_indicator;
-
- GtkWidget *m_scrolledwindow;
- GtkWidget *m_info_label;
-
- public:
- GcmdGtkFoldview *foldview() { return (GcmdGtkFoldview*)a_this; }
- GtkWidget *connection_combo() { return (m_con_combo); }
-
- //---------------------------------------------------------------------
- // icons
- //---------------------------------------------------------------------
- private:
- GdkPixbuf *m_pixbuf[50];
-
- public:
- enum eIcon
- {
- eIconUnknown ,
-
- eIconDirReadWrite ,
- eIconDirReadOnly ,
- eIconDirForbidden ,
-
- eIconSymlinkToDirReadWrite ,
- eIconSymlinkToDirReadOnly ,
- eIconSymlinkToDirForbidden
- };
-
- private:
- gboolean icons_load();
- void icons_unload();
-
- public:
- GdkPixbuf *pixbuf(eIcon icon) { return m_pixbuf[icon]; }
-
- static eIcon Icon_from_type_permissions (GnomeVFSFileType type, GnomeVFSFilePermissions permissions);
- static eIcon Icon_from_type_access (GnomeVFSFileType type, GcmdGtkFoldview::eFileAccess access);
-
- //---------------------------------------------------------------------
- // connection combo
- //---------------------------------------------------------------------
- public:
- void connection_combo_add_connection(GnomeCmdCon *con);
- void connection_combo_reset();
-
- //---------------------------------------------------------------------
- // gtk treeview ( main view )
- //---------------------------------------------------------------------
- private:
- GtkWidget *m_treeview;
- GtkTreeModel *m_treemodel;
-
- GtkTreeView *treeview() { return GTK_TREE_VIEW (m_treeview); }
-
- public:
- void init_instance(GtkWidget *_this, GtkTreeModel *_treemodel);
- private:
- void raz_pointers();
- gboolean create(GtkWidget *_this, GtkTreeModel *_treemodel);
- void destroy();
-
- private:
- GtkTreeSelection *selection() { return gtk_tree_view_get_selection(treeview()); }
- gint selection_count()
- {
- // Note: gtk_tree_selection_count_selected_rows() does not
- // exist in gtk+-2.0, only in gtk+ >= v2.2 !
- return gtk_tree_selection_count_selected_rows(selection());
- }
-
- //.....................................................................
- static gboolean signal_test_expand_row(GtkTreeView *tree_view,
- GtkTreeIter *iter, GtkTreePath *path, gpointer user_data);
-
- static void signal_row_expanded(GtkTreeView *tree_view,
- GtkTreeIter *iter, GtkTreePath *path, gpointer user_data);
-
- static void signal_row_collapsed(GtkTreeView *tree_view,
- GtkTreeIter *iter, GtkTreePath *path,gpointer user_data);
-
- static gboolean signal_button_press_event(GtkWidget *tree_view,
- GdkEventButton *event, gpointer user_data);
-
- static void signal_drag_begin(GtkWidget *widget,
- GdkDragContext *drag_context, gpointer user_data);
-
- static void signal_size_request(GtkWidget *widget,
- GtkRequisition *requisition,gpointer data);
-
- //---------------------------------------------------------------------
- // contextual menu
- //---------------------------------------------------------------------
- public:
- struct ctx_menu_data
- {
- GcmdGtkFoldview *a_foldview;
- GtkTreePath *d_path_clicked;
- GtkTreePath *d_path_selected;
- guint32 a_time;
- gint a_event_x;
- gint a_event_y;
- guint a_button;
-
- ~ctx_menu_data()
- {
- if ( d_path_selected )
- {
- gtk_tree_path_free(d_path_selected);
- }
- if ( d_path_clicked )
- {
- gtk_tree_path_free(d_path_clicked);
- }
- }
-
- void *operator new(size_t size) { return g_new0(ctx_menu_data, 1); }
- void operator delete(void *p) { g_free(p); }
- };
- public:
- struct ctx_menu_desc
- {
- gboolean a_connect;
- gchar *a_text;
- GCallback a_callback;
- };
- struct ctx_menu_entry
- {
- ctx_menu_desc a_desc;
- GtkWidget *a_widget;
- gulong a_handle;
- };
- struct ctx_menu_section
- {
- gchar *a_title;
- gint a_card;
- ctx_menu_entry a_entry[5];
- };
- struct ctx_menu
- {
- GtkWidget *a_widget;
- gint a_card;
- ctx_menu_section a_section[5];
- };
-
- private:
- gboolean context_menu_pop(ctx_menu_data*);
-
- gboolean click_left_single(ctx_menu_data *ctxdata);
- gboolean click_left_double(ctx_menu_data *ctxdata);
-
- //---------------------------------------------------------------------
- // Theming
- //---------------------------------------------------------------------
- public:
- void update_style();
-
- } view;
- //=========================================================================
- // Model
- //=========================================================================
- struct Model
- {
- public:
- void init_instance();
- void release_objects();
- private:
- void raz_pointers();
- gboolean create();
-
- //---------------------------------------------------------------------
- // divers
- //---------------------------------------------------------------------
- public:
- static GtkTreeIter Iter_zero;
-
- //---------------------------------------------------------------------
- // treestore
- //---------------------------------------------------------------------
-#ifdef __GTS__ // With GtkTreeStore
-
- private:
- GtkTreeStore *m_treestore;
- public:
- GtkTreeStore *treestore() { return m_treestore; }
- GtkTreeModel *treemodel() { return GTK_TREE_MODEL(m_treestore); }
- GtkTreeSortable *treesortable() { return GTK_TREE_SORTABLE(m_treestore);}
-
-#else // With GnomeCmdFoldviewTreestore
-
- private:
- GnomeCmdFoldviewTreestore *m_treestore;
- public:
- GnomeCmdFoldviewTreestore *treestore() { return m_treestore; }
- GtkTreeModel *treemodel() { return GTK_TREE_MODEL(m_treestore); }
- GtkTreeSortable *treesortable() { return GTK_TREE_SORTABLE(m_treestore);}
-
- //
- // Instead of storing boring G_TYPES vars in the store, we can store
- // anything that inherits from GnomeCmdFoldviewTreestore::Data
- // when using GnomeCmdFoldviewTreestore :)
- //
- public:
- struct Rowlike : GnomeCmdFoldviewTreestore::Data
- {
- private:
- gchar *d_utf8_name;
- gchar *d_utf8_collate_key;
- gint a_icon;
- //.................................................................
- public:
- Rowlike(gchar *_utf8_name, gint _icon);
- ~Rowlike();
- //.................................................................
- public:
- const gchar* utf8_collate_key();
- const gchar* utf8_name();
- gint icon();
- };
-
-#endif
-
- // Treemodel methods. These methods use either
- // GtkTreestore or CnomeCmdFoldviewTreestore, depending on the
- // #define __GTS__ above.
-
- //
- // Methods from GtkTreeModelIface
- //
- gboolean get_iter(GtkTreePath *path /*in*/, GtkTreeIter *iter /*out*/);
- gint iter_n_children (GtkTreeIter *parent);
- //
- // Custom methods
- //
- private:
- static gint Compare(GtkTreeModel*, GtkTreeIter*, GtkTreeIter* , gpointer);
- public:
- static GtkTreeIter* Iter_new(GtkTreeIter*);
- static void Iter_del(GtkTreeIter*);
-
- GnomeVFSURI* iter_get_uri_new (GtkTreeIter *iter);
- gchar* iter_get_string_new (GtkTreeIter *iter);
-
- void set_value(GtkTreeIter*, gchar*, gint icon);
-
- void iter_replace_first_child(GtkTreeIter *parent, GtkTreeIter *child, gchar *name, gint icon);
- void iter_replace_dummy_child(GtkTreeIter *parent, GtkTreeIter *child, gchar *name, gint icon);
-
- gboolean iter_add_child (GtkTreeIter* parent /*in*/, GtkTreeIter *child /*out*/, const gchar *name, gint icon);
-
- //gboolean iter_remove(GtkTreeIter *iter);
- void iter_remove_all();
-
- gint iter_remove_children(GtkTreeIter *parent);
-
- //---------------------------------------------------------------------
- // store custom data in gtktreestore !
- //---------------------------------------------------------------------
-
- //---------------------------------------------------------------------
- // root element ( because of samba possibility )
- //---------------------------------------------------------------------
- public:
- struct Root
- {
- GtkTreeIter m_iter;
- GnomeVFSURI *m_uri;
- GnomeVFSFileInfo *m_info; // __GWR_TODO__ gnome_vfs_dup segfault ???
- gboolean set(GnomeVFSURI *uri);
- void unset();
- } root;
-
- //---------------------------------------------------------------------
- // gnome-cmd-connection
- //---------------------------------------------------------------------
- private:
- GnomeCmdCon *m_con;
-
- public:
- void connection(GnomeCmdCon *con) { m_con = con; }
- GnomeCmdCon* connection() { return m_con; }
-
- } model;
-
- //=========================================================================
- // Controller
- //=========================================================================
- public:
- void control_init_instance();
- private:
- void control_raz_pointers();
- gboolean control_create();
- void control_finalize();
- void control_dispose();
-
- //-------------------------------------------------------------------------
- // GObject stuff
- //-------------------------------------------------------------------------
- public:
- static GObjectClass *Control_parent_class;
- public:
- static void Control_gtk_object_destroy (GtkObject*);
- static void Control_g_object_dispose (GObject*);
- static void Control_g_object_finalize (GObject*);
- static void Control_g_object_init (GcmdGtkFoldview *foldview);
-
- gint control_ref_count()
- {
- return ((GInitiallyUnowned*)this)->ref_count;
- }
-
- //-------------------------------------------------------------------------
- // divers
- //-------------------------------------------------------------------------
- private:
- gboolean control_root_uri_set(GnomeVFSURI *uri);
+#define GCMDGTKFOLDVIEW_SORTING_CYCLE_PERIOD_MS 60
- void control_gcmd_file_list_set_connection(GnomeCmdFileList*, GnomeVFSURI*);
+// ===========================================================================
+// some vars
+// ===========================================================================
- void control_connection_combo_update();
-
- //-------------------------------------------------------------------------
- // expand / collapse
- //-------------------------------------------------------------------------
- public:
- void control_iter_collapsed(GtkTreeIter *parent);
-
- private:
- static void control_check_if_empty_callback_1(gvfs_async*);
- void control_check_if_empty_p(GnomeVFSURI *parent_uri, gchar *parent_path);
- public:
- void control_check_if_empty(GtkTreeIter *parent);
+struct GnomeCmdConnectionTreeview;
- private:
- static void control_iter_expand_callback_1(gvfs_async*);
- static void control_iter_expand_callback_2(gvfs_async*);
- void control_iter_expand_p(GnomeVFSURI *parent_uri, gchar *parent_path);
- public:
- void control_iter_expand(GtkTreeIter *parent);
-
- //-------------------------------------------------------------------------
- // context menu actions
- //-------------------------------------------------------------------------
- private:
- void control_set_active_tab (GtkTreePath *path);
- void control_open_new_tab (GtkTreePath *path);
- void control_set_new_root (GcmdGtkFoldview::View::ctx_menu_data*);
- public:
- static void Control_set_active_tab (GtkMenuItem*, View::ctx_menu_data*);
- static void Control_open_new_tab (GtkMenuItem*, View::ctx_menu_data*);
- static void Control_set_new_root (GtkMenuItem*, View::ctx_menu_data*);
+// ###########################################################################
+//
+// GcmdGtkFoldview
+//
+// ###########################################################################
+struct GcmdGtkFoldview
+{
+ // ***********************************************************************
+ // * *
+ // * GObject stuff *
+ // * *
+ // ***********************************************************************
+ public:
+ GtkVBox vbox;
+ static GObjectClass * Parent_class;
+ // ======================================================================
+ static void G_object_init (GcmdGtkFoldview *foldview);
+ static void Gtk_object_destroy (GtkObject*);
+ static void G_object_dispose (GObject*);
+ static void G_object_finalize (GObject*);
+
+ inline gint ref_count()
+ {
+ return ((GInitiallyUnowned*)this)->ref_count;
+ }
+ // ***********************************************************************
+ // * *
+ // * Enums, ... *
+ // * *
+ // ***********************************************************************
+ enum eIcon
+ {
+ eIconGtkAdd = 0,
+ eIconCard = 1
+ };
+ // ***********************************************************************
+ // * *
+ // * Structs *
+ // * *
+ // ***********************************************************************
+
+ // =======================================================================
+ // HeadBand
+ // =======================================================================
+ private:
+ struct HeadBand
+ {
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ GtkWidget * d_hbox_main;
+ GtkWidget * d_button_add;
+ GtkWidget * d_con_combo;
+ GtkWidget * d_alignement_padder;
+ GtkWidget * d_button_up;
+ GtkWidget * d_arrow_up;
+ GtkWidget * d_button_down;
+ GtkWidget * d_arrow_down;
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ void add_connection(GnomeCmdCon *con);
+ //.................................................................
+ public:
+ inline GtkWidget * widget() { return d_hbox_main; }
+
+ void show();
+ void hide();
+ void update_style();
+
+ gboolean can_add_that_connection(GnomeCmdCon*);
+ void update_connections();
+ void reset_connections();
+ GnomeCmdCon * get_selected_connection();
+
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ void * operator new (size_t);
+ void operator delete (void*);
+
+ public:
+ HeadBand(GcmdGtkFoldview*);
+ ~HeadBand();
+ };
+
+ // ***********************************************************************
+ // * *
+ // * Members *
+ // * *
+ // ***********************************************************************
+ private:
+ static GdkPixbuf * s_gdk_pixbuf[eIconCard];
+ static gboolean s_gdk_pixbuf_loaded;
+
+ GtkWidget * d_scrolled_window;
+ GtkWidget * d_vbox_sw;
+ GcmdStruct<HeadBand> * d_headband;
+
+ GList * d_list_widget;
+ guint a_list_widget_card;
+
+ // =======================================================================
+ // divers
+ // =======================================================================
+ void control_gcmd_file_list_set_connection(GnomeCmdFileList*, GnomeVFSURI*);
+ void control_connection_combo_update();
- private:
- enum eSyncState
- {
- SYNC_Y_LIST_Y,
- SYNC_Y_LIST_N,
- SYNC_N_LIST_Y,
- SYNC_N_LIST_N
- };
- eSyncState control_sync_check ();
- private:
- void control_sync_treeview (GcmdGtkFoldview::View::ctx_menu_data*);
- void control_unsync_treeview ();
- void control_sync_update (GcmdGtkFoldview::View::ctx_menu_data*);
- public:
- static void Control_sync_treeview (GtkMenuItem*, View::ctx_menu_data*);
- static void Control_unsync_treeview (GtkMenuItem*, View::ctx_menu_data*);
- static void Control_sync_update (GtkMenuItem*, View::ctx_menu_data*);
- private:
- GnomeCmdFileList *a_synced_list;
- gboolean a_synced;
+ // ***********************************************************************
+ // * *
+ // * Methods *
+ // * *
+ // ***********************************************************************
+ // =======================================================================
+ // Instance init / destroy
+ // =======================================================================
private:
- static View::ctx_menu s_context_menu;
-
- public:
- void control_context_menu_populate_add_separator(GtkWidget *widget);
- void control_context_menu_populate_add_section(GtkWidget *widget, gint i, View::ctx_menu_data *ctxdata);
-
- //=========================================================================
- // Interface
- //=========================================================================
- public:
- gboolean root_uri_set_1(gchar *text);
- gboolean root_uri_set_2(GnomeVFSURI *uri);
+ void init_instance();
+ void raz_pointers();
+ void dispose();
+ void finalize();
+
+ // =======================================================================
+ // Accessors
+ // =======================================================================
+ private:
+ inline HeadBand * headband() { return d_headband; }
+
+ // =======================================================================
+ // Icons
+ // =======================================================================
+ private:
+ static gboolean Pixbuf_load(GcmdGtkFoldview::eIcon, const gchar*);
+ static gboolean Pixbuf_load_all();
+ static void Pixbuf_unload_all();
+
+ // =======================================================================
+ // Widgets signals
+ // =======================================================================
+ public:
+ static void Signal_button_add_clicked (GtkButton*, gpointer);
+ static void Signal_button_up_clicked (GtkButton*, gpointer);
+ static void Signal_button_down_clicked (GtkButton*, gpointer);
+
+ // =======================================================================
+ // Treeviews
+ // =======================================================================
+ void treeview_add(GnomeCmdCon*);
+ void treeview_del(GnomeCmdConnectionTreeview*);
+ void treeview_set_packing_expansion(GnomeCmdConnectionTreeview*, gboolean);
};
GType gcmdgtkfoldview_get_type ();
GtkWidget* gcmdgtkfoldview_new ();
-void gcmdgtkfoldview_clear (GcmdGtkFoldview *foldview);
+//void gcmdgtkfoldview_clear (GcmdGtkFoldview *foldview);
+
-//*****************************************************************************
-// GcmdGtkFoldviewClass
-//*****************************************************************************
+// ###########################################################################
+//
+// GcmdGtkFoldviewClass
+//
+// ###########################################################################
struct GcmdGtkFoldviewClass
{
GtkVBoxClass parent_class;
@@ -900,8 +253,5 @@ struct GcmdGtkFoldviewClass
void (* gcmdgtkfoldview) (GcmdGtkFoldview* fv);
};
-extern GcmdGtkFoldview *GcmdFoldview();
-extern GtkWidget *GcmdWidget();
-
#endif //__GCMDGTKFOLDVIEW_PRIVATE_H__
diff --git a/src/foldview/gnome-cmd-foldview-quickstack.h b/src/foldview/gnome-cmd-foldview-quickstack.h
new file mode 100644
index 0000000..6af9fef
--- /dev/null
+++ b/src/foldview/gnome-cmd-foldview-quickstack.h
@@ -0,0 +1,252 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GNOME_CMD_FOLDVIEW_QUICKSTACK_H__
+#define __GNOME_CMD_FOLDVIEW_QUICKSTACK_H__
+
+#include <glib.h>
+
+template <typename ElementType>
+struct GnomeCmdQuickStack
+{
+ private:
+ guint32 a_el_core_size; //= sizeof(ElementType);
+ guint32 a_ix_core_size; //= sizeof(IndexType);
+
+ guint32 a_step;// increment = 10;
+ guint32 a_size;//
+
+ ElementType* d_el;// = NULL;
+ guint32* d_ix;// = NULL;
+ guint32 a_ff;// = 0;
+
+ private:
+ gboolean realloc();
+ guint32 index_pop();
+ void index_push(guint32 index);
+
+ public:
+ GnomeCmdQuickStack<ElementType>(gint increment);
+ ~GnomeCmdQuickStack();
+
+ static guint32 s_invalid_index; // = 0xFFFFFFFF
+
+ guint32 push(ElementType);
+ void pop (guint32);
+
+ ElementType get (guint32 index);
+ ElementType * get_ptr (guint32 index);
+
+ guint32 stat_size() { return a_size; }
+ guint32 stat_first_free() { return a_ff; }
+ guint32 stat_used() { return a_size - ( a_ff + 1 ); }
+};
+
+// ***************************************************************************
+//
+// Ctor, Dtor
+//
+// ***************************************************************************
+template <typename ElementType> guint32 GnomeCmdQuickStack<ElementType>::s_invalid_index = 0xFFFFFFFF;
+
+template <typename ElementType>
+GnomeCmdQuickStack<ElementType>::GnomeCmdQuickStack(gint increment)
+{
+ guint32 i = 0;
+ //.........................................................................
+
+ a_el_core_size = sizeof(ElementType);
+ a_ix_core_size = sizeof(guint32);
+
+ a_step = increment;
+ a_size = 0;
+
+ d_el = NULL;
+ d_ix = NULL;
+ a_ff = 0;
+
+ // alloc for pointers
+ d_el = (ElementType*)(g_malloc0(a_el_core_size * a_step));
+ if ( !d_el )
+ {
+ g_printerr("GVFS_qstack_init:g_malloc0 failed for d_el");
+ return;
+ }
+
+ // alloc for indexes
+ d_ix = (guint32*)(g_malloc0(a_ix_core_size * a_step));
+ if ( !d_ix )
+ {
+ g_printerr("GVFS_qstack_init:g_malloc0 failed for d_ix");
+ return;
+ }
+
+ // init indexes stack
+ for ( i = 0 ; i != a_step ; i++ )
+ {
+ d_ix[i] = a_step - i - 1;
+ }
+ a_ff = a_step - 1;
+
+ // size
+ a_size = a_step;
+}
+template <typename ElementType>
+GnomeCmdQuickStack<ElementType>::~GnomeCmdQuickStack()
+{
+ //GCMD_INF("gstack_destroy");
+ g_free(d_el);
+ g_free(d_ix);
+}
+
+// ***************************************************************************
+//
+// private
+//
+// ***************************************************************************
+template <typename ElementType>
+gboolean
+GnomeCmdQuickStack<ElementType>::realloc()
+{
+ gpointer temp = NULL;
+ guint32 i = 0;
+
+ //GCMD_WNG("GVFS_qstack_realloc at size:%04i", a_size);
+
+ //.........................................................................
+ // free indexes stack ; since there is no more index free,
+ // we could just realloc - but there is no g_realloc0 in Glib
+ //
+ // We should use g_memdup for emulate g_realloc0 // _GWR_TODO_
+
+ // free the old indexes stack
+ g_free(d_ix);
+
+ // alloc a new indexes stack
+ d_ix = (guint32*)(g_malloc0(a_ix_core_size * ( a_size + a_step ) ));
+ if ( !d_ix )
+ {
+ g_printerr("GVFS_qstack_realloc:g_malloc0 failed for d_ix");
+ return FALSE;
+ }
+
+ // store new free indexes
+ for ( i = 0 ; i != a_step ; i++ )
+ {
+ d_ix[i] = a_size + a_step - i - 1;
+ }
+
+ //.........................................................................
+ // realloc pointers array
+ temp = (gpointer)d_el;
+ d_el = (ElementType*)(g_malloc0(a_el_core_size * ( a_size + a_step ) ));
+ if ( !d_el )
+ {
+ g_printerr("GVFS_qstack_realloc:g_malloc0 failed for d_el");
+ return FALSE;
+ }
+
+ // copy used pointers
+ memcpy( d_el, temp, a_el_core_size * a_size);
+
+ // free temp
+ g_free(temp);
+
+ // update stack size
+ a_size += a_step;
+
+ // update first free index
+ a_ff = a_step - 1;
+
+ return TRUE;
+}
+template <typename ElementType>
+guint32
+GnomeCmdQuickStack<ElementType>::index_pop()
+{
+ if ( a_ff == 0 )
+ {
+ //guint32 temp = a_ff;
+ // index on indexes is zero ; we are missing storage places
+ // -> realloc
+ guint32 index = d_ix[0];
+ realloc();
+
+ //GCMD_INF("GVFS_qstack_pop (realloc):index:%04i ff:%04i->%04i of %04i", index, temp, a_ff, a_size-1);
+ return index;
+ }
+
+ //GCMD_INF("GVFS_qstack_pop:ff:%04i->%04i of %04i", a_ff, a_ff-1, a_size-1);
+ return d_ix[a_ff--];
+}
+template <typename ElementType>
+void
+GnomeCmdQuickStack<ElementType>::index_push(guint32 index)
+{
+ if ( a_ff >= a_size )
+ {
+ g_printerr("GnomeCmdQuickStack::push:a_ff too high");
+ return;
+ }
+
+ //GCMD_INF("GVFS_qstack_push:index:%04i ff:%04i->%04i of %04i", index, a_ff, a_ff+1, a_size-1);
+ d_ix[++a_ff] = index;
+}
+
+
+
+
+// ***************************************************************************
+//
+// public
+//
+// ***************************************************************************
+template <typename ElementType>
+guint32
+GnomeCmdQuickStack<ElementType>::push(ElementType element)
+{
+ guint32 index = index_pop();
+
+ d_el[index] = element;
+
+ return index;
+}
+template <typename ElementType>
+void
+GnomeCmdQuickStack<ElementType>::pop(guint32 index)
+{
+ index_push(index);
+}
+
+template <typename ElementType>
+ElementType
+GnomeCmdQuickStack<ElementType>::get(guint32 _index)
+{
+ return d_el[_index];
+}
+
+
+
+
+
+
+
+#endif //__GNOME_CMD_FOLDVIEW_QUICKSTACK_H__
diff --git a/src/foldview/gnome-cmd-foldview-treestore.cc b/src/foldview/gnome-cmd-foldview-treestore.cc
index 9ebf215..b1fe20c 100644
--- a/src/foldview/gnome-cmd-foldview-treestore.cc
+++ b/src/foldview/gnome-cmd-foldview-treestore.cc
@@ -1,119 +1,138 @@
-#include <string.h>
-#include "gnome-cmd-foldview-treestore.h"
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+ Tim-Philipp Müller
+
+ ***************************************************************************
+ Tim-Philipp Müller wrote the excellent "GTK+ 2.0 Tree View Tutorial" whose
+ section 11 'writing custom models' is the base of the
+ GnomeCmdFoldviewTreestore code.
+ ***************************************************************************
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <string.h>
+#include "gnome-cmd-foldview-treestore.h"
+#include "gnome-cmd-foldview-utils.h"
+
+
// ###########################################################################
// ### ###
// ## ##
-// # LOGGER #
+// # DATA #
// ## ##
// ### ###
// ###########################################################################
-void gwr_inf(const char* fmt, ...);
-void gwr_wng(const char* fmt, ...);
-void gwr_err(const char* fmt, ...);
-
-//#define DEBUG_STORE
-//#define DEBUG_NODES
-//#define DEBUG_BLOCKS
-
-
-// Logging for GnomeCmdFoldviewTreestore
-#ifdef DEBUG_STORE
+// ###########################################################################
+// ### ###
+// ## ##
+// # PATH #
+// ## ##
+// ### ###
+// ###########################################################################
+void*
+GnomeCmdFoldviewTreestore::Path::operator new(size_t t)
+{
+ Path * path = g_try_new0(Path, 1);
- #define STORE_INF(...) \
- { \
- gwr_inf(__VA_ARGS__); \
- }
- #define STORE_WNG(...) \
- { \
- gwr_wng(__VA_ARGS__); \
- }
- #define STORE_ERR(...) \
- { \
- gwr_err( __VA_ARGS__); \
- }
+ if ( ! path )
+ GCMD_ERR("GnomeCmdFoldviewTreestore::Path::operator new:g_try_new0 failed");
-#else
+ return path;
+}
+void
+GnomeCmdFoldviewTreestore::Path::operator delete(void *p)
+{
+ g_free(p);
+}
- #define STORE_INF(...)
- #define STORE_WNG(...)
- #define STORE_ERR(...)
+GnomeCmdFoldviewTreestore::Path::Path(gint card)
+{
+ d_ascii_dump = (gchar*)g_try_malloc0(64);
+ a_card = card;
+ d_uid = (guint32*) g_try_malloc0(a_card * sizeof(guint32) );
+}
+GnomeCmdFoldviewTreestore::Path::~Path()
+{
+ g_free(d_ascii_dump);
+ g_free(d_uid);
+}
-#endif
+gint
+GnomeCmdFoldviewTreestore::Path::card()
+{
+ return a_card;
+}
-// Logging for nodes
-#ifdef DEBUG_NODES
+guint32
+GnomeCmdFoldviewTreestore::Path::uid_get(gint _pos)
+{
+ return d_uid[_pos];
+}
- #define NODE_INF(...) \
- { \
- gwr_inf(__VA_ARGS__); \
- }
- #define NODE_WNG(...) \
- { \
- gwr_wng(__VA_ARGS__); \
- }
- #define NODE_ERR(...) \
- { \
- gwr_err( __VA_ARGS__); \
- }
+void
+GnomeCmdFoldviewTreestore::Path::uid_set(gint _pos, guint32 _uid)
+{
+ d_uid[_pos] = _uid;
+}
-#else
+GnomeCmdFoldviewTreestore::Path*
+GnomeCmdFoldviewTreestore::Path::dup()
+{
+ Path * dup = NULL;
+ gint i = 0;
+ //.........................................................................
- #define NODE_INF(...)
- #define NODE_WNG(...)
- #define NODE_ERR(...)
+ dup = new Path(card());
-#endif
+ for ( i = 0 ; i != card() ; i++ )
+ dup->uid_set(i, uid_get(i));
-// Logging for blocks
-#ifdef DEBUG_BLOCKS
+ return dup;
+}
- #define BLOCK_INF(...) \
- { \
- gwr_inf(__VA_ARGS__); \
- }
- #define BLOCK_WNG(...) \
- { \
- gwr_wng(__VA_ARGS__); \
- }
- #define BLOCK_ERR(...) \
- { \
- gwr_err( __VA_ARGS__); \
+const gchar*
+GnomeCmdFoldviewTreestore::Path::dump()
+{
+ gchar temp[128];
+ gint i ;
+ //.........................................................................
+ if ( a_card == 0 )
+ {
+ sprintf(d_ascii_dump, "~ Empty ~");
+ return (const gchar*)d_ascii_dump;
}
-#else
-
- #define BLOCK_INF(...)
- #define BLOCK_WNG(...)
- #define BLOCK_ERR(...)
+ sprintf(d_ascii_dump, "%03i", uid_get(0));
-#endif
-
-
-// ###########################################################################
-// ### ###
-// ## ##
-// # DATA #
-// ## ##
-// ### ###
-// ###########################################################################
-gint GnomeCmdFoldviewTreestore::Data::Count = 0;
+ for ( i = 1 ; i < a_card ; i++ )
+ {
+ sprintf(temp, " %03i ", uid_get(i));
+ strcat(d_ascii_dump, temp);
+ }
-GnomeCmdFoldviewTreestore::Data::Data()
-{
- GnomeCmdFoldviewTreestore::Data::Count++;
- //STORE_INF("DAT(+ %04i)", Count);
+ return (const gchar*)d_ascii_dump;
}
-GnomeCmdFoldviewTreestore::Data::~Data()
-{
- Count--;
- //STORE_INF("DAT(- %04i)", Count);
-}
-
-
-
// ###########################################################################
// ### ###
// ## ##
@@ -122,10 +141,10 @@ GnomeCmdFoldviewTreestore::Data::~Data()
// ### ###
// ###########################################################################
-gint GnomeCmdFoldviewTreestore::node::Count = 0;
+gint GnomeCmdFoldviewTreestore::Node::Count = 0;
#define NODE_FROM_ITER(_node, _iter) \
- _node = (GnomeCmdFoldviewTreestore::node*)_iter->user_data
+ _node = (GnomeCmdFoldviewTreestore::Node*)_iter->user_data
#define ITER_FROM_NODE(_treestore, _iter, _node) \
(_iter)->stamp = _treestore->stamp(); \
@@ -142,7 +161,38 @@ gint GnomeCmdFoldviewTreestore::node::Count = 0;
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node::new:
+ * GnomeCmdFoldviewTreestore::Node::new()
+ *
+ **/
+
+//=============================================================================
+void* GnomeCmdFoldviewTreestore::Node::operator new(
+ size_t size)
+{
+ GnomeCmdFoldviewTreestore::Node *n = g_try_new0(GnomeCmdFoldviewTreestore::Node, 1);
+
+ return n;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Node::delete()
+ *
+ **/
+
+//=============================================================================
+void
+GnomeCmdFoldviewTreestore::Node::operator delete(
+void *p)
+{
+ g_free(p);
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Node::node()
*
* @_depth : Depth of the node ( = same as depth in GtkTreePath )
* @_pos : Pos ( starting from 0 ) of the node in the block
@@ -153,96 +203,122 @@ gint GnomeCmdFoldviewTreestore::node::Count = 0;
**/
//=============================================================================
-void* GnomeCmdFoldviewTreestore::node::operator new(
- size_t size,
- gint _depth, // only for the new node_block
- gint _pos,
- GnomeCmdFoldviewTreestore::node *_parent,
- GnomeCmdFoldviewTreestore::Data* _data)
+GnomeCmdFoldviewTreestore::Node::Node(
+ guint32 _uid,
+ gint _depth, // only for the new node_block
+ gint _pos,
+ Node * _parent,
+ DataInterface * _data)
{
- GnomeCmdFoldviewTreestore::node *n = g_try_new0(GnomeCmdFoldviewTreestore::node, 1);
+ a_bits = 0;
+ a_bits += ( (guint32)( _uid << e_UID_SHIFT) ) & e_UID_BITS;
+ a_pos = _pos;
+ a_parent = _parent;
+ a_next = NULL;
- if ( !n )
- return n;
+ a_children = new NodeBlock(_depth + 1, this);
- n->a_pos = _pos;
- n->a_parent = _parent;
- n->a_next = NULL;
-
- n->a_children = new (_depth + 1, n) node_block;
-
- n->d_data = _data;
+ d_data = _data;
Count++;
- NODE_INF("NOD(+%04i nodes) d:%03i p:%03i p:0x%08x,%03i", Count, _depth, _pos, _parent, _parent ? _parent->pos() : 0);
-
- return n;
+ //NODE_INF("NOD+(%04i):[%s]",Count, log());
}
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node::delete:
+ * GnomeCmdFoldviewTreestore::Node::~node()
*
- * This function does _NOT_ free the GArray containing the children.
- * For recursive delete, use purge()
+ * Here we only delete the memory allowed for the struct itself.
+ * We do _NOT_ free the node_block containing the children.
+ * For recursive delete, use remove()
*
**/
//=============================================================================
-void
-GnomeCmdFoldviewTreestore::node::operator delete(
-void *p)
+GnomeCmdFoldviewTreestore::Node::~Node()
{
- GnomeCmdFoldviewTreestore::node *n = (GnomeCmdFoldviewTreestore::node*)p;
-
- #ifdef DEBUG_NODES
- NODE_INF("NOD(-%04i nodes) p:%03i p:0x%08x,%03i", Count - 1, n->pos(), n->parent(), n->parent() ? n->parent()->pos() : 0);
- #endif
-
- delete n->data();
+ //NODE_INF("NOD-(%04i):[%s]", (Count - 1), log());
- g_free(p);
+ delete data();
Count--;
}
+
+
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node::purge:
+ * GnomeCmdFoldviewTreestore::Node:remove_children()
*
- * @node : the node of this block to remove
+ * __RECURSIVE__ remove the descendance of the node.
*
- * _RECURSIVELY_ remove the node and all its descendance. The GArray
- * containing the children of the node is deleted.
+ **/
+
+//=============================================================================
+gint
+GnomeCmdFoldviewTreestore::Node::remove_children()
+{
+ return children()->remove_nodes();
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Node:remove_child()
*
+ * __RECURSIVE__ remove a child and all its descendance.
+ *
**/
//=============================================================================
gint
-GnomeCmdFoldviewTreestore::node::purge()
+GnomeCmdFoldviewTreestore::Node::remove_child(
+ gint _pos)
{
gint count = 0;
//.........................................................................
- count += children()->purge();
- delete children();
+ // remove children nodes
+ count += children()->remove_node(_pos);
+
return count;
}
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Node::row
+ *
+ * __RECURSIVE__
+ * Get a node's row index in the tree
+ *
+ **/
+
+//=============================================================================
+gint
+GnomeCmdFoldviewTreestore::Node::row()
+{
+ if ( depth() != 1 )
+ {
+ return ( pos() + 1 ) + parent()->row();
+ }
+
+ return pos();
+}
//=============================================================================
//
// node : Logging
//
//=============================================================================
-#ifdef DEBUG_NODES
-const gchar* GnomeCmdFoldviewTreestore::node::log()
+const gchar* GnomeCmdFoldviewTreestore::Node::log()
{
static gchar Node_str_01[1024];
- //node : pos parent next children data
- sprintf(Node_str_01, "dep:%03i pos:%03i nxt:%s chd:%03i dat:%s",
+ //node : ref_count pos parent next children data
+ sprintf(Node_str_01, "this:%08x dep:%03i pos:%03i nxt:%s chd:%03i dat:%s",
+ this,
a_parent ? a_parent->children()->depth() : 1,
a_pos,
a_next ? "Y" : "N",
@@ -251,12 +327,80 @@ const gchar* GnomeCmdFoldviewTreestore::node::log()
return Node_str_01;
}
-#else
-const gchar* GnomeCmdFoldviewTreestore::node::log()
+
+void GnomeCmdFoldviewTreestore::Node::dump_tree(
+ gint _level)
{
- return "XXX";
+ GnomeCmdFoldviewTreestore::NodeBlock * block = NULL;
+ GnomeCmdFoldviewTreestore::Node * child = NULL;
+ gint card = 0;
+ gint depth = 0;
+
+ gint i = 0;
+ gchar sp [256];
+ gchar s1 [256];
+ gchar s2 [256];
+ //.........................................................................
+ //
+ // 0123456789
+ // [xxxxxxxx] 0 8
+ // | 4 1
+ // +-----[xxxxxxxx] 4 10
+ // |
+ // +-----[xxxxxxxx]
+ //
+
+ //.........................................................................
+ //
+ // some vars
+ //
+ block = children();
+ card = block->card();
+ depth = block->depth();
+
+ //.........................................................................
+ //
+ // this
+ //
+ if ( _level == 0 )
+ {
+ strcpy(s1, " ");
+ strcpy(s2, " ");
+ }
+ if ( _level == 1 )
+ {
+ strcpy(s1, " |");
+ strcpy(s2, " +-----");
+ }
+ if ( _level >= 2 )
+ {
+ strcpy(sp, " ");
+ for ( i = 2 ; i <= _level ; i++ )
+ {
+ // 0123456789
+ strcat(sp, " ");
+ }
+
+ strcpy(s1, sp);
+ strcpy(s2, sp);
+ strcat(s1, " |");
+ strcat(s2, " +-----");
+ }
+
+ NODE_TKI("%s", s1);
+ NODE_TKI("%s[%08x]", s2, this);
+
+ //.........................................................................
+ //
+ // children
+ //
+ for ( i = 0 ; i != card ; i++ )
+ {
+ child = g_array_index(block->array(), GnomeCmdFoldviewTreestore::Node*, i);
+
+ child->dump_tree(1 + _level);
+ }
}
-#endif
// ###########################################################################
// ### ###
@@ -265,87 +409,129 @@ const gchar* GnomeCmdFoldviewTreestore::node::log()
// ## ##
// ### ###
// ###########################################################################
-gint GnomeCmdFoldviewTreestore::node_block::Count = 0;
+gint GnomeCmdFoldviewTreestore::NodeBlock::Count = 0;
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node_block::new:
+ * GnomeCmdFoldviewTreestore::NodeBlock::new:
*
- * @_depth : The depth of the block ( = same as depth in GtkTreePath )
- * @_parent : The parent node
+ **/
+
+//=============================================================================
+void* GnomeCmdFoldviewTreestore::NodeBlock::operator new(
+ size_t size)
+{
+ GnomeCmdFoldviewTreestore::NodeBlock *nb = g_try_new0(GnomeCmdFoldviewTreestore::NodeBlock, 1);
+
+ return nb;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::NodeBlock::delete:
*
**/
//=============================================================================
-void* GnomeCmdFoldviewTreestore::node_block::operator new(
- size_t size,
- guint _depth,
- GnomeCmdFoldviewTreestore::node *_parent)
+void GnomeCmdFoldviewTreestore::NodeBlock::operator delete (void *p)
{
- GnomeCmdFoldviewTreestore::node_block *nb = g_try_new0(GnomeCmdFoldviewTreestore::node_block, 1);
+ g_free(p);
+}
- if ( !nb )
- return nb;
+//=============================================================================
- nb->a_card = 0;
- nb->a_depth = _depth;
- nb->a_parent = _parent;
+ /**
+ * GnomeCmdFoldviewTreestore::NodeBlock::NodeBlock()
+ *
+ * @_depth : The depth of the block ( = same as depth in GtkTreePath )
+ * @_parent : The parent node
+ *
+ **/
+
+//=============================================================================
+GnomeCmdFoldviewTreestore::NodeBlock::NodeBlock(
+ guint _depth,
+ GnomeCmdFoldviewTreestore::Node * _parent)
+{
+ a_card = 0;
+ a_depth = _depth;
+ a_parent = _parent;
- nb->d_nodes = g_array_sized_new(
+ d_nodes = g_array_sized_new(
FALSE, // zero_terminated element appended at the end
TRUE, // all bits set to zero
- sizeof(node*), // element_size,
+ sizeof(Node*), // element_size,
10); //reserved_size);
// Fuck, Fuck, Fuck !!!
// Spended hours on this, g_array_sized_new( ...set bits to 0 )
// doesnt fucking work !!!
- // printf("GArray 0x%08x d:%03i p:0x%08x [0]=0x%08x\n", nb->d_nodes, nb->a_depth, nb->a_parent, g_array_index(nb->d_nodes, GnomeCmdFoldviewTreestore::node*, 0));
+ // printf("GArray 0x%08x d:%03i p:0x%08x [0]=0x%08x\n", nb->d_nodes, nb->a_depth, nb->a_parent, g_array_index(nb->d_nodes, GnomeCmdFoldviewTreestore::Node*, 0));
Count++;
- BLOCK_INF("BLK(+%04i blocks) d:%03i", Count, nb->a_depth);
-
- return nb;
+ //BLOCK_INF("BLK+(%04i):d %03i", Count, a_depth);
}
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node_block::delete:
+ * GnomeCmdFoldviewTreestore::NodeBlock::~node_block()
+ *
+ * Here we only delete the array of children ; it does _NOT_ affect the
+ * children objects.
+ * For recursive delete, use purge()
*
**/
//=============================================================================
-void GnomeCmdFoldviewTreestore::node_block::operator delete (void *p)
+GnomeCmdFoldviewTreestore::NodeBlock::~NodeBlock()
{
- GnomeCmdFoldviewTreestore::node_block *b = (GnomeCmdFoldviewTreestore::node_block*)p;
- #ifdef DEBUG_BLOCKS
- BLOCK_INF("BLK(-%04i blocks) d:%03i c:%03i", Count - 1, b->a_depth, b->a_card);
- #endif
+ //BLOCK_INF("BLK-(%04i):d %03i c:%03i", Count - 1, a_depth, a_card);
- g_array_free( b->d_nodes, TRUE );
-
- g_free(p);
+ g_array_free( d_nodes, TRUE );
Count--;
}
+
+
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node_block::node_get:
+ * GnomeCmdFoldviewTreestore::NodeBlock::reset()
+ *
+ * Set the number of children to zero, redim the GArray
+ *
+ **/
+
+//=============================================================================
+void
+GnomeCmdFoldviewTreestore::NodeBlock::reset()
+{
+ if ( ! a_card )
+ return;
+
+ g_array_remove_range(d_nodes, 0, a_card);
+ a_card = 0;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::NodeBlock::node_get:
*
* @pos : Position ( starting from zero ) of the node to get.
*
**/
//=============================================================================
-GnomeCmdFoldviewTreestore::node*
-GnomeCmdFoldviewTreestore::node_block::node_get(
+GnomeCmdFoldviewTreestore::Node*
+GnomeCmdFoldviewTreestore::NodeBlock::node_get(
gint pos)
{
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
if ( a_card == 0 )
{
@@ -366,7 +552,7 @@ GnomeCmdFoldviewTreestore::node_block::node_get(
return NULL;
}
- node = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, pos);
+ node = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, pos);
//BLOCK_INF("BLK(%-20s) d:%03i p:%03i c:%03i [%s]", "node_get", a_depth, pos, a_card, node->log());
return node;
}
@@ -374,116 +560,111 @@ GnomeCmdFoldviewTreestore::node_block::node_get(
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node_block::node_append:
+ * GnomeCmdFoldviewTreestore::NodeBlock::node_append:
*
* @data : user's data
*
* Insert a node in the block. This method respect the ordering settings
* of the store.
*
- **/
+ **/
//=============================================================================
-GnomeCmdFoldviewTreestore::node*
-GnomeCmdFoldviewTreestore::node_block::node_append(
-GnomeCmdFoldviewTreestore::Data *data)
+GnomeCmdFoldviewTreestore::Node*
+GnomeCmdFoldviewTreestore::NodeBlock::node_add(
+ guint32 _uid,
+ eSortType _sort_type,
+ gint _collate_key_to_use,
+ DataInterface * _data)
{
- GnomeCmdFoldviewTreestore::node *node = NULL;
- GnomeCmdFoldviewTreestore::node *temp = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *temp = NULL;
gint i = 0;
//.........................................................................
// create a new node with pos = 0 :
// we cant set the position now, because we dont know at which position
// we will be stored
- node = new (a_depth, 0, a_parent, data) GnomeCmdFoldviewTreestore::node;
+ node = new GnomeCmdFoldviewTreestore::Node(_uid, a_depth, 0, a_parent, _data);
- if ( !GnomeCmdFoldviewTreestore::Render_sort() )
+ if ( ! _sort_type ) // eSortNone is 0x00
{
goto generic_append;
}
- else
+
+ if ( _sort_type == GnomeCmdFoldviewTreestore::eSortDescending )
{
- if ( GnomeCmdFoldviewTreestore::Render_sort_ascending() )
- {
- // ascending - case NO
- if ( !GnomeCmdFoldviewTreestore::Render_sort_case_sensitive() )
- {
- g_assert(FALSE);
- }
- //.................................................................
- // ascending - case YES
- else
- {
- temp = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, 0);
+ temp = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, 0);
loop_acy:
- // Fuck, Fuck, Fuck !!!
- // Spended hours on this, g_array_sized_new( ...set bits to 0 )
- // doesnt fucking work !!!
- //if ( !temp )
- if ( i >= a_card )
- goto generic_append;
-
- g_assert( node->parent() == temp->parent() );
+ // Fuck, Fuck, Fuck !!!
+ // Spended hours on this, g_array_sized_new( ...set bits to 0 )
+ // doesnt fucking work ( in glib 2.16.6 ) !!!
+ if ( i >= a_card )
+ goto generic_append;
+
+ // Previous method, with direct access to collate keys
+ // from DataInterface
+ //
+ // if ( strcmp (
+ // node->data()->utf8_collate_key(_collate_key_to_use),
+ // temp->data()->utf8_collate_key(_collate_key_to_use)
+ // ) >= 0 )
+ //
+ if ( node->data()->compare(temp->data()) >= 0 )
+ goto generic_insert;
- if ( strcmp( node->data()->utf8_collate_key(), temp->data()->utf8_collate_key() ) >= 0 )
- goto generic_insert;
+ temp = temp->next();
+ i++;
+ goto loop_acy;
+ }
- temp = temp->next(); i++;
- goto loop_acy;
- }
- }
- else
- {
- // descending - case NO
- if ( !GnomeCmdFoldviewTreestore::Render_sort_case_sensitive() )
- {
- g_assert(FALSE);
- }
- //.................................................................
- // descending - case YES
- else
- {
- temp = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, 0);
+ if ( _sort_type == GnomeCmdFoldviewTreestore::eSortAscending )
+ {
+ temp = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, 0);
loop_dcy:
- // Fuck, Fuck, Fuck !!!
- // Spended hours on this, g_array_sized_new( ...set bits to 0 )
- // doesnt fucking work !!!
- //if ( !temp )
- if ( i >= a_card )
- goto generic_append;
-
- g_assert( node->parent() == temp->parent() );
-
- if ( strcmp( node->data()->utf8_collate_key(), temp->data()->utf8_collate_key() ) <= 0 )
- goto generic_insert;
-
- temp = temp->next(); i++;
- goto loop_dcy;
- }
- }
+ // Fuck, Fuck, Fuck !!!
+ // Spended hours on this, g_array_sized_new( ...set bits to 0 )
+ // doesnt fucking work ( in glib 2.16.6 ) !!!
+ if ( i >= a_card )
+ goto generic_append;
+
+ // Previous method, with direct access to collate keys
+ // from DataInterface
+ //
+ //if ( strcmp (
+ // node->data()->utf8_collate_key(_collate_key_to_use),
+ // temp->data()->utf8_collate_key(_collate_key_to_use)
+ // ) <= 0 )
+ //
+ if ( node->data()->compare(temp->data()) <= 0 )
+ goto generic_insert;
+
+ temp = temp->next(); i++;
+ goto loop_dcy;
}
+ // Bad sort type
+ g_assert(FALSE);
//.........................................................................
//
- // Generic back-end : We have to append 'node' at the end of the array
+ // 'Append' back-end : We have to append 'node' at the end of the array
//
// append to the end of the array
generic_append:
- // Now we know our pos, it is a_card - 1 + 1 = a_card
- node->a_pos = a_card;
+ // Now we know the node's pos, it is a_card - 1 + 1 = a_card
+ node->set_pos(a_card);
// Note : I have never seen d_nodes change in append case
+ // but I still reaffect the GArray, cf GLib documentation
d_nodes = g_array_append_val(d_nodes, node);
// modify the previous node so its ->next field points to the newly
// created node ; do that only if we didnt create the first node.
if ( a_card != 0 )
{
- temp = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, a_card - 1);
- g_assert( node->parent() == temp->parent() );
- temp->a_next = node;
+ temp = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, a_card - 1);
+ temp->set_next(node);
}
a_card++;
@@ -491,31 +672,31 @@ generic_append:
//.........................................................................
//
- // Generic back-end : We have to insert 'node' at pos i, instead of 'temp'
+ // 'Insert' back-end : We have to insert 'node' at pos i, instead of 'temp'
//
generic_insert:
// Now we know our pos, it is i
- node->a_pos = i;
+ node->set_pos(i);
- // insert
+ // I reaffect the GArray, cf GLib documentation, but I didnt dig this case
d_nodes = g_array_insert_val(d_nodes, i, node);
// modify the previous node so its ->next field points to 'node' ( at pos i )
// do that only if we didnt create the first node.
if ( i != 0 )
- g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, i - 1)->a_next = node;
+ g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, i - 1)->set_next(node);
// modify 'node' so its ->next field points to the node at pos i + 1
// here we have collated, so we are sure that we have taken the place
// of a node, that is now just after us
- node->a_next = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, i + 1);
+ node->set_next( g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, i + 1) );
// increase by 1 all ->pos fields of nodes following 'node'
temp = node->next();
g_assert(temp);
while ( temp )
{
- temp->a_pos++;
+ temp->inc_pos();
temp = temp->next();
}
@@ -523,136 +704,295 @@ generic_insert:
return node;
}
-
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node_block::node_cut:
+ * GnomeCmdFoldviewTreestore::NodeBlock::remove_node()
*
- * @node : the node to cut
+ * @param node : the node to remove
*
- * Cut the node, i.e. simply remove its pointer from the node_block
- * it belongs to, and delete it;
+ * __RECURSIVE__
+ * Remove the node and all its children. Update block info.
*
**/
//=============================================================================
-/*
-void
-GnomeCmdFoldviewTreestore::node_block::node_cut(
- GnomeCmdFoldviewTreestore::node* node)
+gint
+GnomeCmdFoldviewTreestore::NodeBlock::remove_node(
+ gint pos)
{
- GnomeCmdFoldviewTreestore::node* follow = NULL;
+ GnomeCmdFoldviewTreestore::Node* node = NULL;
+ GnomeCmdFoldviewTreestore::Node* follow = NULL;
gint i = 0;
- gint pos = 0;
+ gint count = 0;
//.........................................................................
+ node = node_get(pos);
+ g_return_val_if_fail( node, 0 );
- pos = node->pos();
+ //BLOCK_INF("remove_node():[%s]", node->log());
// remove the node from the array
g_array_remove_index(d_nodes, pos);
a_card--;
- // now update all node->a_pos, starting from node->pos() since it just
- // has been replaced by GArray call
+ // modify eventually the previous node's "next" field
+ // ( dont call node_get, we do inline-verifications
+ // - pos = 0 => no previous node to modify
+ // - pos !== a_card <=> we remove the last node ; in this case next = NULL
+ if ( pos != 0 )
+ g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, pos - 1)->set_next
+ (
+ ( pos != a_card ?
+ g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, pos) :
+ NULL )
+ );
+
+ // update all nodes "pos" field, starting from node->pos() since it just
+ // has been replaced by the g_array_index call
+ // ( dont call node_get, we dont need verifications )
for ( i = pos ; i < a_card ; i ++ )
{
- follow = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, i);
- follow->a_pos -= 1;
+ follow = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, i);
+ follow->dec_pos();
}
- // delete the node, it will automatically call delete on the Data* member
- delete node;
+ //
+ // delete the node and all its children
+ //
- // modify the previous->a_next field
- if ( pos != 0 )
- g_array_index(d_nodes, GnomeCmdFoldviewTreestore::node*, pos - 1)->a_next = NULL;
+ // remove children nodes
+ count += node->remove_children();
+ // delete the NodeBlock struct
+ delete node->children();
+
+ // delete the Node struct
+ delete node;
+
+ // return count
+ return ( 1 + count);
}
-*/
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::node_block::purge:
+ * GnomeCmdFoldviewTreestore::NodeBlock::remove_nodes()
*
- * @node : the node of this block to remove
- *
- * _RECURSIVELY_ remove all the nodes of the block.
- * After this call, the block cannot be used, its info is invalid
+ * __RECURSIVE__
+ * Remove all the nodes and all their children. Update block info.
*
**/
//=============================================================================
gint
-GnomeCmdFoldviewTreestore::node_block::purge()
+GnomeCmdFoldviewTreestore::NodeBlock::remove_nodes()
{
- GnomeCmdFoldviewTreestore::node* node = NULL;
- GnomeCmdFoldviewTreestore::node* next = NULL;
- gint count = 0;
+ GnomeCmdFoldviewTreestore::Node* node = NULL;
+ GnomeCmdFoldviewTreestore::Node* next = NULL;
+ gint count = 0;
//.........................................................................
- node = node_get(0);
+ //BLOCK_INF("remove_nodes():[%03i]", a_card);
- while ( node )
- {
- next = node->next();
- count += node->purge();
+ node = node_get(0);
- delete node;
- count++;
+ while ( node )
+ {
+ next = node->next();
+ count += remove_node(node->pos());
+ node = next;
+ }
+ //for ( i = 0 ; i < a_card ; i ++ )
+ //{
+ // node = g_array_index(d_nodes, GnomeCmdFoldviewTreestore::Node*, i);
+ // count += remove_node(i);
+ //}
- node = next;
- }
+ reset();
- // no update block, the "purge" process for node_blocks is separated
- // in two methods - this is the quick part
- return count;
+ return count;
}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # BRANCH #
+// ## ##
+// ### ###
+// ###########################################################################
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::operator new()
+ *
+ **/
+
+//=============================================================================
+void* GnomeCmdFoldviewTreestore::Branch::operator new(size_t size)
+{
+ return (void*)g_try_new0(GnomeCmdFoldviewTreestore::Branch, 1);
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::operator delete()
+ *
+ **/
+
+//=============================================================================
+void GnomeCmdFoldviewTreestore::Branch::operator delete(void *p)
+{
+ g_free(p);
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::Branch()
+ *
+ **/
+
+//=============================================================================
+GnomeCmdFoldviewTreestore::Branch::Branch(
+ Node * _node)
+{
+ Node * _parent;
+ //.........................................................................
+ Branch();
+
+ g_return_if_fail( _node );
+
+ _parent = _node->parent();
+ g_return_if_fail( _parent );
+
+ a_root = _node;
+ a_root_parent = _parent;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::Branch()
+ *
+ **/
+
+//=============================================================================
+GnomeCmdFoldviewTreestore::Branch::Branch()
+{
+ a_root = NULL;
+ a_root_parent = NULL;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::~Branch()
+ *
+ **/
+
+//=============================================================================
+GnomeCmdFoldviewTreestore::Branch::~Branch()
+{
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::dup()
+ *
+ **/
+
+//=============================================================================
+GnomeCmdFoldviewTreestore::Branch*
+GnomeCmdFoldviewTreestore::Branch::dup()
+{
+ return NULL;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::cut()
+ *
+ * Delete a branch.
+ *
+ **/
+
+//=============================================================================
gint
-GnomeCmdFoldviewTreestore::node_block::purge_and_update()
+GnomeCmdFoldviewTreestore::Branch::cut()
{
- GnomeCmdFoldviewTreestore::node* node = NULL;
- GnomeCmdFoldviewTreestore::node* next = NULL;
- gint count = 0;
- //.........................................................................
+ gint count = 0;
+ NodeBlock * block_parent = NULL;
+ //.........................................................................
- node = node_get(0);
+ // tell the parent to remove a_root child
+ block_parent = a_root_parent->children();
+ g_return_val_if_fail( block_parent, -1 );
- while ( node )
- {
- next = node->next();
- count += node->purge();
+ count = block_parent->remove_node( a_root->pos() );
- delete node;
- count++;
+ a_root = NULL;
- node = next;
- }
+ return count;
+}
- // update block, the "purge" process for node_blocks is separated
- // in two methods - this is the first call
- g_array_remove_range(d_nodes, 0, a_card);
- a_card = 0;
- return count;
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::cut_but_keep_root()
+ *
+ **/
+
+//=============================================================================
+gint
+GnomeCmdFoldviewTreestore::Branch::cut_but_keep_root()
+{
+ return a_root->remove_children();
}
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::Branch::sort()
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::Branch::sort()
+{
+ return FALSE;
+}
+
+
// ###########################################################################
// ### ###
// ## ##
-// # TREESTORE - CUSTOM METHODS #
+// # NODE ROOT #
// ## ##
// ### ###
// ###########################################################################
+void
+GnomeCmdFoldviewTreestore::node_root_init()
+{
+ //g_return_if_fail( ! a_node_root_created );
-GnomeCmdFoldviewTreestore::eRenderFlags
- GnomeCmdFoldviewTreestore::Render_flags =
- (GnomeCmdFoldviewTreestore::eRenderFlags)
- ( GnomeCmdFoldviewTreestore::eSortDescending |
- GnomeCmdFoldviewTreestore::eSortCaseSensitive
- );
+ d_node_root = new GnomeCmdFoldviewTreestore::Node( 0, 0, 0, NULL, NULL) ;
+ a_node_root_created = TRUE;
+}
+
+// ###########################################################################
+// ### ###
+// ## ##
+// # TREESTORE - CUSTOM METHODS #
+// ## ##
+// ### ###
+// ###########################################################################
//=============================================================================
@@ -698,13 +1038,14 @@ GnomeCmdFoldviewTreestore::iter_is_valid_but_may_be_null(
/**
* GnomeCmdFoldviewTreestore::emit_row_inserted:
*
- * @iter : the iter to check
+ * @iter : the iter inserted
*
**/
//=============================================================================
-void GnomeCmdFoldviewTreestore::emit_row_inserted(
-GnomeCmdFoldviewTreestore::node* node)
+void
+GnomeCmdFoldviewTreestore::emit_row_inserted(
+GnomeCmdFoldviewTreestore::Node* node)
{
GtkTreePath *path = NULL;
GtkTreeIter iter;
@@ -728,13 +1069,14 @@ GnomeCmdFoldviewTreestore::node* node)
/**
* GnomeCmdFoldviewTreestore::emit_row_changed:
*
- * @iter : the iter to check
+ * @iter : the iter changed
*
**/
//=============================================================================
-void GnomeCmdFoldviewTreestore::emit_row_changed(
-GnomeCmdFoldviewTreestore::node* node)
+void
+GnomeCmdFoldviewTreestore::emit_row_changed(
+GnomeCmdFoldviewTreestore::Node* node)
{
GtkTreePath *path = NULL;
GtkTreeIter iter;
@@ -753,11 +1095,134 @@ GnomeCmdFoldviewTreestore::node* node)
gtk_tree_path_free(path);
}
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::emit_row_deleted:
+ *
+ * @iter : the iter deleted
+ *
+ **/
+
+//=============================================================================
+void
+GnomeCmdFoldviewTreestore::emit_row_deleted(
+GnomeCmdFoldviewTreestore::Node* node)
+{
+ GtkTreePath *path = NULL;
+ GtkTreeIter iter;
+ //.........................................................................
+ g_assert( node );
+
+ ITER_FROM_NODE(this, &iter, node);
+
+ path = get_path(GTK_TREE_MODEL(this), &iter);
+
+ gtk_tree_model_row_deleted(
+ GTK_TREE_MODEL(this),
+ path);
+
+ gtk_tree_path_free(path);
+}
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::add_child:
+ * GnomeCmdFoldviewTreestore::emit_row_has_child_toggled:
+ *
+ * @iter : the iter that has
+ * - its first child
+ * or
+ * - no more children
+ *
+ **/
+
+//=============================================================================
+void
+GnomeCmdFoldviewTreestore::emit_row_has_child_toggled(
+GnomeCmdFoldviewTreestore::Node* node)
+{
+ GtkTreePath *path = NULL;
+ GtkTreeIter iter;
+ //.........................................................................
+ g_assert( node );
+
+ ITER_FROM_NODE(this, &iter, node);
+
+ path = get_path(GTK_TREE_MODEL(this), &iter);
+
+ gtk_tree_model_row_has_child_toggled(
+ GTK_TREE_MODEL(this),
+ path,
+ &iter);
+
+ gtk_tree_path_free(path);
+}
+
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::iter_get_uid:
+ *
+ * @iter : the iter to get the uid from
+ *
+ **/
+
+//=============================================================================
+guint32
+GnomeCmdFoldviewTreestore::iter_get_uid(
+ GtkTreeIter *_in_iter)
+{
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ //.........................................................................
+ g_return_val_if_fail( iter_is_valid(_in_iter), 0 );
+
+ NODE_FROM_ITER(node, _in_iter);
+
+ return node->uid();
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_dump
+ *
+ * Dump the treestore, for debugging purpose
+ *
+ **/
+
+//=============================================================================
+void
+GnomeCmdFoldviewTreestore::ext_dump_tree(
+ GtkTreeIter * _iter)
+{
+ GnomeCmdFoldviewTreestore::Node * node = NULL;
+ //.........................................................................
+ if ( ! _iter )
+ {
+ node = node_root();
+ }
+ else
+ {
+ NODE_FROM_ITER(node, _iter);
+ }
+ NODE_TKI(" +-------------------------------------------+");
+ // [12345678]
+ NODE_TKI(" | Dumping Tree from node [%08x] |", node);
+ NODE_TKI(" +-------------------------------------------+");
+
+ node->dump_tree();
+
+ NODE_TKI(" ");
+ //NODE_INF(" +-------------------------------------------+");
+ NODE_TKI(" Dumped !");
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_add_child:
*
* @in_parent : the iter that will have a new child
* @out_child : the child that will be created
@@ -771,71 +1236,76 @@ GnomeCmdFoldviewTreestore::node* node)
//=============================================================================
void
-GnomeCmdFoldviewTreestore::add_child(
- GtkTreeIter *in_parent,
- GtkTreeIter *out_child,
- GnomeCmdFoldviewTreestore::Data *data)
+GnomeCmdFoldviewTreestore::ext_add_child(
+ GtkTreeIter * _in_parent,
+ GtkTreeIter * _out_child,
+ GnomeCmdFoldviewTreestore::DataInterface * _data_child)
{
- GnomeCmdFoldviewTreestore::node *n_parent = NULL;
- GnomeCmdFoldviewTreestore::node *n_child = NULL;
+ GnomeCmdFoldviewTreestore::Node *n_parent = NULL;
+ GnomeCmdFoldviewTreestore::Node *n_child = NULL;
//.........................................................................
- g_return_if_fail( iter_is_valid_but_may_be_null(in_parent) );
+ g_return_if_fail( iter_is_valid_but_may_be_null( _in_parent ) );
// try to set node_root
- if ( ! in_parent )
+ if ( ! _in_parent )
{
- g_return_if_fail( ! node_root() );
+ g_return_if_fail( node_root() );
- d_node_root = new ( 1, 0, NULL, data) GnomeCmdFoldviewTreestore::node;
- n_child = d_node_root;
+ n_parent = node_root();
}
else
{
- NODE_FROM_ITER(n_parent, in_parent );
+ NODE_FROM_ITER(n_parent, _in_parent );
g_return_if_fail( n_parent );
-
- n_child = n_parent->children()->node_append(data);
}
- ITER_FROM_NODE(this, out_child, n_child);
+ n_child = n_parent->children()->node_add(uid_new(), a_sort_type, a_sort_collate_key_to_use, _data_child);
+
+ ITER_FROM_NODE(this, _out_child, n_child);
+
+ _data_child->set_path_from_treestore(ext_path_from_iter(_out_child));
+
emit_row_inserted( n_child );
}
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::set_value:
+ * GnomeCmdFoldviewTreestore::ext_set_data:
*
- * @iter : the iter to check
+ * @iter : set Data for an iter.
*
**/
//=============================================================================
-void GnomeCmdFoldviewTreestore::set_value(
- GtkTreeIter *in,
- gint column,
- GValue *value)
+void
+GnomeCmdFoldviewTreestore::ext_set_data(
+ GtkTreeIter * _iter_in,
+ DataInterface * _data)
{
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ Node * node = NULL;
+ DataInterface * data_old = NULL;
+ DataInterface * data_new = NULL;
//.........................................................................
- g_return_if_fail ( iter_is_valid(in) );
- g_return_if_fail ( value );
+ g_return_if_fail ( iter_is_valid(_iter_in) );
- g_return_if_fail( G_IS_VALUE(value) );
- g_return_if_fail( G_VALUE_TYPE(value) == G_TYPE_POINTER );
+ NODE_FROM_ITER(node, _iter_in);
+ g_assert(node);
- // specific to foldview
- g_return_if_fail( G_VALUE_HOLDS(value, G_TYPE_POINTER) );
+ data_old = node->data();
+ g_return_if_fail( data_old );
- NODE_FROM_ITER(node, in);
- g_assert(node);
+ data_new = _data;
+ g_return_if_fail( data_new );
- GnomeCmdFoldviewTreestore::Data* data = node->data();
+ // We set the Path for the new Data with a copy of the old Data's Path
+ data_new->set_path_from_treestore( data_old->path()->dup() );
- if ( data )
- delete data;
+ // Then we delete the old Data, that will delete old Path too
+ delete data_old;
- node->data() = (GnomeCmdFoldviewTreestore::Data*)g_value_get_pointer(value);
+ // Then we set the new Data as iter Data
+ node->data() = data_new;
emit_row_changed( node );
}
@@ -843,32 +1313,68 @@ void GnomeCmdFoldviewTreestore::set_value(
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::remove_children:
+ * GnomeCmdFoldviewTreestore::ext_data_changed:
*
- * @iter : the iter to check
+ * @iter : set Data for an iter.
+ *
+ * Tell the treestore that an iter's data has changed. So emit the
+ * row_changed signal.
*
**/
//=============================================================================
-gint GnomeCmdFoldviewTreestore::remove_children(
- GtkTreeIter *in)
+void
+GnomeCmdFoldviewTreestore::ext_data_changed(
+ GtkTreeIter * _iter_in)
{
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ Node * node = NULL;
//.........................................................................
- g_return_val_if_fail ( iter_is_valid(in), 0 );
+ g_return_if_fail ( iter_is_valid(_iter_in) );
- NODE_FROM_ITER(node, in);
- g_return_val_if_fail( node, 0 );
+ NODE_FROM_ITER(node, _iter_in);
+ g_assert(node);
- gint count = node->children()->purge_and_update();
+ emit_row_changed( node );
+}
- return count;
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_get_data:
+ *
+ * @iter : get Data for an iter.
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_get_data(
+ GtkTreeIter * _iter_in,
+ DataInterface ** _data_out)
+{
+ Node * node = NULL;
+ DataInterface * data_old = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( _data_out != NULL, FALSE );
+ *_data_out = NULL;
+
+ g_return_val_if_fail ( iter_is_valid(_iter_in), FALSE );
+
+ NODE_FROM_ITER(node, _iter_in);
+ g_assert(node);
+
+ data_old = node->data();
+ g_return_val_if_fail( data_old, FALSE );
+
+ *_data_out = data_old;
+
+ return ( data_old != NULL );
}
//=============================================================================
/**
- * GnomeCmdFoldviewTreestore::clear:
+ * GnomeCmdFoldviewTreestore::ext_clear:
*
* Clear * everything *
*
@@ -876,32 +1382,551 @@ gint GnomeCmdFoldviewTreestore::remove_children(
//=============================================================================
gint
-GnomeCmdFoldviewTreestore::clear()
+GnomeCmdFoldviewTreestore::ext_clear()
{
gint count = 0;
+ //.........................................................................
+ g_return_val_if_fail( d_node_root, 0 );
- // store is empty !
- if ( !d_node_root )
- return 0;
-
- // Quickly purge all beyond node_root
- count = d_node_root->children()->purge();
+ // We should code a quicker mehod // _GWR_TODO_
+ count = d_node_root->remove_children();
// delete node_root
delete d_node_root->children();
delete d_node_root;
- count++;
// Set pointer to NULL
d_node_root = NULL;
- gwr_inf("GnomeCmdFoldviewTreestore::clear:%03i nodes deleted", count);
+ LEAKS_INF("GnomeCmdFoldviewTreestore::ext_clear()");
+ LEAKS_INF(" remaining nodes : %04i %s", Node::Remaining(), Node::Remaining() ? "- not empty -" : "EMPTY !");
+ LEAKS_INF(" remaining blocks : %04i %s", NodeBlock::Remaining(), NodeBlock::Remaining() ? "- not empty -" : "EMPTY !");
return count;
}
+//=============================================================================
+ /**
+ * GnomeCmdFoldviewTreestore::ext_get_root:
+ *
+ * Retrives the root node of a given node
+ *
+ **/
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_get_root(
+ GtkTreeIter *in,
+ GtkTreeIter *out_root)
+{
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), FALSE );
+ g_return_val_if_fail ( out_root, FALSE );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, FALSE );
+
+ // All this code for this simple loop :)
+ while ( node->parent() != node_root() )
+ node = node->parent();
+
+ ITER_FROM_NODE(this, out_root, node);
+ return TRUE;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_is_root:
+ *
+ * Tell wether the iter is a root iter
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_is_root(
+ GtkTreeIter *in)
+{
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), FALSE );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, FALSE );
+
+ return ( node->parent() == node_root() ? TRUE : FALSE );
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_iter_depth:
+ *
+ * Return the depth of an iter
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_iter_depth(
+ GtkTreeIter *in)
+{
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), FALSE );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, FALSE );
+
+ return node->depth();
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_get_gtk_path_str_new:
+ *
+ * @in : a GtkTreeIter
+ *
+ * Return the string path for an iter ( GtkTreePath style )
+ *
+ **/
+
+//=============================================================================
+gchar*
+GnomeCmdFoldviewTreestore::ext_get_gtk_path_str_new(
+ GtkTreeIter *in)
+{
+ gint i = 0;
+ GArray *a = NULL;
+ gint pos = 0;
+ gchar ascii_tmp1 [8];
+ gchar ascii_tmp2 [1024];
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), NULL );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, NULL );
+
+ a = g_array_sized_new(FALSE, TRUE, sizeof(gint), 10);
+
+ do
+ {
+ pos = node->pos();
+ g_array_append_vals(a, &pos, 1);
+
+ node = node->parent();
+ i++;
+ }
+ while ( node != node_root() );
+
+ ascii_tmp2[0] = 0;
+
+ STORE_INF("get_path_str_new:depth %02i", i);
+
+ if ( i > 1 )
+ g_sprintf( ascii_tmp2, "%i:", g_array_index(a, gint, --i) );
+
+ while ( i > 1 )
+ {
+ g_sprintf( ascii_tmp1, "%i:", g_array_index(a, gint, --i) );
+ g_strlcat(ascii_tmp2, ascii_tmp1, 1024);
+ }
+
+ g_sprintf( ascii_tmp1, "%i", g_array_index(a, gint, 0) );
+ g_strlcat(ascii_tmp2, ascii_tmp1, 1024);
+
+ g_array_free(a, TRUE);
+
+ //STORE_INF("get_path_str_new:%s", ascii_tmp2);
+
+ return g_strdup(ascii_tmp2);
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_iter_get_row:
+ *
+ * @in : a GtkTreeIter
+ *
+ * Get the row of an iter
+ *
+ **/
+
+//=============================================================================
+gint GnomeCmdFoldviewTreestore::ext_iter_get_row(
+ GtkTreeIter *in)
+{
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), 0 );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, 0 );
+
+ return node->row();
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_iter_remove_children_no_signal_row_deleted:
+ *
+ * @in : a GtkTreeIter
+ *
+ * Remove all children of iter, but dont send any row_deleted signal.
+ * Only send row_toggled if parent
+ * Call only this method if an iter is collapsed !
+ *
+ **/
+
+//=============================================================================
+gint
+GnomeCmdFoldviewTreestore::ext_iter_remove_children_no_signal_row_deleted(
+ GtkTreeIter *in)
+{
+ gint count = 0;
+ Node * node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), 0 );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, 0 );
+
+ // Create branch from the node
+ Branch branch(node);
+ g_return_val_if_fail( branch.is_valid(), -1 );
+
+ count = branch.cut_but_keep_root();
+
+ // if a_root is now sterile, send child_toggled signal ( if parent != root )
+ if ( branch.root()->is_sterile() )
+ if ( branch.root() != node_root() )
+ emit_row_has_child_toggled(branch.root());
+
+ return count;
+
+ // Previous method, without the Branch concept
+ //
+ // g_return_val_if_fail ( iter_is_valid(in), 0 );
+ //
+ // NODE_FROM_ITER(node, in);
+ // g_return_val_if_fail( node, 0 );
+ //
+ // gint count = node->remove_children();
+ //
+ // // if parent is now sterile, send child_toggled signal ( if parent != root )
+ // if ( ! node->children()->card() )
+ // if ( node->parent() != node_root() )
+ // emit_row_has_child_toggled(node);
+ //
+ // return count;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_iter_sterile_remove:
+ *
+ * @in : a GtkTreeIter with no children
+ *
+ * Remove the iter & send a row_deleted signal
+ *
+ **/
+
+//=============================================================================
+gint
+GnomeCmdFoldviewTreestore::ext_iter_sterile_remove(
+ GtkTreeIter *in)
+{
+ gint count = 0;
+ Node * node = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid(in), FALSE );
+
+ NODE_FROM_ITER(node, in);
+ g_return_val_if_fail( node, FALSE );
+ g_return_val_if_fail( node->is_sterile(), FALSE );
+
+ // Create branch from the node
+ Branch branch(node);
+ g_return_val_if_fail( branch.is_valid(), FALSE );
+
+ // *IMPORTANT* send signal before removing, according to GtkTreeModel doc
+ emit_row_deleted(node);
+
+ // cut the branch
+ count = branch.cut();
+
+ // if parent is now sterile, send child_toggled signal ( if parent != root )
+ if ( branch.parent()->is_sterile() )
+ if ( branch.parent() != node_root() )
+ emit_row_has_child_toggled(branch.parent());
+
+ return count;
+
+ // Previous method, without the Branch concept
+ //
+ // // children block where node resides
+ // block = node->parent()->children();
+ //
+ // // *IMPORTANT* send signal before removing, according to GtkTreeModel doc
+ // emit_row_deleted(node);
+ //
+ // // remove the node
+ // block->remove_node( node->pos() );
+ //
+ // // if parent is now sterile, send child_toggled signal ( if parent != root )
+ // if ( ! block->card() )
+ // if ( block->parent() != node_root() )
+ // emit_row_has_child_toggled(block->parent());
+ //
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_iter_from_path
+ *
+ * @_path : a GnomeCmdFoldviewTreestore::Path
+ * @_iter_out : a GtkTreeIter
+ *
+ * Retrieves an iter from a Path.
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_iter_from_path(
+ const Path * _path,
+ GtkTreeIter * _iter_out)
+{
+ return ext_iter_from_path((Path*)_path, _iter_out);
+}
+gboolean
+GnomeCmdFoldviewTreestore::ext_iter_from_path(
+ Path * _path,
+ GtkTreeIter * _iter_out)
+{
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ gint depth = 0;
+ //.........................................................................
+ g_return_val_if_fail( _path, FALSE );
+
+ depth = 1;
+ node = node_root();
+
+loop:
+ node = node->children()->node_get(0);
+
+ while ( node )
+ {
+ if ( node->uid() == _path->uid_get(depth-1) )
+ {
+ if ( ++depth > _path->card() )
+ goto found;
+ else
+ goto loop;
+ }
+ node = node->next();
+ }
+
+ return FALSE;
+
+found:
+ //REFRESH_INF("Model::iter_find_from_base_path:Retrieved iter %s", path->dump());
+ ITER_FROM_NODE(this, _iter_out, node);
+ return TRUE;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_path_from_iter
+ *
+ * @_path : a GnomeCmdFoldviewTreestore::Path
+ * @_iter_out : a GtkTreeIter
+ *
+ * Return a mallocated Path from an iter
+ *
+ **/
+
+//=============================================================================
+GnomeCmdFoldviewTreestore::Path*
+GnomeCmdFoldviewTreestore::ext_path_from_iter(
+ GtkTreeIter * _iter_in)
+{
+ GnomeCmdFoldviewTreestore::Node * node = NULL;
+ gint depth = 0;
+ gint i = 1;
+ Path * path = NULL;
+ //.........................................................................
+ g_return_val_if_fail( _iter_in, FALSE );
+ g_return_val_if_fail( iter_is_valid(_iter_in), FALSE );
+
+ NODE_FROM_ITER(node, _iter_in);
+ g_return_val_if_fail( node, FALSE );
+
+ // build & fill a reverse path
+ depth = node->depth();
+ path = new Path(depth);
+
+ do
+ {
+ if ( node == node_root() )
+ {
+ NODE_ERR("GnomeCmdFoldviewTreestore::ext_path_from_iter():node root reached !");
+ delete path;
+ return NULL;
+ }
+
+ path->uid_set( depth - i, node->uid() );
+
+ node = node->parent();
+ }
+ while ( (i++) != depth );
+
+ return path;
+}
+
+
+//*****************************************************************************
+//* *
+//* Match functions *
+//* *
+//*****************************************************************************
+
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_match_child_gint:
+ *
+ * in_parent : a GtkTreeIter
+ * out_child : a GtkTreeIter
+ * gboolean(*match_function)(Data*, gint) : matching function
+ * the_gint : a gint
+ *
+ * For all childs of in_parent, call match_function(child->data, the_gint).
+ *
+ * If parent is NULL, test root nodes
+ *
+ * If it returns TRUE for a child, the function fills in out_child with
+ * this child and return TRUE.
+ *
+ * If matching_function return FALSE for all childs, return FALSE.
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_match_child_gint(
+ GtkTreeIter * in_parent ,
+ GtkTreeIter * out_child ,
+ gboolean(*match_function)(DataInterface*, gint) ,
+ gint the_gint)
+{
+ gint i = 0;
+ Node * node = NULL;
+ NodeBlock * block = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid_but_may_be_null(in_parent), FALSE );
+
+ if ( !in_parent )
+ node = node_root();
+ else
+ NODE_FROM_ITER(node, in_parent);
+
+ g_return_val_if_fail( node, FALSE );
+
+ block = node->children();
+ g_return_val_if_fail( block->card() != 0, FALSE );
+
+ while ( i < block->card() )
+ {
+ node = block->node_get(i++);
+ if ( match_function(node->data(), the_gint ) )
+ {
+ ITER_FROM_NODE(this, out_child, node);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//=============================================================================
+
+ /**
+ * GnomeCmdFoldviewTreestore::ext_match_child_collate_key:
+ *
+ * in_parent : a GtkTreeIter
+ * out_child : a GtkTreeIter
+ * collate_key_id : a gint identifying
+ * the collate key to use
+ * for the childs
+ * utf8_collate_key : a collate key
+ *
+ * For all childs of in_parent, compare child->collatekey &
+ * collate_key_to_use.
+ *
+ * If parent is NULL, test root nodes
+ *
+ * If it collate for a child, the function fills in out_child with
+ * this child and return TRUE.
+ *
+ * If no collate for all childs, return FALSE.
+ *
+ **/
+
+//=============================================================================
+gboolean
+GnomeCmdFoldviewTreestore::ext_match_child_str(
+ GtkTreeIter * in_parent ,
+ GtkTreeIter * out_child ,
+ const gchar * _str)
+{
+ gint i = 0;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ GnomeCmdFoldviewTreestore::NodeBlock *block = NULL;
+ //.........................................................................
+ g_return_val_if_fail ( iter_is_valid_but_may_be_null(in_parent), FALSE );
+
+ if ( !in_parent )
+ node = node_root();
+ else
+ NODE_FROM_ITER(node, in_parent);
+
+ g_return_val_if_fail( node, FALSE );
+
+ block = node->children();
+ g_return_val_if_fail( block->card() != 0, FALSE );
+
+ while ( i < block->card() )
+ {
+ node = block->node_get(i++);
+ // Previous method, with direct access to collate keys
+ // from DataInterface
+ //
+ //if ( strcmp
+ // (
+ // node->data()->utf8_collate_key(collate_key_id),
+ // utf8_collate_key
+ // ) == 0 )
+ if ( node->data()->compare_str(_str) == 0 )
+ {
+ ITER_FROM_NODE(this, out_child, node);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
// ###########################################################################
// ### ###
@@ -986,48 +2011,43 @@ GnomeCmdFoldviewTreestore::get_iter(
GtkTreePath *path)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
- GnomeCmdFoldviewTreestore::node_block *block = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ GnomeCmdFoldviewTreestore::NodeBlock *block = NULL;
gint *indices = NULL, pos = 0, depth =0;
gint i = 0;
//.........................................................................
g_assert( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel) );
- g_assert( path!=NULL );
-
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
+ g_assert( path );
indices = gtk_tree_path_get_indices(path);
depth = gtk_tree_path_get_depth(path);
- g_assert( indices );
- g_assert( depth > 0 );
-
- // foldview specific : we have only one toplevel node
+ // get the position
pos = indices[i++];
- g_assert( pos == 0 );
- // ok, get root node
- node = treestore->node_root();
+ // ok, get first root node ( first child of the ~root~ node )
+ node = treestore->node_root()->children()->node_get(pos);
- // treestore is empty !
- if ( ! node )
- return FALSE;
-
- // loop
- while ( i < depth )
+ while ( node )
{
- g_assert(node);
+ // path is done ?
+ if ( i == depth )
+ {
+ ITER_FROM_NODE(treestore, iter, node);
+ return TRUE;
+ }
- // go further
+ // node = node->children()->get_pos( indices[i++] );
block = node->children();
pos = indices[i++];
node = block->node_get(pos);
}
- g_assert(node);
+ if ( treestore->node_root()->children()->card() != 0 )
+ GCMD_ERR("GnomeCmdFoldviewTreestore::get_iter::failed to get iter from path");
- ITER_FROM_NODE(treestore, iter, node);
- return TRUE;
+ return FALSE;
}
@@ -1048,7 +2068,7 @@ GnomeCmdFoldviewTreestore::get_path(
{
GnomeCmdFoldviewTreestore *treestore = NULL;
GtkTreePath *path = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), NULL );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
@@ -1059,13 +2079,14 @@ GnomeCmdFoldviewTreestore::get_path(
NODE_FROM_ITER(node, iter);
g_return_val_if_fail( node, NULL );
- while ( node )
+ do
{
gtk_tree_path_prepend_index(path, node->pos());
node = node->parent();
}
+ while ( node != treestore->node_root() );
- STORE_INF("get_path:%s", gtk_tree_path_to_string(path));
+ //STORE_INF("get_path:%s", gtk_tree_path_to_string(path));
return path;
}
@@ -1089,19 +2110,24 @@ GnomeCmdFoldviewTreestore::get_value(
GValue *value)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
- g_return_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel) );
+ if ( ! IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel) ) goto fail;
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
- g_return_if_fail ( treestore->iter_is_valid(iter) );
- g_return_if_fail ( column == 0 );
- g_return_if_fail ( value );
+ if ( ! treestore->iter_is_valid(iter) ) goto fail;
+ //if ( column != 0 ) goto fail;
+ //if ( !value ) goto fail;
NODE_FROM_ITER(node, iter);
- g_assert(node);
+ if ( ! node ) goto fail;
g_value_init(value, G_TYPE_POINTER);
g_value_set_pointer(value, node->data());
+ return;
+
+fail:
+ g_value_init(value, G_TYPE_POINTER);
+ g_value_set_pointer(value, NULL);
}
@@ -1121,10 +2147,11 @@ GnomeCmdFoldviewTreestore::iter_next(
GtkTreeIter *iter)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), FALSE );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
+
g_return_val_if_fail ( treestore->iter_is_valid(iter), FALSE );
NODE_FROM_ITER(node, iter);
@@ -1161,10 +2188,11 @@ GnomeCmdFoldviewTreestore::iter_children(
GtkTreeIter *iter_parent)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), FALSE );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
+
g_return_val_if_fail ( treestore->iter_is_valid_but_may_be_null(iter_parent), FALSE );
if ( ! iter_parent )
@@ -1172,14 +2200,17 @@ GnomeCmdFoldviewTreestore::iter_children(
node = treestore->node_root();
g_return_val_if_fail( node, FALSE );
- ITER_FROM_NODE(treestore, iter_child, node);
+ if ( node->is_sterile() )
+ return FALSE;
+
+ ITER_FROM_NODE(treestore, iter_child, node->children()->node_get(0));
return TRUE;
}
NODE_FROM_ITER(node, iter_parent);
g_assert(node);
- if ( node->children()->card() )
+ if ( ! node->is_sterile() )
{
ITER_FROM_NODE(treestore, iter_child, node->children()->node_get(0));
return TRUE;
@@ -1205,7 +2236,7 @@ GnomeCmdFoldviewTreestore::iter_has_child(
GtkTreeIter *iter)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), FALSE );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
@@ -1236,17 +2267,17 @@ GnomeCmdFoldviewTreestore::iter_n_children(
GtkTreeIter *iter)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), 0 );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
g_return_val_if_fail ( treestore->iter_is_valid_but_may_be_null(iter), 0 );
- // We have only one node_root for instant
if ( ! iter )
- return 1;
+ node = treestore->node_root();
+ else
+ NODE_FROM_ITER(node, iter);
- NODE_FROM_ITER(node, iter);
g_assert(node);
return node->children()->card();
@@ -1275,26 +2306,26 @@ GnomeCmdFoldviewTreestore::iter_nth_child(
gint n)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
- GnomeCmdFoldviewTreestore::node_block *block = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
+ GnomeCmdFoldviewTreestore::NodeBlock *block = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), FALSE );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
g_return_val_if_fail ( treestore->iter_is_valid_but_may_be_null(iter_parent), FALSE );
if ( ! iter_parent )
+ node = treestore->node_root();
+ else
{
- ITER_FROM_NODE(treestore, iter_child, treestore->node_root());
- return TRUE;
+ NODE_FROM_ITER(node, iter_parent);
+ g_assert( node );
}
- NODE_FROM_ITER(node, iter_parent);
- g_assert( node );
-
block = node->children();
- if ( n >= block->card() )
- return FALSE;
+ g_assert( n < block->card() );
+ //if ( n >= block->card() )
+ //return FALSE;
ITER_FROM_NODE(treestore, iter_child, block->node_get(n));
return TRUE;
@@ -1317,7 +2348,7 @@ GnomeCmdFoldviewTreestore::iter_parent(
GtkTreeIter *iter_child)
{
GnomeCmdFoldviewTreestore *treestore = NULL;
- GnomeCmdFoldviewTreestore::node *node = NULL;
+ GnomeCmdFoldviewTreestore::Node *node = NULL;
//.........................................................................
g_return_val_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(treemodel), FALSE );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(treemodel);
@@ -1325,10 +2356,11 @@ GnomeCmdFoldviewTreestore::iter_parent(
NODE_FROM_ITER(node, iter_child);
g_assert( node );
- g_assert( node != treestore->node_root() );
+ g_assert( node->parent() );
node = node->parent();
g_assert( node );
+ //g_assert( node != treestore->node_root() );
ITER_FROM_NODE(treestore, iter_parent, node);
return TRUE;
@@ -1367,8 +2399,17 @@ static void
gnome_cmd_foldview_treestore_init(
GnomeCmdFoldviewTreestore *treestore)
{
+ // default sort settings
+ treestore->set_sort_type(GnomeCmdFoldviewTreestore::eSortAscending);
+ treestore->set_sort_collate_key_to_use(0);
+
+ //treestore->d_node_root = NULL;
+ //treestore->a_node_root_created = FALSE;
+
+ // others
treestore->stamp_init();
treestore->node_root_init();
+ treestore->uid_init();
}
//=============================================================================
@@ -1442,10 +2483,10 @@ gnome_cmd_foldview_treestore_finalize(GObject *object)
g_return_if_fail ( IS_GNOME_CMD_FOLDVIEW_TREESTORE(object) );
treestore = GNOME_CMD_FOLDVIEW_TREESTORE(object);
- gwr_inf("GnomeCmdFoldviewTreestore::finalize()");
+ GCMD_INF("GnomeCmdFoldviewTreestore::finalize()");
// free all records and free all memory used by the list
- treestore->clear();
+ treestore->ext_clear();
// must chain up - finalize parent
(* parent_class->finalize) (object);
@@ -1521,3 +2562,8 @@ gnome_cmd_foldview_treestore_new(void)
return t;
}
+
+
+
+
+
diff --git a/src/foldview/gnome-cmd-foldview-treestore.h b/src/foldview/gnome-cmd-foldview-treestore.h
index 43ea462..ab1f9e5 100644
--- a/src/foldview/gnome-cmd-foldview-treestore.h
+++ b/src/foldview/gnome-cmd-foldview-treestore.h
@@ -1,30 +1,37 @@
-#ifndef _GNOME_CMD_FOLDVIEW_TREESTORE_H_
-#define _GNOME_CMD_FOLDVIEW_TREESTORE_H_
-
-#include <gtk/gtk.h>
-
-//*****************************************************************************
-//
-// Docs
-//
-//*****************************************************************************
/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+ Tim-Philipp Müller
+
+ ***************************************************************************
+ Tim-Philipp Müller wrote the excellent "GTK+ 2.0 Tree View Tutorial" whose
+ section 11 'writing custom models' is the base of the
+ GnomeCmdFoldviewTreestore code.
+ ***************************************************************************
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
- GtkTreeIter usage:
- {
- gint stamp : ginu
- gpointer user_data : treestore data : pointer on node ( GnomeCmdFoldviewTreestore::node* )
- gpointer user_data2 : NULL ( for instant : this is the place for the collate key )
- gpointer user_data3 : treestore's user data
- }
-
- So for each valid GtkTreeIter, we have iter->node->data() == iter->user_data3 ;
- and a treestore's user can just do : get_iter(path), then (user's_type*)iter->user_data3
- instead of treestore->get_value(g_value_stuff...)
- Note that treestore code does that as well...
-
+#ifndef _GNOME_CMD_FOLDVIEW_TREESTORE_H_
+#define _GNOME_CMD_FOLDVIEW_TREESTORE_H_
-*/
+#include <gtk/gtk.h>
+#include "gnome-cmd-foldview-utils.h"
+#include "gnome-cmd-foldview-logger.h"
//*****************************************************************************
//
@@ -32,189 +39,369 @@
//
//*****************************************************************************
#define GNOME_CMD_FOLDVIEW_TREESTORE_TYPE (gnome_cmd_foldview_treestore_get_type())
-
#define GNOME_CMD_FOLDVIEW_TREESTORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_CMD_FOLDVIEW_TREESTORE_TYPE, GnomeCmdFoldviewTreestore))
-
#define IS_GNOME_CMD_FOLDVIEW_TREESTORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_CMD_FOLDVIEW_TREESTORE_TYPE))
+extern Logger sLogger;
+
struct GnomeCmdFoldviewTreestore
{
//=========================================================================
+ // Some common things
+ //=========================================================================
+ public:
+ enum eSortType
+ {
+ eSortNone = 0x00,
+ eSortAscending = 0x01,
+ eSortDescending = 0x02,
+ };
+
+ //=========================================================================
+ // Al structs, for crossed refs in this header
+ //=========================================================================
+ public:
+ struct Path;
+ struct DataInterface;
+
+ private:
+ struct Node;
+ struct Branch;
+ struct NodeBlock;
+
+ //=========================================================================
//
// Data
//
- // This structure is for :
+ // Instead of storing boring G_TYPES vars in the store, we can store
+ // any struct that inherits from GnomeCmdFoldviewTreestore::Data
+ // when using GnomeCmdFoldviewTreestore :)
+ //
+ // It allows :
+ //
+ // - calling delete on this store will directly call g_free on the
+ // users's data, that inherits from this struct.
//
- // - calling delete from the store, so indirectly calling destructor
- // of user's subclass automaically
- // - ensure we have a collate key
- // - debugging purpose
+ // - convention :
+ //
+ // DataInterface_A.compare_xxx(DataInterface_B)
+ //
+ // = 0 if DataInterface_A & DataInterface_B cant be ordered
+ //
+ // < 0 if A is before B
+ //
+ // > 0 if A is after B
//
//=========================================================================
- struct Data
+ public:
+ struct DataInterface
{
- private:
- static gint Count;
- //.................................................................
public:
- virtual const gchar* utf8_collate_key() = 0;
- //.................................................................
+ inline virtual ~DataInterface() {}
+
public:
- Data();
- virtual ~Data() = 0; // forbid instantiation
+ virtual gint compare (DataInterface*) = 0;
+ virtual gint compare_str (const gchar*) = 0;
+
+ public:
+ virtual void set_path_from_treestore (Path*) = 0;
+ virtual Path * path () = 0;
};
//=========================================================================
//
- // Nodes
+ // Node
//
//=========================================================================
- struct node_block;
-
- struct node
+ private:
+ struct Node
{
- friend struct node_block;
-
+ friend struct GnomeCmdFoldviewTreestore;
+ friend struct NodeBlock;
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ enum
+ {
+ e_UID_SHIFT = 0 ,
+ e_UID_BITS = GCMD_B32(00000000,00001111,11111111,11111111) ,
+ e_UID_MASK = ~e_UID_BITS ,
+
+ e_VISIBLE_SHIFT = 20 ,
+ e_VISIBLE_BITS = GCMD_B32(00000000,00010000,00000000,00000000) ,
+ e_VISIBLE_MASK = ~e_VISIBLE_BITS
+ };
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
static gint Count;
-
+ public:
+ static gint Remaining() { return Count; }
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
+ guint32 a_bits;
gint a_pos;
- node * a_parent;
- node * a_next;
- node_block * a_children;
- GnomeCmdFoldviewTreestore::Data * d_data;
- //.................................................................
- public:
- void* operator new (size_t size, gint _depth, gint _pos, node *_parent, GnomeCmdFoldviewTreestore::Data* _data);
+ Node * a_parent;
+ Node * a_next;
+ NodeBlock * a_children;
+ DataInterface * d_data;
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public:
+ void* operator new (size_t size);
void operator delete (void *p);
- //.................................................................
- public:
- const gchar* log();
- //.................................................................
- public:
- gint pos() { return a_pos; }
- node * parent() { return a_parent; }
- node * next() { return a_next; }
- node_block * children() { return a_children; }
- Data*& data() { return d_data; } // only this can be modified by all
- private:
- gint purge();
+ Node(guint32 _uid, gint _depth, gint _pos, Node *_parent, DataInterface* _data);
+ ~Node();
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ gint remove_child(gint _pos);
+ gint remove_children();
+ //.....................................................................
+ public:
+ const gchar* log ();
+ void dump_tree (gint _level = 0);
+
+ inline guint32 uid() { return ( a_bits & e_UID_BITS ) >> e_UID_SHIFT; }
+ inline gboolean visible() { return ( a_bits & e_VISIBLE_BITS ) != (guint32)0 ? TRUE : FALSE; }
+ inline gboolean hidden() { return ( a_bits & e_VISIBLE_BITS ) == (guint32)0 ? FALSE : TRUE; }
+ inline gint pos() { return a_pos; }
+ inline void inc_pos() { a_pos += 1; }
+ inline void dec_pos() { a_pos -= 1; }
+ inline void set_pos(gint _p) { a_pos = _p; }
+ inline gint depth() { return parent() ? parent()->children()->depth() : 0; }
+ inline Node * parent() { return a_parent; }
+ inline Node * next() { return a_next; }
+ inline void set_next(Node *_n) { a_next = _n; }
+ inline NodeBlock * children() { return a_children; }
+ inline gboolean is_sterile() { return a_children->empty(); }
+ inline DataInterface *& data() { return d_data; }
+ gint row();
};
//=========================================================================
//
- // Node blocks
+ // NodeBlock
//
//=========================================================================
- struct node_block
+ struct NodeBlock
{
+ friend struct GnomeCmdFoldviewTreestore;
+ friend struct Branch;
+ friend struct Node;
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
static gint Count;
-
+ public:
+ static gint Remaining() { return Count; }
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
gint a_card;
guint a_depth;
- node * a_parent;
+ Node * a_parent;
// d_nodes will be a GArray of node* ; we dont store entire node structs
- // for speeding the sort ; the counterpart is that we will be forced
- // to malloc each node
+ // for speeding the sort : we dont move struct, but only pointers. The
+ // counterpart is that we are forced to malloc each node
+ // We should use something lighter than a GArray // _GWR_TODO_
+
GArray * d_nodes;
- //.................................................................
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public:
- void* operator new (size_t size, guint _depth, node *_parent);
+ void* operator new (size_t size);
void operator delete (void *p);
- //.................................................................
- public:
- gint card() { return a_card; }
- guint depth() { return a_depth; }
- GArray* array() { return d_nodes; }
- //.................................................................
- private:
- // useless for instant
- //void node_cut (node *node);
+
+ NodeBlock (guint _depth, Node *_parent);
+ ~NodeBlock ();
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ gint remove_node (gint pos);
+ gint remove_nodes ();
+ //.....................................................................
public:
- node * node_get (gint index);
- node * node_append (Data *data);
- gint purge();
- gint purge_and_update();
+ inline gint card() { return a_card; }
+ inline gint empty() { return ! a_card; }
+ inline guint depth() { return a_depth; }
+ inline GArray* array() { return d_nodes; }
+
+ void reset();
+ Node * parent() { return a_parent; }
+ Node * node_get (gint pos);
+ Node * node_add (guint32 _uid, eSortType, gint _collate_key_to_use, DataInterface*);
+
};
//=========================================================================
//
- // Object
+ // Branch
//
//=========================================================================
+ private:
+ struct Branch
+ {
+ public:
+ void* operator new (size_t size);
+ void operator delete (void *p);
+
+ Branch();
+ Branch(Node*);
+ ~Branch();
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ Node * a_root;
+ Node * a_root_parent;
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ inline gboolean is_valid() { return (a_root && a_root_parent); }
+ inline Node * root() { return a_root; }
+ inline Node * parent() { return a_root_parent; }
+
+ Branch * dup();
+
+ gint cut();
+ gint cut_but_keep_root();
+
+ gboolean sort();
+ };
+
+ //=========================================================================
//
- // GObject inheritance
+ // Path
//
+ //=========================================================================
public:
- GObject parent;
+ struct Path
+ {
+ private:
+ gchar * d_ascii_dump;
+ gint a_card;
+ guint32 * d_uid;
+
+ public:
+ void * operator new (size_t size);
+ void operator delete (void *p);
+ Path (gint card);
+ ~Path ();
+ public:
+ gint card ();
+ guint32 uid_get (gint _pos);
+ void uid_set (gint _pos, guint32 _uid);
+ Path* dup ();
+ const gchar * dump ();
+ };
- //.........................................................................
- // root node
- //.........................................................................
+ //=========================================================================
+ //
+ // GnomeCmdFoldviewTreestore
+ //
+ //=========================================================================
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // GObject inheritance
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ GObject parent;
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // This one is THE root node, hidden, and father
+ // of all nodes
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
- node *d_node_root;
+ gboolean a_node_root_created;
+ Node * d_node_root;
+
public:
- node* node_root() { return d_node_root; }
- void node_root_init() { d_node_root = NULL; }
- //.........................................................................
+ inline Node * node_root() { return d_node_root; }
+ void node_root_init();
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // uids
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private:
+ guint32 a_uid;
+
+ public:
+ void uid_init() { a_uid = 0; }
+ guint32 uid_new() { return ++a_uid; }
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// stamp
- //.........................................................................
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private:
gint a_stamp;
- public:
- inline gint stamp() { return a_stamp; }
- void stamp_init() { a_stamp = 0x00; }
- //.........................................................................
- // rendering
- //.........................................................................
public:
- enum eRenderFlags
- {
- eSortAscending = 0x01,
- eSortDescending = 0x02,
- eSortCaseSensitive = 0x04
- };
- static eRenderFlags Render_flags;
+ inline gint stamp() { return a_stamp; }
+ void stamp_init() { a_stamp = 0x00; }
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // sorting
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ eSortType a_sort_type;
+ gint a_sort_collate_key_to_use;
public:
- static gboolean Render_sort() { return Render_flags != 0; }
- static gboolean Render_sort_case_sensitive() { return Render_flags & eSortCaseSensitive; }
- static gboolean Render_sort_ascending() { return Render_flags & eSortAscending; }
- static gboolean Render_sort_descending() { return Render_flags & eSortDescending; }
+ gboolean must_sort_ascending() { return a_sort_type == eSortAscending; }
+ gboolean must_sort_descending() { return a_sort_type == eSortDescending; }
public:
- gboolean set_render_flags(eRenderFlags flags)
+ void set_sort_type(eSortType sort_type)
+ {
+ a_sort_type = sort_type;
+ }
+ void set_sort_collate_key_to_use(gint sort_collate_key_to_use)
{
- eRenderFlags old = Render_flags;
- Render_flags = flags;
-
- if ( Render_sort_case_sensitive() )
- {
- if ( !Render_sort_ascending() && !Render_sort_descending() )
- {
- Render_flags = old;
- return FALSE;
- }
- }
-
- return TRUE;
+ a_sort_collate_key_to_use = sort_collate_key_to_use;
}
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // some helpers
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- public:
- gint refcount()
- {
- return ((GInitiallyUnowned*)this)->ref_count;
- }
+ //
+ // iter validation
+ //
+ private:
+ gboolean iter_is_valid(GtkTreeIter*);
+ gboolean iter_is_valid_but_may_be_null(GtkTreeIter*);
- //.........................................................................
- // GtkTreeModel interface
- //.........................................................................
+ //
+ // private helpers for sending signals
+ //
+ private:
+ void emit_row_inserted (Node*);
+ void emit_row_changed (Node*);
+ void emit_row_deleted (Node*);
+ void emit_row_has_child_toggled (Node*);
+
+ //
+ // private
+ //
+ private:
+ guint32 iter_get_uid (GtkTreeIter*);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // public extensions : useful for foldview
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ void ext_dump_tree (GtkTreeIter *);
+ void ext_add_child (GtkTreeIter *_in_parent, GtkTreeIter *_out_child, DataInterface*);
+ void ext_set_data (GtkTreeIter *in, DataInterface*);
+ void ext_data_changed (GtkTreeIter *in);
+ gboolean ext_get_data (GtkTreeIter *in, DataInterface**);
+ gint ext_clear();
+ gboolean ext_get_root (GtkTreeIter *in, GtkTreeIter *out_root);
+ gboolean ext_is_root (GtkTreeIter *in);
+ gint ext_iter_depth (GtkTreeIter *in);
+ gchar* ext_get_gtk_path_str_new (GtkTreeIter *in);
+ gint ext_iter_get_row (GtkTreeIter *in);
+ gint ext_iter_remove_children_no_signal_row_deleted (GtkTreeIter *in);
+ gint ext_iter_sterile_remove (GtkTreeIter *in);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // public extension : paths of uids
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ gboolean ext_iter_from_path( Path *path, GtkTreeIter *_iter_out);
+ gboolean ext_iter_from_path(const Path *path, GtkTreeIter *_iter_out);
+ Path* ext_path_from_iter(GtkTreeIter *_iter_in);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // public extension : perform action when matching
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ public:
+ gboolean ext_match_child_gint (GtkTreeIter *in_parent, GtkTreeIter *out_child, gboolean(*)(DataInterface*, gint), gint the_gint);
+ gboolean ext_match_child_str (GtkTreeIter *in_parent, GtkTreeIter *out_child, const gchar * the_str);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // GtkTreeModelIface implementation
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public:
static GtkTreeModelFlags get_flags (GtkTreeModel*);
static gint get_n_columns (GtkTreeModel*);
@@ -229,30 +416,19 @@ struct GnomeCmdFoldviewTreestore
static gint iter_n_children (GtkTreeModel*, GtkTreeIter *in_parent);
static gboolean iter_nth_child (GtkTreeModel*, GtkTreeIter *out_child, GtkTreeIter *in_parent, gint n);
static gboolean iter_parent (GtkTreeModel*, GtkTreeIter *out_parent, GtkTreeIter *in_child);
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Divers
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ void resort();
- //.........................................................................
- // our treestore methods
- //.........................................................................
- public:
- // iter validation
- inline gboolean iter_is_valid(GtkTreeIter*);
- inline gboolean iter_is_valid_but_may_be_null(GtkTreeIter*);
- // private helpers for sending signals
- private:
- void emit_row_inserted (node*);
- void emit_row_changed (node*);
- // useful for foldview
public:
- void add_child (GtkTreeIter *in_parent, GtkTreeIter *out_child, GnomeCmdFoldviewTreestore::Data*);
- void set_value (GtkTreeIter *in, gint column, GValue *value);
- gint remove_children (GtkTreeIter *in);
- gint clear();
+ gint refcount() { return ((GInitiallyUnowned*)this)->ref_count; }
+
};
GType gnome_cmd_foldview_treestore_get_type (void);
GnomeCmdFoldviewTreestore* gnome_cmd_foldview_treestore_new (void);
-
//*****************************************************************************
//
// Class Definition
@@ -262,11 +438,13 @@ GnomeCmdFoldviewTreestore* gnome_cmd_foldview_treestore_new (void);
#define IS_GNOME_CMD_FOLDVIEW_TREESTORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_CMD_FOLDVIEW_TREESTORE_TYPE))
#define GNOME_CMD_FOLDVIEW_TREESTORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_CMD_FOLDVIEW_TREESTORE_TYPE, GnomeCmdFoldviewTreestoreClass))
-typedef struct _GnomeCmdFoldviewTreestoreClass GnomeCmdFoldviewTreestoreClass;
struct _GnomeCmdFoldviewTreestoreClass
{
GObjectClass parent_class;
};
+typedef struct _GnomeCmdFoldviewTreestoreClass GnomeCmdFoldviewTreestoreClass;
+
+
#endif
diff --git a/src/foldview/gnome-cmd-foldview-utils.h b/src/foldview/gnome-cmd-foldview-utils.h
new file mode 100644
index 0000000..ac7c7eb
--- /dev/null
+++ b/src/foldview/gnome-cmd-foldview-utils.h
@@ -0,0 +1,261 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyleft 2010-2010 Guillaume Wardavoir
+
+ This program 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.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GCMDGTKFOLDVIEW_UTILS_H__
+#define __GCMDGTKFOLDVIEW_UTILS_H__
+
+#include <glib.h>
+
+// ***************************************************************************
+//
+// Some macros
+//
+// ***************************************************************************
+#define GCMD_STRINGIZE(a) #a
+#define GCMD_LABEL __attribute__ ((unused)) asm("nop");
+
+// ***************************************************************************
+//
+// Macros for inserting binary numbers in source code ( up to 32 bits )
+//
+// endianness : b1 is lsb :
+//
+// MB32(b4,b3,b2,b1) = b1 + 2^8 * b2 + ... + 2^24 * b4
+//
+// I know there are too many parenthesis, but gcc complains
+//
+// ***************************************************************************
+
+//
+// helper macros
+//
+
+//
+// GCMD_HEX_(token)
+//
+// Convert a 8-binary-token to a 32 bits integer
+//
+// b8_max =
+// 11111111 ->
+// 0x11111111LU ->
+// binary 0001 0001 0001 0001 0001 0001 0001 0001
+//
+// So b8_max fits in 32 bits
+//
+#define GCMD_HEX_(token) \
+ (guint32)(0x##token##LU)
+//
+// 8-bit conversion macro, takes a the result of GCMD_HEX_() as input
+//
+#define GCMD_B8_(x) \
+( \
+ ( (x & 0x00000001) ? 0x01 : 0 ) \
+ + ( (x & 0x00000010) ? 0x02 : 0 ) \
+ + ( (x & 0x00000100) ? 0x04 : 0 ) \
+ + ( (x & 0x00001000) ? 0x08 : 0 ) \
+ + ( (x & 0x00010000) ? 0x10 : 0 ) \
+ + ( (x & 0x00100000) ? 0x20 : 0 ) \
+ + ( (x & 0x01000000) ? 0x40 : 0 ) \
+ + ( (x & 0x10000000) ? 0x80 : 0 ) \
+)
+//
+// The two above macros in one
+//
+#define GCMD_B8(b) \
+ ( GCMD_B8_( GCMD_HEX_(b) ) )
+
+
+//
+// 32 bits
+//
+#define GCMD_B32(b4,b3,b2,b1) \
+( \
+ (guint32) \
+ ( \
+ ( ((guint32)GCMD_B8(b1)) ) \
+ + ( ((guint32)GCMD_B8(b2)) << 8 ) \
+ + ( ((guint32)GCMD_B8(b3)) << 16 ) \
+ + ( ((guint32)GCMD_B8(b4)) << 24 ) \
+ ) \
+)
+
+
+// ***************************************************************************
+//
+// GStruct
+//
+// ***************************************************************************
+//
+// I like & trust glib memory management.
+// This template is for avoiding overloading new / delete in all structs.
+//
+// There are many GStruct<> template-constructors, for handling
+// the number of constructor parameters of any "T" ( I tried va_args but
+// didnt succeed ).
+//
+// Exercice : add a template parameter N, representing the number of arguments
+// of T constructor, and autogenerate the GStruct<T,N> constructors
+// with recursive templates.
+//
+template <typename T> struct GcmdStruct : public T
+{
+ public:
+
+ void* operator new(size_t size)
+ {
+ GcmdStruct<T>* g = g_try_new0(GcmdStruct<T>, 1);
+
+ if ( !g )
+ g_critical("GStruct<%s>::new():g_try_new0 failed", GCMD_STRINGIZE(T));
+
+ return g;
+ }
+
+ void operator delete (void *p)
+ {
+ g_free(p);
+ }
+
+ GcmdStruct() : T() {}
+ template <typename U1> GcmdStruct(U1 u1) : T(u1) {}
+ template <typename U1, typename U2> GcmdStruct(U1 u1, U2 u2) : T(u1, u2) {}
+ template <typename U1, typename U2, typename U3> GcmdStruct(U1 u1, U2 u2, U3 u3) : T(u1, u2, u3) {}
+ template <typename U1, typename U2, typename U3, typename U4> GcmdStruct(U1 u1, U2 u2, U3 u3, U4 u4) : T(u1, u2, u3, u4) {}
+ template <typename U1, typename U2, typename U3, typename U4, typename U5> GcmdStruct(U1 u1, U2 u2, U3 u3, U4 u4, U5 u5) : T(u1, u2, u3, u4, u5) {}
+
+ virtual ~GcmdStruct<T>() {}
+};
+
+//
+// The GStruct<> struct comes with a convenience macro for
+// creating new instances of GStruct<> - and its free of charge.
+//
+#define GCMD_STRUCT_NEW_CAST( type, ... ) (type*) ( new GcmdStruct<type>(__VA_ARGS__) )
+#define GCMD_STRUCT_NEW( type, ... ) ( new GcmdStruct<type>(__VA_ARGS__) )
+
+// ***************************************************************************
+//
+// Logging
+//
+// ***************************************************************************
+enum eLogChannel
+{
+ // common
+ eLogGcmd = 0,
+ eLogLeaks = 1,
+
+ // control
+ eLogFifo = 5,
+ eLogMsg = 6,
+
+ // model
+ eLogFiles = 10,
+ eLogRefresh = 11,
+ eLogSort = 12,
+ eLogEnumerate = 13,
+ eLogCheck = 14,
+ eLogExpand = 15,
+ eLogMonitor = 16,
+
+ eLogTreeNode = 20,
+ eLogTreeBlock = 21,
+ eLogTreeStore = 22
+};
+
+#define GCMD_LOG_HELPER(_c, _f, ...) (sLogger.log_function(_c, _f))(sLogger.header(_c), __VA_ARGS__);
+//.....................................................................
+#define GCMD_INF(...) GCMD_LOG_HELPER(eLogGcmd, Logger::eLogInf, __VA_ARGS__)
+#define GCMD_WNG(...) GCMD_LOG_HELPER(eLogGcmd, Logger::eLogWng, __VA_ARGS__)
+#define GCMD_ERR(...) GCMD_LOG_HELPER(eLogGcmd, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define LEAKS_INF(...) GCMD_LOG_HELPER(eLogLeaks, Logger::eLogInf, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define FIFO_INF(...) GCMD_LOG_HELPER(eLogFifo, Logger::eLogInf, __VA_ARGS__)
+#define FIFO_WNG(...) GCMD_LOG_HELPER(eLogFifo, Logger::eLogWng, __VA_ARGS__)
+#define FIFO_ERR(...) GCMD_LOG_HELPER(eLogFifo, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define MSG_INF(...) GCMD_LOG_HELPER(eLogMsg, Logger::eLogInf, __VA_ARGS__)
+#define MSG_WNG(...) GCMD_LOG_HELPER(eLogMsg, Logger::eLogWng, __VA_ARGS__)
+#define MSG_ERR(...) GCMD_LOG_HELPER(eLogMsg, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define FILES_INF(...) GCMD_LOG_HELPER(eLogFiles, Logger::eLogInf, __VA_ARGS__)
+#define FILES_WNG(...) GCMD_LOG_HELPER(eLogFiles, Logger::eLogWng, __VA_ARGS__)
+#define FILES_ERR(...) GCMD_LOG_HELPER(eLogFiles, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define REFRESH_INF(...) GCMD_LOG_HELPER(eLogRefresh, Logger::eLogInf, __VA_ARGS__)
+#define REFRESH_WNG(...) GCMD_LOG_HELPER(eLogRefresh, Logger::eLogWng, __VA_ARGS__)
+#define REFRESH_ERR(...) GCMD_LOG_HELPER(eLogRefresh, Logger::eLogErr, __VA_ARGS__)
+#define REFRESH_TKI(...) GCMD_LOG_HELPER(eLogRefresh, Logger::eLogTki, __VA_ARGS__)
+#define REFRESH_TKW(...) GCMD_LOG_HELPER(eLogRefresh, Logger::eLogTkw, __VA_ARGS__)
+#define REFRESH_TKE(...) GCMD_LOG_HELPER(eLogRefresh, Logger::eLogTke, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define SORT_INF(...) GCMD_LOG_HELPER(eLogSort, Logger::eLogInf, __VA_ARGS__)
+#define SORT_WNG(...) GCMD_LOG_HELPER(eLogSort, Logger::eLogWng, __VA_ARGS__)
+#define SORT_ERR(...) GCMD_LOG_HELPER(eLogSort, Logger::eLogErr, __VA_ARGS__)
+#define SORT_TKI(...) GCMD_LOG_HELPER(eLogSort, Logger::eLogTki, __VA_ARGS__)
+#define SORT_TKW(...) GCMD_LOG_HELPER(eLogSort, Logger::eLogTkw, __VA_ARGS__)
+#define SORT_TKE(...) GCMD_LOG_HELPER(eLogSort, Logger::eLogTke, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define ENUMERATE_INF(...) GCMD_LOG_HELPER(eLogEnumerate, Logger::eLogInf, __VA_ARGS__)
+#define ENUMERATE_WNG(...) GCMD_LOG_HELPER(eLogEnumerate, Logger::eLogWng, __VA_ARGS__)
+#define ENUMERATE_ERR(...) GCMD_LOG_HELPER(eLogEnumerate, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define CHECK_INF(...) GCMD_LOG_HELPER(eLogCheck, Logger::eLogInf, __VA_ARGS__)
+#define CHECK_WNG(...) GCMD_LOG_HELPER(eLogCheck, Logger::eLogWng, __VA_ARGS__)
+#define CHECK_ERR(...) GCMD_LOG_HELPER(eLogCheck, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define EXPAND_INF(...) GCMD_LOG_HELPER(eLogExpand, Logger::eLogInf, __VA_ARGS__)
+#define EXPAND_WNG(...) GCMD_LOG_HELPER(eLogExpand, Logger::eLogWng, __VA_ARGS__)
+#define EXPAND_ERR(...) GCMD_LOG_HELPER(eLogExpand, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define MONITOR_INF(...) GCMD_LOG_HELPER(eLogMonitor, Logger::eLogInf, __VA_ARGS__)
+#define MONITOR_WNG(...) GCMD_LOG_HELPER(eLogMonitor, Logger::eLogWng, __VA_ARGS__)
+#define MONITOR_ERR(...) GCMD_LOG_HELPER(eLogMonitor, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define NODE_INF(...) GCMD_LOG_HELPER(eLogTreeNode, Logger::eLogInf, __VA_ARGS__)
+#define NODE_WNG(...) GCMD_LOG_HELPER(eLogTreeNode, Logger::eLogWng, __VA_ARGS__)
+#define NODE_ERR(...) GCMD_LOG_HELPER(eLogTreeNode, Logger::eLogErr, __VA_ARGS__)
+#define NODE_TKI(...) GCMD_LOG_HELPER(eLogTreeNode, Logger::eLogTki, __VA_ARGS__)
+#define NODE_TKW(...) GCMD_LOG_HELPER(eLogTreeNode, Logger::eLogTkw, __VA_ARGS__)
+#define NODE_TKE(...) GCMD_LOG_HELPER(eLogTreeNode, Logger::eLogTke, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define BLOCK_INF(...) GCMD_LOG_HELPER(eLogTreeBlock, Logger::eLogInf, __VA_ARGS__)
+#define BLOCK_WNG(...) GCMD_LOG_HELPER(eLogTreeBlock, Logger::eLogWng, __VA_ARGS__)
+#define BLOCK_ERR(...) GCMD_LOG_HELPER(eLogTreeBlock, Logger::eLogErr, __VA_ARGS__)
+// ---------------------------------------------------------------------------
+#define STORE_INF(...) GCMD_LOG_HELPER(eLogTreeStore, Logger::eLogInf, __VA_ARGS__)
+#define STORE_WNG(...) GCMD_LOG_HELPER(eLogTreeStore, Logger::eLogWng, __VA_ARGS__)
+#define STORE_ERR(...) GCMD_LOG_HELPER(eLogTreeStore, Logger::eLogErr, __VA_ARGS__)
+
+//*****************************************************************************
+//
+// GtkTreeIter macros
+//
+//*****************************************************************************
+
+#define GCMD_ITER_COPY(dest, src) \
+ (dest)->stamp = (src)->stamp; \
+ (dest)->user_data = (src)->user_data; \
+ (dest)->user_data2 = (src)->user_data2; \
+ (dest)->user_data3 = (src)->user_data3;
+
+
+#endif //__GCMDGTKFOLDVIEW_UTILS_H__
diff --git a/src/foldview/gnome-cmd-foldview.cc b/src/foldview/gnome-cmd-foldview.cc
index d30fbc5..3a3c985 100644
--- a/src/foldview/gnome-cmd-foldview.cc
+++ b/src/foldview/gnome-cmd-foldview.cc
@@ -1,17 +1,15 @@
/*
+ ###########################################################################
+
+ gnome-cmd-foldview-private.h
+
+ ---------------------------------------------------------------------------
+
GNOME Commander - A GNOME based file manager
Copyright (C) 2001-2006 Marcus Bjurman
Copyright (C) 2007-2010 Piotr Eljasiak
Copyright (C) 2010-2010 Guillaume Wardavoir
- ---------------------------------------------------------------------------
-
- C++
-
- Contain variadic macros
-
- ---------------------------------------------------------------------------
-
This program 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
@@ -25,289 +23,242 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
+ ---------------------------------------------------------------------------
+
+ - Public methods
+ - GcmdGtkFoldview GObject
+
+ ###########################################################################
+*/
#include <config.h>
#include <stdlib.h>
-
+// ...........................................................................
#include <gtk/gtksignal.h>
#include <gtk/gtkvbox.h>
#include <libgnomevfs/gnome-vfs.h>
#include <libgnomevfs/gnome-vfs-utils.h>
-
-#include "gnome-cmd-includes.h"
+// ...........................................................................
+#include "gnome-cmd-foldview-private.h"
+//#include "gnome-cmd-includes.h"
#include "gnome-cmd-combo.h"
#include "gnome-cmd-main-win.h"
#include "gnome-cmd-style.h"
#include "gnome-cmd-data.h"
-
-#include "gnome-cmd-foldview-private.h"
-#include "gnome-cmd-foldview-gvfs.h"
-
-// ***************************************************************************
-// * *
-// * Defines *
-// * *
-// ***************************************************************************
-
-#define GVFS_MAX_ASYNC_OPS 10000
-#define GVFS_ITEMS_PER_NOTIFICATION 30
-
-// ***************************************************************************
-// * *
-// * Helpers *
-// * *
-// ***************************************************************************
-
-//=============================================================================
-// Common vars
-//=============================================================================
-static GnomeVFSResult sVFSResult = GNOME_VFS_OK; // for sync operations
+#include "gnome-cmd-con-list.h"
+#include "gnome-cmd-con-smb.h"
+// ...........................................................................
+#include "gnome-cmd-connection-treeview.h"
extern GnomeCmdMainWin *main_win;
+Logger sLogger(30);
// ###########################################################################
// ### ###
// ## ##
-// # Logging #
+// # Public methods #
// ## ##
// ### ###
// ###########################################################################
+void
+gnome_cmd_foldview_update_style(GtkWidget *widget)
+{
+ //g_return_if_fail( widget != NULL );
+ //(GCMDGTKFOLDVIEW(widget))->view.update_style();
+}
-//=============================================================================
-// Logger
-//=============================================================================
-/*
- <ESC>[{attr};{fg};{bg}m
-
-{attr} needs to be one of the following:
- 0 Reset All Attributes (return to normal mode)
- 1 Bright (usually turns on BOLD)
- 2 Dim
- 3 Underline
- 5 Blink
- 7 Reverse
- 8 Hidden
-
-{fg} needs to be one of the following:
- 30 Black
- 31 Red
- 32 Green
- 33 Yellow
- 34 Blue
- 35 Magenta
- 36 Cyan
- 37 White
-
-{bg} needs to be one of the following:
- 40 Black
- 41 Red
- 42 Green
- 43 Yellow
- 44 Blue
- 45 Magenta
- 46 Cyan
- 47 White
-*/
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Core logging
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-static char sLogStr [1024];
-static char sLogStrFinal[1024];
+GtkWidget*
+gnome_cmd_foldview_new()
+{
+ return gcmdgtkfoldview_new();
+}
-void gwr_print(const char* str)
+// ###########################################################################
+// ### ###
+// ## ##
+// # GcmdGtkFoldview::HeadBand #
+// ## ##
+// ### ###
+// ###########################################################################
+GcmdGtkFoldview::HeadBand::HeadBand(
+GcmdGtkFoldview * _foldview)
{
- sprintf(sLogStrFinal,"%s%s", str,sLogStr);
- printf("%s\n",sLogStrFinal);
+ d_hbox_main = gtk_hbox_new(FALSE, 0);
+ d_button_add = gtk_button_new();
+ d_con_combo = (GtkWidget*)( new GnomeCmdCombo(2, 1, NULL) );
+ d_alignement_padder = gtk_alignment_new(1.0f, 1.0f, 1.0f, 1.0f);
+ d_button_up = gtk_button_new();
+ d_arrow_up = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE);
+ d_button_down = gtk_button_new();
+ d_arrow_down = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+
+ //.........................................................................
+ //
+ // Setup
+ //
+
+ // connection combo
+ //gtk_object_set_data_full (GTK_OBJECT (_foldview), "con_combo", m_con_combo, (GtkDestroyNotify) g_object_unref);
+ gtk_widget_set_size_request (d_con_combo, 150, -1);
+ gtk_clist_set_row_height (GTK_CLIST (GNOME_CMD_COMBO (d_con_combo)->list), 20);
+ gtk_entry_set_editable (GTK_ENTRY (GNOME_CMD_COMBO (d_con_combo)->entry), FALSE);
+ gtk_clist_set_column_width (GTK_CLIST (GNOME_CMD_COMBO (d_con_combo)->list), 0, 20);
+ gtk_clist_set_column_width (GTK_CLIST (GNOME_CMD_COMBO (d_con_combo)->list), 1, 60);
+ GTK_WIDGET_UNSET_FLAGS (GNOME_CMD_COMBO (d_con_combo)->button, GTK_CAN_FOCUS);
+
+ // buttons
+ gtk_button_set_image(GTK_BUTTON(d_button_add), gtk_image_new_from_pixbuf(GcmdGtkFoldview::s_gdk_pixbuf[eIconGtkAdd]));
+ gtk_button_set_image(GTK_BUTTON(d_button_up), d_arrow_up);
+ gtk_button_set_image(GTK_BUTTON(d_button_down), d_arrow_down);
+
+ g_signal_connect(d_button_add, "clicked", G_CALLBACK(Signal_button_add_clicked), (gpointer)_foldview);
+ g_signal_connect(d_button_up, "clicked", G_CALLBACK(Signal_button_up_clicked), (gpointer)_foldview);
+ g_signal_connect(d_button_down, "clicked", G_CALLBACK(Signal_button_down_clicked), (gpointer)_foldview);
+
+ //.........................................................................
+ //
+ // Packing
+ //
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_add, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_con_combo, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_alignement_padder, TRUE , TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_up, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(d_hbox_main), d_button_down, FALSE, TRUE, 0);
}
-void gwr_inf(const char* fmt, ...)
+GcmdGtkFoldview::HeadBand::~HeadBand()
{
- #ifndef DEBUG_SHOW_INF
- return;
- #endif
- va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
- gwr_print("\033[0;32mINF:\033[0m");
}
-void gwr_wng(const char* fmt, ...)
+
+void
+GcmdGtkFoldview::HeadBand::show()
{
- #ifndef DEBUG_SHOW_WNG
- return;
- #endif
- va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
- gwr_print("\033[0;35mWNG:\033[0m");
+ gtk_widget_show_all(d_hbox_main);
+ GNOME_CMD_COMBO(d_con_combo)->select_data((gpointer)gnome_cmd_con_list_get_home(gnome_cmd_con_list_get()));
}
-void gwr_err(const char* fmt, ...)
+void
+GcmdGtkFoldview::HeadBand::hide()
{
- #ifndef DEBUG_SHOW_ERR
- return;
- #endif
- va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
- gwr_print("\033[0;31mERR:\033[0m");
+ gtk_widget_hide_all(d_hbox_main);
}
-void gwr_inf_vfs(const char* fmt, ...)
+void
+GcmdGtkFoldview::HeadBand::update_style()
{
- #ifndef DEBUG_SHOW_VFS
- return;
- #endif
- va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
- strcat(sLogStr, " [VFS-INF:");
- strcat(sLogStr, gnome_vfs_result_to_string(sVFSResult));
- strcat(sLogStr, "]");
- gwr_print("\033[0;31mERR:\033[0m");
+ ((GnomeCmdCombo*)d_con_combo)->update_style();
}
-void gwr_err_vfs(const char* fmt, ...)
+// ===========================================================================
+// Connection combo specific
+// ===========================================================================
+void
+GcmdGtkFoldview::HeadBand::reset_connections()
{
- #ifndef DEBUG_SHOW_VFS
- return;
- #endif
- va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
- strcat(sLogStr, " [VFS-ERR:");
- strcat(sLogStr, gnome_vfs_result_to_string(sVFSResult));
- strcat(sLogStr, "]");
- gwr_print("\033[0;31mERR:\033[0m");
+ GnomeCmdCombo * combo = NULL;
+ //.........................................................................
+ combo = GNOME_CMD_COMBO(d_con_combo);
+
+ combo->clear();
+ combo->highest_pixmap = 20;
+ combo->widest_pixmap = 20;
+ gtk_clist_set_row_height (GTK_CLIST (combo->list), 20);
+ gtk_clist_set_column_width (GTK_CLIST (combo->list), 0, 20);
}
+void
+GcmdGtkFoldview::HeadBand::add_connection(
+ GnomeCmdCon * _con)
+{
+ GnomeCmdCombo * combo = NULL;
+ gchar * text [3];
+ gint row = 0;
+ //.........................................................................
+ combo = GNOME_CMD_COMBO(d_con_combo);
+
+ text[0] = NULL;
+ text[1] = (gchar *)gnome_cmd_con_get_alias(_con);
+ text[2] = NULL;
+
+ GnomeCmdPixmap *pixmap = gnome_cmd_con_get_go_pixmap(_con);
+ if (pixmap)
+ {
+ row = combo->append(text, _con);
+ combo->set_pixmap(row, 0, pixmap);
+ }
+}
-// ###########################################################################
-// ### ###
-// ## ##
-// # Divers #
-// ## ##
-// ### ###
-// ###########################################################################
-GcmdGtkFoldview::eFileAccess GcmdGtkFoldview::Access_from_permissions(
- GnomeVFSFilePermissions permissions)
-{
- eFileAccess access = eAccessUnknown;
- gboolean b_read = FALSE;
- gboolean b_write = FALSE;
- if ( ( permissions & GNOME_VFS_PERM_ACCESS_READABLE ) != 0 ) b_read = TRUE;
- if ( ( permissions & GNOME_VFS_PERM_ACCESS_WRITABLE ) != 0 ) b_write = TRUE;
- if ( b_read )
- {
- access = ( b_write ? eAccessReadWrite : eAccessReadOnly );
- }
- else
- {
- access = ( b_write ? eAccessUnknown : eAccessForbidden );
- }
- return access;
+gboolean
+GcmdGtkFoldview::HeadBand::can_add_that_connection(
+ GnomeCmdCon * _con)
+{
+ // dont add connection if
+ // it is closed AND it is not a device AND it is not smb
+ if (
+ !gnome_cmd_con_is_open (_con) &&
+ !GNOME_CMD_IS_CON_DEVICE (_con) &&
+ !GNOME_CMD_IS_CON_SMB (_con)
+ ) return FALSE;
+
+ return TRUE;
}
-GcmdGtkFoldview::View::eIcon GcmdGtkFoldview::View::Icon_from_type_permissions(
- GnomeVFSFileType type,
- GnomeVFSFilePermissions permissions)
+
+void
+GcmdGtkFoldview::HeadBand::update_connections()
{
- eFileAccess access = eAccessUnknown;
+ GnomeCmdCombo * combo = NULL;
+ GList * l = NULL;
+ //.........................................................................
- access = Access_from_permissions(permissions);
+ combo = GNOME_CMD_COMBO(d_con_combo);
- return Icon_from_type_access(type, access);
-}
+ reset_connections();
-GcmdGtkFoldview::View::eIcon GcmdGtkFoldview::View::Icon_from_type_access(
- GnomeVFSFileType type,
- GcmdGtkFoldview::eFileAccess access)
-{
- if ( type == GNOME_VFS_FILE_TYPE_DIRECTORY )
- {
- switch ( access )
- {
- case eAccessReadWrite: return GcmdGtkFoldview::View::eIconDirReadWrite; break;
- case eAccessReadOnly : return GcmdGtkFoldview::View::eIconDirReadOnly; break;
- case eAccessForbidden: return GcmdGtkFoldview::View::eIconDirForbidden; break;
- default : return GcmdGtkFoldview::View::eIconUnknown; break;
- }
- }
+ for ( l = gnome_cmd_con_list_get_all(gnome_cmd_con_list_get ()); l ; l = l->next )
+ {
+ GnomeCmdCon *con = (GnomeCmdCon *)l->data;
- if ( type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK )
- {
- switch ( access )
- {
- case eAccessReadWrite: return GcmdGtkFoldview::View::eIconSymlinkToDirReadWrite; break;
- case eAccessReadOnly : return GcmdGtkFoldview::View::eIconSymlinkToDirReadOnly; break;
- case eAccessForbidden: return GcmdGtkFoldview::View::eIconSymlinkToDirForbidden; break;
- default : return GcmdGtkFoldview::View::eIconUnknown; break;
- }
- }
+ if ( ! can_add_that_connection(con) )
+ continue;
- return View::eIconUnknown;
+ // else add it
+ add_connection(con);
+ }
}
-
+GnomeCmdCon*
+GcmdGtkFoldview::HeadBand::get_selected_connection()
+{
+ return GNOME_CMD_CON(GNOME_CMD_COMBO(d_con_combo)->sel_data);
+}
// ###########################################################################
// ### ###
// ## ##
-// # GcmdGtkFoldview #
+// # GcmdGtkFoldview #
// ## ##
// ### ###
// ###########################################################################
-// ***************************************************************************
-// * *
-// * Singleton impl *
-// * *
-// ***************************************************************************
-
-//
-// ~ The ~ singleton
-//
-static GtkWidget* GcmdGtkFoldviewSingleton = NULL;
-
+// ###########################################################################
//
-// Singleton accessors
+// GcmdGtkFoldview : GObject
//
-GtkWidget* GcmdWidget()
-{
- if ( GcmdGtkFoldviewSingleton != NULL )
- return GcmdGtkFoldviewSingleton;
-
- GcmdGtkFoldviewSingleton = gcmdgtkfoldview_new();
-
- // assume ownership:
- // ensure foldview will not be destroyed when showing / hiding
- g_object_ref_sink(GcmdGtkFoldviewSingleton);
-
- return GcmdGtkFoldviewSingleton;
-}
-
-GcmdGtkFoldview* GcmdFoldview()
-{
- return (GcmdGtkFoldview*)( GcmdWidget() );
-}
-
-// ***************************************************************************
-// * *
-// * GObject impl *
-// * *
-// ***************************************************************************
-
-static void gcmdgtkfoldview_class_init(GcmdGtkFoldviewClass *klass);
-
+// ###########################################################################
enum
{
GCMDGTKFOLDVIEW_SIGNAL,
LAST_SIGNAL
};
-static guint gcmdgtkfoldview_signals[LAST_SIGNAL] = { 0 };
+static void gcmdgtkfoldview_class_init(GcmdGtkFoldviewClass *klass);
+static guint gcmdgtkfoldview_signals[LAST_SIGNAL] = { 0 };
-//=============================================================================
-//
-// Pure GObject stuff
-//
-//=============================================================================
+ GObjectClass * GcmdGtkFoldview::Parent_class = NULL;
-//-----------------------------------------------------------------------------
-// GcmdGtkFoldview GType implementation
-//-----------------------------------------------------------------------------
+// ===========================================================================
GType
gcmdgtkfoldview_get_type (void)
{
@@ -325,7 +276,7 @@ gcmdgtkfoldview_get_type (void)
NULL, /* class_data */
sizeof (GcmdGtkFoldview),
0,
- (GInstanceInitFunc)GcmdGtkFoldview::Control_g_object_init,
+ (GInstanceInitFunc)GcmdGtkFoldview::G_object_init,
};
fv_type = g_type_register_static(GTK_TYPE_VBOX, "gtkGcmdFoldview", &fv_info, (GTypeFlags)0);
@@ -333,10 +284,6 @@ gcmdgtkfoldview_get_type (void)
return fv_type;
}
-
-//-----------------------------------------------------------------------------
-// GcmdGtkFoldview class initialization
-//-----------------------------------------------------------------------------
static void
gcmdgtkfoldview_class_init (GcmdGtkFoldviewClass *klass)
{
@@ -356,73 +303,399 @@ gcmdgtkfoldview_class_init (GcmdGtkFoldviewClass *klass)
GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
- GcmdGtkFoldview::Control_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
+ GcmdGtkFoldview::Parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
// override dispose & finalize
- gtk_object_class->destroy = GcmdGtkFoldview::Control_gtk_object_destroy;
- g_object_class->dispose = GcmdGtkFoldview::Control_g_object_dispose;
- g_object_class->finalize = GcmdGtkFoldview::Control_g_object_finalize;
+ gtk_object_class->destroy = GcmdGtkFoldview::Gtk_object_destroy;
+ g_object_class->dispose = GcmdGtkFoldview::G_object_dispose;
+ g_object_class->finalize = GcmdGtkFoldview::G_object_finalize;
}
-
GtkWidget*
gcmdgtkfoldview_new ()
{
- return GTK_WIDGET (g_object_new (GCMDGTKFOLDVIEW_TYPE, NULL));
+ return GTK_WIDGET(g_object_new (GCMDGTKFOLDVIEW_TYPE, NULL));
}
-
-// ###########################################################################
-// ### ###
-// ## ##
-// # Public methods #
-// ## ##
-// ### ###
-// ###########################################################################
+// ===========================================================================
void
-gnome_cmd_foldview_update_style(GtkWidget *widget)
+GcmdGtkFoldview::G_object_init (GcmdGtkFoldview *foldview)
+{
+ foldview->init_instance();
+}
+void GcmdGtkFoldview::Gtk_object_destroy(GtkObject* object)
+{
+ //g_return_if_fail( IS_GCMDGTKFOLDVIEW(object) );
+ //GCMD_INF("Control_gtk_object_destroy:%03i", GCMDGTKFOLDVIEW(object)->control_ref_count());
+ GCMD_INF("GcmdGtkFoldview::Control_gtk_object_destroy");
+
+ GCMDGTKFOLDVIEW(object)->dispose();
+
+ (* GTK_OBJECT_CLASS (Parent_class)->destroy)(object);
+}
+void GcmdGtkFoldview::G_object_dispose(GObject* object)
{
- g_return_if_fail( widget != NULL );
+ //g_return_if_fail( IS_GCMDGTKFOLDVIEW(object) );
+ //GCMD_INF("Control_g_object_dispose:%03i", GCMDGTKFOLDVIEW(object)->control_ref_count());
+ GCMD_INF("GcmdGtkFoldview::Control_g_object_dispose");
- (GCMDGTKFOLDVIEW(widget))->view.update_style();
+ (*Parent_class->dispose)(object);
}
+void GcmdGtkFoldview::G_object_finalize(GObject* object)
+{
+ g_return_if_fail( IS_GCMDGTKFOLDVIEW(object) );
+ //GCMD_INF("Control_g_object_finalize:%03i", GCMDGTKFOLDVIEW(object)->control_ref_count());
+ GCMD_INF("GcmdGtkFoldview::Control_g_object_finalize");
-GtkWidget*
-gnome_cmd_foldview_get_instance()
+ GCMDGTKFOLDVIEW(object)->finalize();
+
+ (*Parent_class->finalize)(object);
+}
+// ###########################################################################
+//
+// GcmdGtkFoldview : the rest
+//
+// ###########################################################################
+
+GdkPixbuf * GcmdGtkFoldview::s_gdk_pixbuf[GcmdGtkFoldview::eIconCard];
+gboolean GcmdGtkFoldview::s_gdk_pixbuf_loaded = FALSE;
+
+// ***************************************************************************
+//
+// init_instance, ...
+//
+// ***************************************************************************
+void GcmdGtkFoldview::init_instance()
{
- return GcmdWidget();
+ raz_pointers();
+
+ //.........................................................................
+ // Init logger
+ //
+
+ //
+ // Tki
+ // |
+ // Wng| Tke
+ // | | |
+ // Logger format : GCMD_B8(xxxxxx)
+ // | | |
+ // Inf| Tkw
+ // |
+ // Err
+ //
+ //
+
+ // common
+ sLogger.channel_create(eLogGcmd, "GCMD ", GCMD_B8(111000));
+ sLogger.channel_create(eLogLeaks, "LEAKS ", GCMD_B8(111111));
+ // control
+ sLogger.channel_create(eLogFifo, "FIFO ", GCMD_B8(000000));
+ sLogger.channel_create(eLogMsg, "MESSAGES ", GCMD_B8(111011));
+ // model
+ sLogger.channel_create(eLogFiles, "FILES ", GCMD_B8(000000));
+ sLogger.channel_create(eLogRefresh, "REFRESH ", GCMD_B8(011011));
+ sLogger.channel_create(eLogSort, "SORT ", GCMD_B8(111111));
+ sLogger.channel_create(eLogEnumerate, "ENUMERATE", GCMD_B8(111000));
+ sLogger.channel_create(eLogCheck, "CHECK ", GCMD_B8(111000));
+ sLogger.channel_create(eLogExpand, "EXPAND ", GCMD_B8(111000));
+ sLogger.channel_create(eLogMonitor, "MONITOR ", GCMD_B8(000000));
+
+ sLogger.channel_create(eLogTreeNode, "TREENODE ", GCMD_B8(111011));
+ sLogger.channel_create(eLogTreeBlock, "TREEBLOCK", GCMD_B8(111100));
+ sLogger.channel_create(eLogTreeStore, "TREESTORE", GCMD_B8(111100));
+
+ //.........................................................................
+ //
+ // Images
+ //
+ Pixbuf_load_all();
+
+ //.........................................................................
+ //
+ // Members
+ //
+ d_headband = GCMD_STRUCT_NEW(HeadBand, this);
+
+ d_scrolled_window = gtk_scrolled_window_new(NULL,NULL);
+ d_vbox_sw = gtk_vbox_new(FALSE, 0);
+
+ //.........................................................................
+ //
+ // Setup
+ //
+ gtk_container_set_reallocate_redraws(GTK_CONTAINER(this), TRUE);
+ gtk_box_set_homogeneous(GTK_BOX(this), FALSE);
+
+ d_headband->update_connections();
+
+ gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(d_scrolled_window), GTK_CORNER_BOTTOM_RIGHT);
+ gtk_scrolled_window_set_policy
+ ( GTK_SCROLLED_WINDOW(d_scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC );
+
+ gtk_box_set_homogeneous(GTK_BOX(d_vbox_sw), FALSE);
+
+ //.........................................................................
+ //
+ // Packing
+ //
+ gtk_box_pack_start(GTK_BOX(this), d_headband->widget(), FALSE, FALSE, 0);
+
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(d_scrolled_window), d_vbox_sw);
+ gtk_box_pack_start(GTK_BOX(this), d_scrolled_window, TRUE, TRUE, 0);
+
+ //-------------------------------------------------------------------------
+ // show, except the pane container
+ d_headband->show();
+ gtk_widget_show_all(GTK_WIDGET(this));
+
+ //=========================================================================
+ // Control
+ //=========================================================================
}
+void GcmdGtkFoldview::raz_pointers()
+{
+ d_headband = NULL;
+
+ d_scrolled_window = NULL;
+ d_vbox_sw = NULL;
-void gnome_cmd_foldview_destroy()
+ d_list_widget = NULL;
+ a_list_widget_card = 0;
+}
+
+void GcmdGtkFoldview::dispose()
{
- gint rc = 0;
+ GList * l = NULL;
+ GcmdStruct<GnomeCmdConnectionTreeview> * ctv = NULL;
+ //.........................................................................
+ l = g_list_first( d_list_widget );
+
+ while ( l )
+ {
+ if ( ! GTK_IS_HSEPARATOR((GtkSeparator*)l->data) )
+ {
+ ctv = (GcmdStruct<GnomeCmdConnectionTreeview>*)(l->data);
- if ( ! GcmdGtkFoldviewSingleton )
- return;
+ gtk_container_remove(GTK_CONTAINER(d_vbox_sw), ctv->widget());
- rc = (GCMDGTKFOLDVIEW(GcmdGtkFoldviewSingleton))->control_ref_count();
+ delete ctv;
+ }
+ else
+ {
+ gtk_container_remove(GTK_CONTAINER(d_vbox_sw), GTK_WIDGET(l->data));
+ }
- // release our ref
- gwr_inf("gnome_cmd_foldview_destroy:refcount is %03i, releasing one", rc);
- g_object_unref( GcmdGtkFoldviewSingleton );
+ l = g_list_next(l);
+ }
- // last ref !
- //gwr_inf("removing last ref...");
- //g_object_unref( GcmdGtkFoldviewSingleton );
- //gtk_widget_destroy( GcmdWidget() );
+ gtk_container_remove(GTK_CONTAINER(this), headband()->widget());
+ delete d_headband;
+
+ g_list_free(d_list_widget);
+
+}
+
+void GcmdGtkFoldview::finalize()
+{
+ Pixbuf_unload_all();
+}
+// ***************************************************************************
+//
+// Icons
+//
+// ***************************************************************************
+gboolean
+GcmdGtkFoldview::Pixbuf_load(
+ GcmdGtkFoldview::eIcon _icon,
+ const gchar * _filename)
+{
+ GError * g_error = NULL;
+ //.........................................................................
+ s_gdk_pixbuf[_icon] = gdk_pixbuf_new_from_file(_filename, &g_error);
+
+ if ( g_error )
+ {
+ GCMD_ERR("GcmdGtkFoldview::Pixbuf_load():%s", g_error->message );
+ g_error_free(g_error);
+ return FALSE;
+ }
+ return TRUE;
}
+gboolean
+GcmdGtkFoldview::Pixbuf_load_all()
+{
+ if ( s_gdk_pixbuf_loaded )
+ return TRUE;
+ Pixbuf_load(eIconGtkAdd, "../pixmaps/gtk-add.png");
-//=============================================================================
-// Root element
-//=============================================================================
-gboolean GcmdGtkFoldview::root_uri_set_1(gchar * text)
+ return TRUE;
+}
+void
+GcmdGtkFoldview::Pixbuf_unload_all()
{
- GnomeVFSURI *uri = GVFS_uri_new(text);
- control_root_uri_set(uri);
- gnome_vfs_uri_unref(uri);
- return TRUE;
+ g_object_unref(s_gdk_pixbuf[eIconGtkAdd]);
+}
+// ***************************************************************************
+//
+// Widget signals
+//
+// ***************************************************************************
+void
+GcmdGtkFoldview::Signal_button_add_clicked(
+ GtkButton * _button,
+ gpointer _udata)
+{
+ GcmdGtkFoldview * gfv = NULL;
+ GnomeCmdCon * con = NULL;
+ GList * l = NULL;
+ gboolean b = FALSE;
+ //.........................................................................
+ g_return_if_fail( _udata );
+ gfv = GCMDGTKFOLDVIEW(_udata);
+
+ // get selected connection
+ con = gfv->headband()->get_selected_connection();
+ if ( ! con )
+ {
+ GCMD_ERR("GcmdGtkFoldview::Signal_button_add_clicked():No connection selected");
+ return;
+ }
+
+ // if connection no more available, abort
+ for ( l = gnome_cmd_con_list_get_all(gnome_cmd_con_list_get ()); l ; l = l->next )
+ {
+ if ( con == (GnomeCmdCon *)l->data )
+ {
+ b = TRUE;
+ break;
+ }
+ }
+ if ( ! b )
+ {
+ GCMD_ERR("GcmdGtkFoldview::Signal_button_add_clicked():Connection no more available");
+ gfv->headband()->update_connections();
+ return;
+ }
+
+ if ( ! gfv->headband()->can_add_that_connection(con) )
+ {
+ GCMD_ERR("GcmdGtkFoldview::Signal_button_add_clicked():Cant add that connection");
+ return;
+ }
+
+ // add a new treeview
+ gfv->treeview_add(con);
+}
+void
+GcmdGtkFoldview::Signal_button_up_clicked(
+ GtkButton * _button,
+ gpointer _udata)
+{
+}
+void
+GcmdGtkFoldview::Signal_button_down_clicked(
+ GtkButton * _button,
+ gpointer _udata)
+{
+}
+// ***************************************************************************
+//
+// Treeviews
+//
+// ***************************************************************************
+void
+GcmdGtkFoldview::treeview_add(
+ GnomeCmdCon * _con)
+{
+ GcmdStruct<GnomeCmdConnectionTreeview> * ctv = NULL;
+ GtkWidget * sep = NULL;
+ //.........................................................................
+ g_return_if_fail( _con );
+
+ // the separator
+ if ( a_list_widget_card != 0 )
+ {
+ sep = gtk_hseparator_new();
+ gtk_widget_set_size_request(sep, -1, 10);
+ gtk_widget_show(sep);
+
+ d_list_widget = g_list_append(d_list_widget, sep);
+ a_list_widget_card++;
+ }
+
+ // the gct
+ ctv = GCMD_STRUCT_NEW(GnomeCmdConnectionTreeview, this, _con);
+ ctv->show();
+
+ d_list_widget = g_list_append(d_list_widget, ctv);
+ a_list_widget_card++;
+
+ // pack
+ if ( sep )
+ gtk_box_pack_start(GTK_BOX(d_vbox_sw), sep, FALSE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(d_vbox_sw), ctv->widget(), TRUE, TRUE, 0);
+}
+
+void
+GcmdGtkFoldview::treeview_del(
+ GnomeCmdConnectionTreeview * _ctv)
+{
+ GList * l = NULL;
+ GList * l1 = NULL;
+ GList * l2 = NULL;
+ GcmdStruct<GnomeCmdConnectionTreeview> * ctv = NULL;
+ GtkWidget * sep = NULL;
+ //.........................................................................
+ g_return_if_fail( _ctv );
+
+ l = g_list_first(d_list_widget);
+ while ( l )
+ {
+ if ( ! GTK_IS_HSEPARATOR((GtkSeparator*)l->data) )
+ {
+ ctv = (GcmdStruct<GnomeCmdConnectionTreeview>*)(l->data);
+
+ if ( ((GnomeCmdConnectionTreeview*)ctv) == _ctv )
+ {
+ l1 = l;
+ l = g_list_next(l);
+ if ( l )
+ {
+ l2 = l;
+ sep = GTK_WIDGET(l->data);
+ }
+
+ gtk_container_remove(GTK_CONTAINER(d_vbox_sw), ctv->widget());
+
+ delete ctv;
+ d_list_widget = g_list_delete_link(d_list_widget, l1);
+ a_list_widget_card--;
+
+
+ if ( sep )
+ {
+ gtk_container_remove(GTK_CONTAINER(d_vbox_sw), sep);
+
+ d_list_widget = g_list_delete_link(d_list_widget, l2);
+ a_list_widget_card--;
+ }
+ }
+ }
+
+ l = g_list_next(l);
+ }
}
-gboolean GcmdGtkFoldview::root_uri_set_2(GnomeVFSURI *uri)
+
+void
+GcmdGtkFoldview::treeview_set_packing_expansion(
+ GnomeCmdConnectionTreeview * _ctv,
+ gboolean _expand)
{
- return control_root_uri_set(uri);
+ gtk_box_set_child_packing(GTK_BOX(d_vbox_sw), _ctv->widget(), _expand, TRUE, 0, GTK_PACK_START);
}
+
+
+
diff --git a/src/foldview/gnome-cmd-foldview.h b/src/foldview/gnome-cmd-foldview.h
index e20327c..8cfa2bd 100644
--- a/src/foldview/gnome-cmd-foldview.h
+++ b/src/foldview/gnome-cmd-foldview.h
@@ -2,7 +2,7 @@
GNOME Commander - A GNOME based file manager
Copyright (C) 2001-2006 Marcus Bjurman
Copyright (C) 2007-2010 Piotr Eljasiak
- Copyright (C) 2010-2010 Guillaume Wardavoir
+ Copyleft 2010-2010 Guillaume Wardavoir
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,9 +33,15 @@
#include <gtk/gtkvbox.h>
#include <gtk/gtklabel.h>
+struct IGnomeCmdFoldview
+{
+
+};
+
// This function because of the creation process of GtkWidgets. Annoying.
-GtkWidget* gnome_cmd_foldview_get_instance();
-GtkWidget* gnome_cmd_foldview_destroy();
-void gnome_cmd_foldview_update_style (GtkWidget *widget);
+GtkWidget* gnome_cmd_foldview_new();
+void gnome_cmd_foldview_update_style(GtkWidget *widget);
+
+
#endif //__GCMDGTKFOLDVIEW_H__
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]