Commit 2979522c authored by Alexander Larsson's avatar Alexander Larsson Committed by Alexander Larsson

Patch by Soren Sandmann

2003-06-27  Alexander Larsson  <alexl@redhat.com>

        Patch by Soren Sandmann

	* configure.in:
	CFLAGS for gsequence

	* cut-n-paste-code/Makefile.am:
	* cut-n-paste-code/gsequence/.cvsignore:
	* cut-n-paste-code/gsequence/Makefile.am:
	* cut-n-paste-code/gsequence/gsequence.[ch]:
	New cut-n-paste lib for gsequence (by Soren Sandmann)

	* src/Makefile.am:
	Link to gsequence

	* src/file-manager/fm-list-model.c:
	Use gsequence plus a reverse mapping hashtable.
parent 0f758600
2003-06-27 Alexander Larsson <alexl@redhat.com>
Patch by Soren Sandmann
* configure.in:
CFLAGS for gsequence
* cut-n-paste-code/Makefile.am:
* cut-n-paste-code/gsequence/.cvsignore:
* cut-n-paste-code/gsequence/Makefile.am:
* cut-n-paste-code/gsequence/gsequence.[ch]:
New cut-n-paste lib for gsequence (by Soren Sandmann)
* src/Makefile.am:
Link to gsequence
* src/file-manager/fm-list-model.c:
Use gsequence plus a reverse mapping hashtable.
2003-06-27 Alexander Larsson <alexl@redhat.com>
This is based on a patch by Jrg Billeter <j@bitron.ch> which was
......
......@@ -293,6 +293,11 @@ GIMPHWRAPBOX_MODULES="gtk+-2.0"
GIMPHWRAPBOX_CFLAGS="`$PKG_CONFIG --cflags $GIMPHWRAPBOX_MODULES`"
AC_SUBST(GIMPHWRAPBOX_CFLAGS)
dnl gsequence
GSEQUENCE_MODULES="glib-2.0"
GSEQUENCE_CFLAGS="`$PKG_CONFIG --cflags $GSEQUENCE_MODULES`"
AC_SUBST(GSEQUENCE_CFLAGS)
dnl libegg
LIBEGG_MODULES="gtk+-2.0 libgnome-2.0"
LIBEGG_CFLAGS="`$PKG_CONFIG --cflags $LIBEGG_MODULES`"
......@@ -387,6 +392,7 @@ components/emblem/Makefile
components/image_properties/Makefile
cut-n-paste-code/Makefile
cut-n-paste-code/libegg/Makefile
cut-n-paste-code/gsequence/Makefile
cut-n-paste-code/widgets/Makefile
cut-n-paste-code/widgets/gimphwrapbox/Makefile
data/Makefile
......
SUBDIRS = widgets libegg
SUBDIRS = widgets libegg gsequence
NULL=
noinst_LTLIBRARIES = libgsequence.la
INCLUDES = $(GSEQUENCE_CFLAGS)
libgsequence_la_SOURCES = \
gsequence.c \
gsequence.h \
$(NULL)
This diff is collapsed.
/* GLIB - Library of useful routines for C programming
* Copyright (C) 2002 Soeren Sandmann (sandmann@daimi.au.dk)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <glib.h>
#ifndef __GSEQUENCE_H__
#define __GSEQUENCE_H__
typedef struct _GSequence GSequence;
typedef struct _GSequenceNode *GSequencePtr;
/* GSequence */
GSequence * g_sequence_new (GDestroyNotify data_destroy);
void g_sequence_free (GSequence *seq);
void g_sequence_sort (GSequence *seq,
GCompareDataFunc cmp_func,
gpointer cmp_data);
void g_sequence_append (GSequence *seq,
gpointer data);
void g_sequence_prepend (GSequence *seq,
gpointer data);
void g_sequence_insert (GSequencePtr ptr,
gpointer data);
void g_sequence_remove (GSequencePtr ptr);
GSequencePtr g_sequence_insert_sorted (GSequence *seq,
gpointer data,
GCompareDataFunc cmp_func,
gpointer cmp_data);
void g_sequence_insert_sequence (GSequencePtr ptr,
GSequence *other_seq);
void g_sequence_concatenate (GSequence *seq1,
GSequence *seq);
void g_sequence_remove_range (GSequencePtr begin,
GSequencePtr end,
GSequence **removed);
gint g_sequence_get_length (GSequence *seq);
GSequencePtr g_sequence_get_end_ptr (GSequence *seq);
GSequencePtr g_sequence_get_begin_ptr (GSequence *seq);
GSequencePtr g_sequence_get_ptr_at_pos (GSequence *seq,
gint pos);
/* GSequencePtr */
gboolean g_sequence_ptr_is_end (GSequencePtr ptr);
gboolean g_sequence_ptr_is_begin (GSequencePtr ptr);
gint g_sequence_ptr_get_position (GSequencePtr ptr);
GSequencePtr g_sequence_ptr_next (GSequencePtr ptr);
GSequencePtr g_sequence_ptr_prev (GSequencePtr ptr);
GSequencePtr g_sequence_ptr_move (GSequencePtr ptr,
guint leap);
void g_sequence_ptr_sort_changed (GSequencePtr ptr,
GCompareDataFunc cmp_func,
gpointer cmp_data);
gpointer g_sequence_ptr_get_data (GSequencePtr ptr);
/* search */
/* return TRUE if you want to be called again with two
* smaller segments
*/
typedef gboolean (* GSequenceSearchFunc) (GSequencePtr begin,
GSequencePtr end,
gpointer data);
void g_sequence_search (GSequence *seq,
GSequenceSearchFunc f,
gpointer data);
/* debug */
gint g_sequence_calc_tree_height (GSequence *seq);
#endif /* __GSEQUENCE_H__ */
......@@ -34,6 +34,7 @@ LDADD =\
$(top_builddir)/libnautilus/libnautilus.la \
$(top_builddir)/libnautilus-adapter/libnautilus-adapter.la \
$(top_builddir)/libnautilus-private/libnautilus-private.la \
$(top_builddir)/cut-n-paste-code/gsequence/libgsequence.la \
$(CORE_LIBS) \
$(POPT_LIBS) \
$(NULL)
......
......@@ -2,7 +2,8 @@
/* fm-list-model.h - a GtkTreeModel for file lists.
Copyright (C) 2001, 2002 Anders Carlsson
Copyright (C) 2001, 2002 Anders Carlsson
Copyright (C) 2003, Soeren Sandmann
The Gnome Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
......@@ -19,7 +20,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Authors: Anders Carlsson <andersca@gnu.org>
Authors: Anders Carlsson <andersca@gnu.org>, Soeren Sandmann (sandmann@daimi.au.dk)
*/
#include <config.h>
......@@ -32,15 +33,17 @@
#include <gtk/gtktreesortable.h>
#include <libnautilus-private/nautilus-icon-factory.h>
#include <libnautilus-private/nautilus-dnd.h>
#include <gsequence/gsequence.h>
#define G_SLIST(x) ((GSList *) x)
static int fm_list_model_compare_func (gconstpointer a,
gconstpointer b,
gpointer user_data);
static GObjectClass *parent_class;
struct FMListModelDetails {
GSList *files;
GSList *tail;
int length;
GSequence *files;
GHashTable *reverse_map; /* map from files to GSequencePtr's */
int stamp;
......@@ -134,22 +137,24 @@ static gboolean
fm_list_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
{
FMListModel *model;
GSList *list;
GSequencePtr ptr;
int i;
model = (FMListModel *)tree_model;
i = gtk_tree_path_get_indices (path)[0];
if (i >= model->details->length) {
if (i >= g_sequence_get_length (model->details->files)) {
return FALSE;
}
list = g_slist_nth (model->details->files, i);
ptr = g_sequence_get_ptr_at_pos (model->details->files, i);
iter->stamp = model->details->stamp;
iter->user_data = list;
iter->user_data = ptr;
g_assert (!g_sequence_ptr_is_end (iter->user_data));
return TRUE;
}
......@@ -158,30 +163,19 @@ fm_list_model_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter)
{
GtkTreePath *path;
FMListModel *model;
GSList *list;
int i;
model = (FMListModel *)tree_model;
g_return_val_if_fail (iter->stamp == model->details->stamp, NULL);
i = 0;
for (list = model->details->files; list; list = list->next) {
if (list == iter->user_data) {
break;
}
i++;
}
if (list == NULL) {
if (g_sequence_ptr_is_end (iter->user_data)) {
/* FIXME is this right? */
return NULL;
}
path = gtk_tree_path_new ();
gtk_tree_path_append_index (path, i);
path = gtk_tree_path_new ();
gtk_tree_path_append_index (path, g_sequence_ptr_get_position (iter->user_data));
return path;
}
......@@ -199,8 +193,9 @@ fm_list_model_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column
model = (FMListModel *)tree_model;
g_return_if_fail (model->details->stamp == iter->stamp);
g_return_if_fail (!g_sequence_ptr_is_end (iter->user_data));
file = G_SLIST (iter->user_data)->data;
file = g_sequence_ptr_get_data (iter->user_data);
switch (column) {
case FM_LIST_MODEL_FILE_COLUMN:
......@@ -275,9 +270,9 @@ fm_list_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
g_return_val_if_fail (model->details->stamp == iter->stamp, FALSE);
iter->user_data = G_SLIST (iter->user_data)->next;
iter->user_data = g_sequence_ptr_next (iter->user_data);
return (iter->user_data != NULL);
return !g_sequence_ptr_is_end (iter->user_data);
}
static gboolean
......@@ -291,15 +286,14 @@ fm_list_model_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTre
return FALSE;
}
if (model->details->files != NULL) {
iter->stamp = model->details->stamp;
iter->user_data = model->details->files;
return TRUE;
}
else {
if (g_sequence_get_length (model->details->files) == 0) {
return FALSE;
}
iter->stamp = model->details->stamp;
iter->user_data = g_sequence_get_begin_ptr (model->details->files);
return TRUE;
}
static gboolean
......@@ -316,7 +310,7 @@ fm_list_model_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter)
model = (FMListModel *)tree_model;
if (iter == NULL) {
return model->details->length;
return g_sequence_get_length (model->details->files);
}
g_return_val_if_fail (model->details->stamp == iter->stamp, -1);
......@@ -328,7 +322,7 @@ static gboolean
fm_list_model_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, int n)
{
FMListModel *model;
GSList *child;
GSequencePtr child;
model = (FMListModel *)tree_model;
......@@ -336,17 +330,16 @@ fm_list_model_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTr
return FALSE;
}
child = g_slist_nth (model->details->files, n);
child = g_sequence_get_ptr_at_pos (model->details->files, n);
if (child != NULL) {
iter->stamp = model->details->stamp;
iter->user_data = child;
return TRUE;
}
else {
if (g_sequence_ptr_is_end (child)) {
return FALSE;
}
iter->stamp = model->details->stamp;
iter->user_data = child;
return TRUE;
}
static gboolean
......@@ -358,33 +351,25 @@ fm_list_model_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeI
gboolean
fm_list_model_get_tree_iter_from_file (FMListModel *model, NautilusFile *file, GtkTreeIter *iter)
{
GSList *list;
GSequencePtr ptr;
for (list = model->details->files; list; list = list->next) {
if (list->data == file) {
break;
}
}
ptr = g_hash_table_lookup (model->details->reverse_map, file);
if (list == NULL) {
if (!ptr) {
return FALSE;
}
g_assert (!g_sequence_ptr_is_end (ptr));
g_assert (g_sequence_ptr_get_data (ptr) == file);
if (iter != NULL) {
iter->stamp = model->details->stamp;
iter->user_data = list;
iter->user_data = ptr;
}
return TRUE;
}
/* Sorting */
typedef struct _SortTuple
{
gint offset;
GSList *el;
} SortTuple;
static int
fm_list_model_compare_func (gconstpointer a,
gconstpointer b,
......@@ -394,11 +379,11 @@ fm_list_model_compare_func (gconstpointer a,
NautilusFile *file2;
FMListModel *model;
int result;
model = (FMListModel *)user_data;
file1 = ((SortTuple *)a)->el->data;
file2 = ((SortTuple *)b)->el->data;
file1 = (NautilusFile *)a;
file2 = (NautilusFile *)b;
result = nautilus_file_compare_for_sort (file1, file2,
fm_list_model_get_sort_type_from_sort_column_id (model->details->sort_column_id),
......@@ -411,58 +396,47 @@ fm_list_model_compare_func (gconstpointer a,
static void
fm_list_model_sort (FMListModel *model)
{
GtkTreeIter iter;
GArray *sort_array;
gint i;
gint *new_order;
GSList *list;
GSequence *files;
GSequencePtr *old_order;
GtkTreePath *path;
int *new_order;
int length;
int i;
if (model->details->length <= 1) {
files = model->details->files;
length = g_sequence_get_length (files);
if (length <= 1) {
return;
}
list = G_SLIST (model->details->files);
sort_array = g_array_sized_new (FALSE, FALSE,
sizeof (SortTuple),
model->details->length);
for (i = 0; i < model->details->length; i++) {
SortTuple tuple;
/* generate old order of GSequencePtr's */
old_order = g_new (GSequencePtr, length);
for (i = 0; i < length; ++i) {
GSequencePtr ptr = g_sequence_get_ptr_at_pos (files, i);
/* If this fails, we are in an inconsistent state. Bad */
g_return_if_fail (list != NULL);
tuple.offset = i;
tuple.el = list;
g_array_append_val (sort_array, tuple);
list = list->next;
old_order[i] = ptr;
}
g_array_sort_with_data (sort_array, fm_list_model_compare_func, model);
for (i = 0; i < model->details->length - 1; i++) {
g_array_index (sort_array, SortTuple, i).el->next = g_array_index (sort_array, SortTuple, i + 1).el;
/* sort */
g_sequence_sort (files, fm_list_model_compare_func, model);
/* generate new order */
new_order = g_new (int, length);
for (i = 0; i < length; ++i) {
new_order[i] = g_sequence_ptr_get_position (old_order[i]);
}
g_array_index (sort_array, SortTuple, model->details->length - 1).el->next = NULL;
model->details->files = g_array_index (sort_array, SortTuple, 0).el;
/* Let the world know about our new order */
new_order = g_new (int, model->details->length);
for (i = 0; i < model->details->length; i++) {
new_order[i] = g_array_index (sort_array, SortTuple, i).offset;
}
path = gtk_tree_path_new ();
iter.stamp = model->details->stamp;
iter.user_data = NULL;
g_assert (new_order != NULL);
gtk_tree_model_rows_reordered (GTK_TREE_MODEL (model),
path, NULL, new_order);
gtk_tree_path_free (path);
g_free (old_order);
g_free (new_order);
g_array_free (sort_array, TRUE);
}
static gboolean
......@@ -624,65 +598,22 @@ fm_list_model_add_file (FMListModel *model, NautilusFile *file)
{
GtkTreeIter iter;
GtkTreePath *path;
GSList *list, *tmp, *tmp_prev;
NautilusFile *file1;
int result;
GSequencePtr new_ptr;
/* We may only add each file once. */
if (fm_list_model_get_tree_iter_from_file (model, file, NULL) == TRUE) {
if (fm_list_model_get_tree_iter_from_file (model, file, NULL)) {
return;
}
tmp_prev = NULL;
nautilus_file_ref (file);
list = g_slist_alloc ();
list->data = nautilus_file_ref (file);
new_ptr = g_sequence_insert_sorted (model->details->files, file,
fm_list_model_compare_func, model);
g_hash_table_insert (model->details->reverse_map, file, new_ptr);
iter.stamp = model->details->stamp;
iter.user_data = list;
if (model->details->tail == NULL) {
model->details->files = iter.user_data;
model->details->tail = iter.user_data;
}
else {
for (tmp = model->details->files; tmp; tmp = tmp->next) {
file1 = tmp->data;
result = nautilus_file_compare_for_sort (file, file1,
fm_list_model_get_sort_type_from_sort_column_id (model->details->sort_column_id),
model->details->sort_directories_first,
(model->details->order == GTK_SORT_DESCENDING));
if (result < 0) {
break;
}
tmp_prev = tmp;
}
if (tmp != NULL) {
if (tmp == model->details->files) {
list->next = model->details->files;
model->details->files = list;
}
else {
list->next = tmp;
}
}
if (tmp_prev != NULL) {
if (tmp_prev == model->details->tail) {
model->details->tail->next = list;
model->details->tail = list;
}
else {
tmp_prev->next = list;
}
}
}
model->details->length += 1;
iter.user_data = new_ptr;
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
......@@ -694,21 +625,19 @@ fm_list_model_file_changed (FMListModel *model, NautilusFile *file)
{
GtkTreeIter iter;
GtkTreePath *path;
GSList *list;
GSequencePtr ptr;
for (list = model->details->files; list; list = list->next) {
if (list->data == file) {
break;
}
ptr = g_hash_table_lookup (model->details->reverse_map, file);
if (!ptr) {
return;
}
if (list == NULL) {
g_sequence_ptr_sort_changed (ptr, fm_list_model_compare_func, model);
if (!fm_list_model_get_tree_iter_from_file (model, file, &iter)) {
return;
}
iter.stamp = model->details->stamp;
iter.user_data = list;
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
gtk_tree_path_free (path);
......@@ -717,64 +646,25 @@ fm_list_model_file_changed (FMListModel *model, NautilusFile *file)
gboolean
fm_list_model_is_empty (FMListModel *model)
{
return model->details->length == 0;
}
static GSList *
remove_link_saving_prev (GSList *list, GSList *link, GSList **prevp)
{
GSList *node;
GSList *prev;
prev = NULL;
for (node = list; node; node = node->next) {
if (node == link) {
if (prev != NULL) {
prev->next = link->next;
}
if (list == link) {
list = list->next;
}
link->next = NULL;
break;
}
prev = node;
}
*prevp = prev;
return list;
return (g_sequence_get_length (model->details->files) == 0);
}
static void
fm_list_model_remove (FMListModel *model, GtkTreeIter *iter)
{
GSequencePtr ptr;
GtkTreePath *path;
GSList *prev;
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter);
nautilus_file_unref (NAUTILUS_FILE (G_SLIST (iter->user_data)->data));
prev = NULL;
model->details->files = remove_link_saving_prev (model->details->files,
iter->user_data,
&prev);
model->details->length -= 1;
if (iter->user_data == model->details->tail) {
model->details->tail = prev;
}
ptr = iter->user_data;
model->details->stamp++;
g_hash_table_remove (model->details->reverse_map, g_sequence_ptr_get_data (ptr));
g_sequence_remove (ptr);
model->details->stamp++;
gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
gtk_tree_path_free (path);
}
void
......@@ -794,9 +684,9 @@ fm_list_model_clear (FMListModel *model)
g_return_if_fail (model != NULL);
while (model->details->files != NULL) {
while (g_sequence_get_length (model->details->files) > 0) {
iter.stamp = model->details->stamp;
iter.user_data = model->details->files;
iter.user_data = g_sequence_get_begin_ptr (model->details->files);
fm_list_model_remove (model, &iter);
}
}
......@@ -960,6 +850,8 @@ fm_list_model_finalize (GObject *object)
model = FM_LIST_MODEL (object);
g_sequence_free (model->details->files);
g_hash_table_destroy (model->details->reverse_map);
g_free (model->details);
EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
......@@ -969,6 +861,8 @@ static void
fm_list_model_init (FMListModel *model)
{
model->details = g_new0 (FMListModelDetails, 1);
model->details->files = g_sequence_new ((GDestroyNotify)nautilus_file_unref);
model->details->reverse_map = g_hash_table_new (g_direct_hash, g_direct_equal);
model->details->stamp = g_random_int ();
model->details->sort_column_id = -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment