Beispiel #1
0
static void fx_many_item_toggled(GtkCellRendererToggle *UNUSED(cell)
		, char* path_str , gpointer data)
{
	FxMany* fxmany = (FxMany*)data;
	GtkTreeView* tree = GTK_TREE_VIEW(fxmany->tree);
	GtkTreeModel* model = gtk_tree_view_get_model(tree);
	GtkTreeView* ctree = GTK_TREE_VIEW(fxmany->selected);
	GtkTreeModel* cmodel = gtk_tree_view_get_model(ctree);
	GtkTreePath* path = gtk_tree_path_new_from_string(path_str);
	GtkTreeIter iter;
	gboolean checked , checked1;
	char* name;
	char* sipuri;
	char* uri;
	char labeltext[128];
	GdkPixbuf* pb;

	GtkTreeIter cIter;
	GtkTreeIter childiter;

	gtk_tree_model_get_iter(model , &iter , path);
	gtk_tree_model_get(model , &iter
					 , S_SIPURI_COL , &sipuri
					 , S_CHECK_COL  , &checked
					 , -1);
	checked ^= 1;

	if(checked)
	{
		if(gtk_tree_path_get_depth(path) > 1){
			gtk_tree_model_get(model , &iter
							 , S_NAME_COL   , &name
							 , S_PIXBUF_COL , &pb
							 , -1);
			gtk_tree_store_append(GTK_TREE_STORE(cmodel) , &cIter , NULL);
			gtk_tree_store_set(GTK_TREE_STORE(cmodel) , &cIter 
							 , C_PIXBUF_COL           , pb
							 , C_NAME_COL             , name
							 , C_SIPURI_COL           , sipuri
							 , -1);
			fxmany->chooseCount ++;

			free(name);
			free(sipuri);
			g_object_unref(pb);
		}else{
			if(gtk_tree_model_iter_children(model , &childiter , &iter)){
				do{
					gtk_tree_model_get(model , &childiter
									 , S_CHECK_COL  , &checked1
									 , S_NAME_COL   , &name
									 , S_SIPURI_COL , &sipuri
									 , S_PIXBUF_COL , &pb
									 , -1);
					if(!checked1){
						gtk_tree_store_append(GTK_TREE_STORE(cmodel) , &cIter , NULL);
						gtk_tree_store_set(GTK_TREE_STORE(cmodel) , &cIter 
										 , C_PIXBUF_COL           , pb
										 , C_NAME_COL             , name
										 , C_SIPURI_COL           , sipuri
										 , -1);
						fxmany->chooseCount ++;
						gtk_tree_store_set(GTK_TREE_STORE(model) , &childiter
								, S_CHECK_COL , TRUE , -1);
					}
					free(name);
					free(sipuri);
					g_object_unref(pb);
				}while(gtk_tree_model_iter_next(model , &childiter));
			}
		}
	}
	else
	{
		if(gtk_tree_path_get_depth(path) > 1){
			gtk_tree_model_get_iter_root(cmodel , &cIter);
			do{
				gtk_tree_model_get(cmodel       , &cIter 
								 , C_SIPURI_COL , &uri
								 , -1);
				if(strcmp(sipuri , uri) == 0){
					free(uri);
					break;
				}
			}while(gtk_tree_model_iter_next(cmodel , &cIter));
			gtk_tree_store_remove(GTK_TREE_STORE(cmodel) , &cIter);
			fxmany->chooseCount --;
		}else{
			if(gtk_tree_model_iter_children(model , &childiter , &iter)){
				do{
					gtk_tree_model_get(model , &childiter 
							, S_CHECK_COL , &checked1
							, S_SIPURI_COL , &sipuri , -1);

					if(!checked1)
						continue;

					gtk_tree_model_get_iter_root(cmodel , &cIter);

					do{
						gtk_tree_model_get(cmodel       , &cIter 
										 , C_SIPURI_COL , &uri
										 , -1);
						if(strcmp(sipuri , uri) == 0){
							free(uri);
							break;
						}
					}while(gtk_tree_model_iter_next(cmodel , &cIter));

					gtk_tree_store_remove(GTK_TREE_STORE(cmodel) , &cIter);
					fxmany->chooseCount --;
					gtk_tree_store_set(GTK_TREE_STORE(model) , &childiter
							, S_CHECK_COL , FALSE , -1);

					free(sipuri);

				}while(gtk_tree_model_iter_next(model , &childiter));
			}
		}
	}
	gtk_tree_store_set(GTK_TREE_STORE(model) , &iter
					 , S_CHECK_COL , checked 
					 , -1);

	gtk_tree_path_free(path);
	snprintf(labeltext, sizeof(labeltext) - 1 ,
			_("Choosed [<span color=\"red\">%d</span>] contacts, "
			"[<span color=\"red\">%d</span>] more available"),
		     fxmany->chooseCount , 10000 - fxmany->chooseCount);
	gtk_label_set_markup(GTK_LABEL(fxmany->label) , labeltext);

}
Beispiel #2
0
// This little bit is needed to prevent the default drag motion
// handler from expanding rows if you hover over them while
// dragging.
// Also controls where valid drop locations are
G_MODULE_EXPORT gboolean
queue_drag_motion_cb(
    GtkTreeView *tv,
    GdkDragContext *ctx,
    gint x,
    gint y,
    guint time,
    signal_user_data_t *ud)
{
    GtkTreePath *path = NULL;
    GtkTreeViewDropPosition pos;
    gint *indices, row, status, finished;
    GValue *js;
    GtkTreeIter iter;
    GtkTreeView *srctv;
    GtkTreeModel *model;
    GtkTreeSelection *select;
    GtkWidget *widget;

    widget = gtk_drag_get_source_widget(ctx);
    if (widget == NULL || widget != GTK_WIDGET(tv))
        return TRUE;

    // This bit checks to see if the source is allowed to be
    // moved.  Only pending and canceled items may be moved.
    srctv = GTK_TREE_VIEW(gtk_drag_get_source_widget(ctx));
    select = gtk_tree_view_get_selection (srctv);
    gtk_tree_selection_get_selected (select, &model, &iter);
    path = gtk_tree_model_get_path (model, &iter);
    indices = gtk_tree_path_get_indices(path);
    row = indices[0];
    gtk_tree_path_free(path);
    js = ghb_array_get_nth(ud->queue, row);
    status = ghb_settings_get_int(js, "job_status");
    if (status != GHB_QUEUE_PENDING && status != GHB_QUEUE_CANCELED)
    {
        gdk_drag_status(ctx, 0, time);
        return TRUE;
    }

    // The reset checks that the destination is a valid position
    // in the list.  Can not move above any finished or running items
    gtk_tree_view_get_dest_row_at_pos (tv, x, y, &path, &pos);
    if (path == NULL)
    {
        gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
        return TRUE;
    }
    // Don't allow *drop into*
    if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
        pos = GTK_TREE_VIEW_DROP_BEFORE;
    if (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
        pos = GTK_TREE_VIEW_DROP_AFTER;
    // Don't allow droping int child items
    if (gtk_tree_path_get_depth(path) > 1)
    {
        gtk_tree_path_up(path);
        pos = GTK_TREE_VIEW_DROP_AFTER;
    }
    indices = gtk_tree_path_get_indices(path);
    row = indices[0];
    js = ghb_array_get_nth(ud->queue, row);

    finished = find_last_finished(ud->queue);
    if (row < finished)
    {
        gtk_tree_path_free(path);
        gdk_drag_status(ctx, 0, time);
        return TRUE;
    }
    if (pos != GTK_TREE_VIEW_DROP_AFTER && 
        row == finished)
    {
        gtk_tree_path_free(path);
        gdk_drag_status(ctx, 0, time);
        return TRUE;
    }
    gtk_tree_view_set_drag_dest_row(tv, path, pos);
    gtk_tree_path_free(path);
    gdk_drag_status(ctx, GDK_ACTION_MOVE, time);
    return TRUE;
}
static void
update_thumbnail_popup_process (GtkWidget *widget, GdkEventMotion *event)
{
    //g_message ("Doing %s, event = %p", __func__, event);

    static gboolean witn = FALSE;	/* "Was in thumbnail".  */
    static GtkTreePath *otp = NULL;
    static GtkTreeViewColumn *otc = NULL;
    static GTimer *hover_timer = NULL;
    if ( hover_timer == NULL ) {
        hover_timer = g_timer_new ();
    }

    /* Fos some crazy reason, drawing the popup image changes the result
    of in_thumbnail (I suspect because gdk is reusing event
    structures in some strange way).  So memorize in_thumbnail up
    front.  */
    // Also, this assertion should pass, but doesn't... synthesizing
    // motion events is apparently a bit harder than I realized.
    // g_assert (event->type == GDK_MOTION_NOTIFY);
    //g_message ("event x: %lf, event y: %lf", event->x, event->y); 
    gboolean event_in_thumbnail = in_thumbnail (widget, event);

    /* Hover time in milliseconds required before a popup image is
    displayed.  */
    const gint hover_time = 70;

    if ( !witn && in_output_thumbnail (widget, event) ) {
        witn = TRUE;
        otp = thumbnail_path (widget, event);
        g_assert (gtk_tree_path_get_depth (otp) == 1);
        otc = thumbnail_column (widget, event);
        g_timer_start (hover_timer);
        //g_message ("Adding timeout from !with && in_output_thumbnail");
        fake_motion_signal_args_t *fmsa = g_new (fake_motion_signal_args_t, 1);
        fmsa->widget = widget;
        fmsa->event = event;      
        fmsa->is_valid = TRUE;
        g_timeout_add (hover_time, (GSourceFunc) emit_fake_motion_signal, fmsa);
    }

    if ( witn && in_output_thumbnail (widget, event) ) {
        //g_message ("in_thumbnail: %d", in_thumbnail (widget, event));
        GtkTreePath *ctp = thumbnail_path (widget, event);
        g_assert (gtk_tree_path_get_depth (ctp) == 1);
        GtkTreeViewColumn *ctc = thumbnail_column (widget, event);
        if ( gtk_tree_path_compare (ctp, otp) == 0 && ctc == otc ) {
            /* Sometimes the timeout handler seems to go off a bit before
            timer has measured the correct amount of time, so we add a
            small margin here.  */
            const gint slop_time = 5;
            const gint seconds_to_mseconds_factor = 1000;
            /* If we hover for this long or longer, we should show the popup.  */
            if ( g_timer_elapsed (hover_timer, NULL) * seconds_to_mseconds_factor 
                >= hover_time - slop_time) {
                    //g_message ("elapsed time: %lf\n", g_timer_elapsed (hover_timer, NULL));
                    //g_message ("Do popup!!!");
                    //g_message ("in_thumbnail: %d", in_thumbnail (widget, event));
                    GdkRegion *tr = thumbnail_region (widget, event);
                    //g_message ("bpw in_thumbnail: %d", in_thumbnail (widget, event));
                    //g_message ("widget: %p", widget);
                    GdkWindow *popup_window = draw_popup_image (widget, ctp, ctc, tr);
                    //g_message ("apw in_thumbnail: %d", in_thumbnail (widget, event));
                    //g_message ("widget: %p", widget);
                    /* We don't want continuous redrawing of the popup, so we
                    disable the handler that triggers it until the popup is
                    removed.  */

                    if (popup_window)
                    {
                        guint signal_id = g_signal_lookup ("motion-notify-event",
                            GTK_WIDGET_TYPE (widget));
                        gulong handler_id 
                            = g_signal_handler_find (widget,
                            G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC
                            | G_SIGNAL_MATCH_DATA,
                            signal_id,
                            (GQuark) 0,
                            NULL,
                            completed_files_list_motion_notify_event_handler,
                            NULL);
                        g_assert (handler_id != 0);
                        g_signal_handler_block (widget, handler_id);
                        /* We want to get rid of the popup window as soon as the user
                        moves the mouse outside of the original thumbnail
                        space.  */
                        maybe_clear_popup_image_args.popup = popup_window;
                        maybe_clear_popup_image_args.tree_view = GTK_TREE_VIEW (widget);
                        if ( maybe_clear_popup_image_args.thumbnail_region != NULL ) {
                            gdk_region_destroy (maybe_clear_popup_image_args.thumbnail_region);
                        }
                        //g_message ("in_thumbnail: %d", in_thumbnail (widget, event));
                        maybe_clear_popup_image_args.thumbnail_region = tr;
                        g_signal_connect (widget, "motion-notify-event", 
                            G_CALLBACK (maybe_clear_popup_image), 
                            &maybe_clear_popup_image_args);
                        //g_message ("in_thumbnail: %d", in_thumbnail (widget, event));
                    }
                } 
            else {
                gtk_tree_path_free (ctp);
            }
        }
        else {
            gtk_tree_path_free (otp);
            otp = ctp;
            otc = ctc;
            g_timer_start (hover_timer);
            //g_message ("Adding timeout from 'different thumbnails'");
            fake_motion_signal_args_t *fmsa = g_new (fake_motion_signal_args_t, 1);
            fmsa->widget = widget;
            fmsa->event = event;      
            fmsa->is_valid = TRUE;
            g_timeout_add (hover_time, (GSourceFunc) emit_fake_motion_signal, fmsa);
        }
    }

    if ( witn && !event_in_thumbnail ) {
        //g_message ("in_thumbnail: %d", in_thumbnail (widget, event));
        //g_message ("Setting witn false");
        witn = FALSE;
    }
}
Beispiel #4
0
// Create a new bus from the current selection
static void create_bus_button_clicked (GtkWidget *widget, gpointer data)
  {
  int row_type = -1 ;
  bus_layout_D *dialog = (bus_layout_D *)data ;
  GList *llTreeRefs = NULL, *llItr = NULL ;
  GtkTreeStore *ts = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tview))) ;
  GtkTreeIter itrBus, itr, itrSrc, itrSrcParent ;
  GtkTreeRowReference *refBus = NULL, *refSrcParent = NULL ;
  GtkTreePath *tp = NULL, *tpSrcParent = NULL ;

  llTreeRefs = get_selected_refs (gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tview))) ;

  if (NULL == llTreeRefs) return ;

  if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &itr,
    tp = gtk_tree_row_reference_get_path (llTreeRefs->data)))
    {
    gtk_tree_path_free (tp) ;
    return ;
    }

  gtk_tree_model_get (GTK_TREE_MODEL (ts), &itr, BUS_LAYOUT_MODEL_COLUMN_TYPE, &row_type, -1) ;

  gtk_tree_path_free (tp) ;

  gtk_tree_store_prepend (ts, &itrBus, NULL) ;
  gtk_tree_store_set (ts, &itrBus,
    BUS_LAYOUT_MODEL_COLUMN_ICON, (row_type & ROW_TYPE_INPUT) ? QCAD_STOCK_BUS_INPUT : QCAD_STOCK_BUS_OUTPUT,
    BUS_LAYOUT_MODEL_COLUMN_NAME, _("Untitled Bus"),
    BUS_LAYOUT_MODEL_COLUMN_TYPE, (row_type & ROW_TYPE_INPUT) ? ROW_TYPE_BUS_INPUT : ROW_TYPE_BUS_OUTPUT,
    BUS_LAYOUT_MODEL_COLUMN_INDEX, -1, -1) ;

  refBus = gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), tp = gtk_tree_model_get_path (GTK_TREE_MODEL (ts), &itrBus)) ;
  gtk_tree_path_free (tp) ;

  for (llItr = g_list_last (llTreeRefs) ; llItr != NULL ; llItr = llItr->prev)
    {
    if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &itrBus, tp = gtk_tree_row_reference_get_path (refBus)))
      {
      gtk_tree_path_free (tp) ;

      gtk_tree_store_append (ts, &itr, &itrBus) ;

      if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &itrSrc, tp = gtk_tree_row_reference_get_path (llItr->data)))
        swap_model_iters_contents (GTK_TREE_MODEL (ts), &itrSrc, &itr) ;
      gtk_tree_path_free (tp) ;

      if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &itrSrc, tp = gtk_tree_row_reference_get_path (llItr->data)))
        {
        if (gtk_tree_path_get_depth (tp) > 1)
          {
          if (gtk_tree_path_up (tpSrcParent = gtk_tree_path_copy (tp)))
            refSrcParent = (1 == gtk_tree_model_path_n_children (GTK_TREE_MODEL (ts), tpSrcParent)) ?
              gtk_tree_row_reference_new (GTK_TREE_MODEL (ts), tpSrcParent) : NULL ;

          gtk_tree_path_free (tpSrcParent) ;
          }
        }
      gtk_tree_path_free (tp) ;

      gtk_tree_row_reference_free (llItr->data) ;

      // Remove cell from old location
      gtk_tree_store_remove (ts, &itrSrc) ;

      // The bus that owned the row we just moved has become empty - delete it
      if (NULL != refSrcParent)
        {
        tpSrcParent = gtk_tree_row_reference_get_path (refSrcParent) ;

        if (gtk_tree_model_get_iter (GTK_TREE_MODEL (ts), &itrSrcParent, tpSrcParent))
          gtk_tree_store_remove (ts, &itrSrcParent) ;

        gtk_tree_path_free (tpSrcParent) ;
        gtk_tree_row_reference_free (refSrcParent) ;
        refSrcParent = NULL ;
        }
      }
    else
      gtk_tree_path_free (tp) ;
    }

  gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tview)), tp = gtk_tree_row_reference_get_path (refBus)) ;

  gtk_tree_path_free (tp) ;
  gtk_tree_row_reference_free (refBus) ;
  g_list_free (llTreeRefs) ;
  }
Beispiel #5
0
static void
fm_list_model_sort_file_entries (FMListModel *model, GSequence *files, GtkTreePath *path)
{
    GSequenceIter **old_order;
    GtkTreeIter iter;
    int *new_order;
    int length;
    int i;
    FileEntry *file_entry;
    gboolean has_iter;

    length = g_sequence_get_length (files);

    if (length <= 1)
    {
        return;
    }

    /* generate old order of GSequenceIter's */
    old_order = g_new (GSequenceIter *, length);
    for (i = 0; i < length; ++i)
    {
        GSequenceIter *ptr = g_sequence_get_iter_at_pos (files, i);

        file_entry = g_sequence_get (ptr);
        if (file_entry->files != NULL)
        {
            gtk_tree_path_append_index (path, i);
            fm_list_model_sort_file_entries (model, file_entry->files, path);
            gtk_tree_path_up (path);
        }

        old_order[i] = ptr;
    }

    /* sort */
    g_sequence_sort (files, fm_list_model_file_entry_compare_func, model);

    /* generate new order */
    new_order = g_new (int, length);
    /* Note: new_order[newpos] = oldpos */
    for (i = 0; i < length; ++i)
    {
        new_order[g_sequence_iter_get_position (old_order[i])] = i;
    }

    /* Let the world know about our new order */

    g_assert (new_order != NULL);

    has_iter = FALSE;
    if (gtk_tree_path_get_depth (path) != 0)
    {
        gboolean get_iter_result;
        has_iter = TRUE;
        get_iter_result = gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
        g_assert (get_iter_result);
    }

    gtk_tree_model_rows_reordered (GTK_TREE_MODEL (model),
                                   path, has_iter ? &iter : NULL, new_order);

    g_free (old_order);
    g_free (new_order);
}
Beispiel #6
0
bool
sc_navigate_index(girara_session_t* session, girara_argument_t* argument,
                  girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  if(zathura->ui.index == NULL) {
    return false;
  }

  GtkTreeView *tree_view = gtk_container_get_children(GTK_CONTAINER(zathura->ui.index))->data;
  GtkTreePath *path;

  gtk_tree_view_get_cursor(tree_view, &path, NULL);
  if (path == NULL) {
    return false;
  }

  GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  GtkTreeIter   iter;
  GtkTreeIter   child_iter;

  gboolean is_valid_path = TRUE;

  switch(argument->n) {
    case UP:
      if (gtk_tree_path_prev(path) == FALSE) {
        /* For some reason gtk_tree_path_up returns TRUE although we're not
         * moving anywhere. */
        is_valid_path = gtk_tree_path_up(path) && (gtk_tree_path_get_depth(path) > 0);
      } else { /* row above */
        while(gtk_tree_view_row_expanded(tree_view, path)) {
          gtk_tree_model_get_iter(model, &iter, path);
          /* select last child */
          gtk_tree_model_iter_nth_child(model, &child_iter, &iter,
                                        gtk_tree_model_iter_n_children(model, &iter)-1);
          gtk_tree_path_free(path);
          path = gtk_tree_model_get_path(model, &child_iter);
        }
      }
      break;
    case COLLAPSE:
      if (gtk_tree_view_collapse_row(tree_view, path) == FALSE
          && gtk_tree_path_get_depth(path) > 1) {
        gtk_tree_path_up(path);
        gtk_tree_view_collapse_row(tree_view, path);
      }
      break;
    case DOWN:
      if (gtk_tree_view_row_expanded(tree_view, path) == TRUE) {
        gtk_tree_path_down(path);
      } else {
        do {
          gtk_tree_model_get_iter(model, &iter, path);
          if (gtk_tree_model_iter_next(model, &iter)) {
            gtk_tree_path_free(path);
            path = gtk_tree_model_get_path(model, &iter);
            break;
          }
        } while((is_valid_path = (gtk_tree_path_get_depth(path) > 1))
                && gtk_tree_path_up(path));
      }
      break;
    case EXPAND:
      if (gtk_tree_view_expand_row(tree_view, path, FALSE)) {
        gtk_tree_path_down(path);
      }
      break;
    case EXPAND_ALL:
      gtk_tree_view_expand_all(tree_view);
      break;
    case COLLAPSE_ALL:
      gtk_tree_view_collapse_all(tree_view);
      gtk_tree_path_free(path);
      path = gtk_tree_path_new_first();
      gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE);
      break;
    case SELECT:
      cb_index_row_activated(tree_view, path, NULL, zathura);
      gtk_tree_path_free(path);
      return false;
  }

  if (is_valid_path) {
    gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE);
  }

  gtk_tree_path_free(path);

  return false;
}
Beispiel #7
0
/* load submenu from disk */
void load_sub_menu_from_disk (char *file_to_load, GtkTreeStore *store,
                              GtkTreeIter *iter)
{
  FILE *menufile;
  char buf[1024];
  char first = 1;
  char s[4096];
  GtkTreeIter sub_iter;

  if (!file_to_load)
    return;
  if (file_to_load[0] != '/')
    sprintf (buf, "%s/%s", gv.epath, file_to_load);
  else
    sprintf (buf, "%s", file_to_load);

  menufile = fopen (buf, "r");

#ifdef DEBUG
  g_print ("Loading submenu: %s\n", buf);
#endif /* DEBUG */

  if (!menufile)
    return;

  while (fgets (s, 4096, menufile))
  {
    s[strlen (s) - 1] = 0;
    if ((s[0] && s[0] != '#'))
    {
      if (first)
        first = 0;
      else
      {
        gchar **data;

	menu_regex (s, &data);

        gtk_tree_store_append (store, &sub_iter, iter);
        gtk_tree_store_set (store, &sub_iter,
                            COL_DESCRIPTION, data[0],
                            COL_ICON, gdk_pixbuf_new_from_file (data[1], NULL),
                            COL_ICONNAME, data[1],
                            COL_PARAMS, data[3],
                            -1);


        if (!strcasecmp (data[2], "menu"))
          load_sub_menu_from_disk (data[3], store, &sub_iter);

	g_free (data[0]);
	g_free (data[1]);
	g_free (data[2]);
	g_free (data[3]);
	g_free (data);
      }
    }
  }

  fclose (menufile);

  return;
}

#define WRITE_FILE /* undef this for debugging without writing menus */
gboolean table_save_func (GtkTreeModel *model, GtkTreePath *path,
                          GtkTreeIter *iter, gpointer user_data)
{
  gchar *description, *icon, *params;
  gchar *tree_path_str;
  gboolean has_child;
  gint depth;
  gchar *realfile;
  gchar *dirname;
  FILE *menu_ptr, *menu_ptr2;
  gchar buffer[128];

  gtk_tree_model_get (model, iter,
                      COL_DESCRIPTION, &description,
                      COL_ICONNAME, &icon,
                      COL_PARAMS, &params,
                      -1);

  tree_path_str = gtk_tree_path_to_string(path);

  has_child = gtk_tree_model_iter_has_child (model, iter);
  depth = gtk_tree_path_get_depth (path) - 1;

  if (depth + 1 >= MAX_RECURSION)
  {
    g_print ("maximum menu recursion reached! -> %d\n", MAX_RECURSION);
    return TRUE;
  }

  if (!g_path_is_absolute (params))
  {
    /* Tarnation! A relative path */
    //realfile = g_strjoin ("/", gv.epath, params, NULL);
    realfile = g_strdup_printf ("%s/%s", gv.epath, params);
    //g_print ("FILE: %s,%s,%s\n", gv.epath, params, realfile);
  }
  else
  {
    realfile = g_strdup (params);
  }

  menu_file[depth] = g_strdup (realfile);

#ifdef WRITE_FILE
  /* create recursiv new menu subdirectory */
  dirname = g_path_get_dirname (realfile);
  mkdir_with_parent (dirname, 0755);
  g_free (dirname);
#endif /* WRITE_FILE */

  if (depth > 0)
  {
#ifdef WRITE_FILE
    menu_ptr = fopen (menu_file[depth-1], "a+");
#endif /* WRITE_FILE */
    if (!menu_ptr)
    {
      printf ("Couldn't save menu to: %s\n", menu_file[depth-1]);
    }

    if (has_child)
    {
#ifdef WRITE_FILE
      menu_ptr2 = fopen (menu_file[depth], "w");
      if (!menu_ptr2)
      {
        printf ("Couldn't save menu to: %s\n", menu_file[depth]);
      }
#endif /* WRITE_FILE */

      sprintf (buffer, "\"%s\"\n", description);
#ifdef WRITE_FILE
      fprintf (menu_ptr2, "%s", from_utf8 (buffer));
      fclose (menu_ptr2);
#else
      g_print ("write header to: \"%s\"\n", menu_file[depth]);
#endif /* !WRITE_FILE */

      sprintf (buffer, "\"%s\"\t%s\tmenu\t\"%s\"\n",
               description[0] == '\0' ? "NULL" : description,
               icon[0] == '\0' ? "NULL" : icon,
               params[0] == '\0' ? "" : params);
#ifdef WRITE_FILE
      fprintf (menu_ptr, "%s", from_utf8 (buffer));
#else
      g_print ("write menu to: \"%s\"\n", menu_file[depth-1]);
#endif /* WRITE_FILE */
    }
    else
    {
      sprintf (buffer, "\"%s\"\t%s\texec\t\"%s\"\n",
               description[0] == '\0' ? "NULL" : description,
               icon[0] == '\0' ? "NULL" : icon,
               params[0] == '\0' ? "" : params);
#ifdef WRITE_FILE
      fprintf (menu_ptr, "%s", from_utf8 (buffer));
#else
      g_print ("write exec to: \"%s\"\n", menu_file[depth-1]);
#endif /*WRITE_FILE */
    }
#ifdef WRITE_FILE
    fclose (menu_ptr);
#endif /*WRITE_FILE */
  }
  else
  {
#ifdef WRITE_FILE
    menu_ptr2 = fopen (menu_file[depth], "w");
    if (!menu_ptr2)
    {
      printf ("Couldn't save menu to: %s\n", menu_file[depth]);
    }
#endif /*WRITE_FILE */

    sprintf (buffer, "\"%s\"\n", description);
#ifdef WRITE_FILE
    fprintf (menu_ptr2, "%s", from_utf8 (buffer));
    fclose (menu_ptr2);
#else
    g_print ("write first header to: \"%s\"\n", menu_file[depth]);
#endif /* WRITE_FILE */
  }

#ifndef WRITE_FILE
  g_print ("%s | ", tree_path_str);
  g_print ("%s %s %s\n", description, icon, params);
#endif /* !WRITE_FILE */

  /* end of filelist to free it later */
  menu_file[depth+1] = NULL;

  g_free (tree_path_str);
  g_free (realfile);
  g_free (description);
  g_free (icon);
  g_free (params);

  return FALSE;
}
/* Create an iter from the given path */
static gboolean replay_message_tree_get_iter(GtkTreeModel *tree_model,
                                          GtkTreeIter *iter,
                                          GtkTreePath *path)
{
  ReplayMessageTree *self;
  ReplayMessageTreePrivate *priv;
  ReplayMessageTreeEntry *entry;
  gint *indices, depth;
  gint i;

  g_return_val_if_fail(REPLAY_IS_MESSAGE_TREE(tree_model), FALSE);
  g_return_val_if_fail(path != NULL, FALSE);

  self = REPLAY_MESSAGE_TREE(tree_model);
  priv = self->priv;

  indices = gtk_tree_path_get_indices(path);
  depth = gtk_tree_path_get_depth(path);

  /* need to walk our tree down to the position - for each indices, go along */
  entry = priv->first_child;

  if (entry)
  {
    for (i = 0; i < depth; i++)
    {
      int j;
      /* go to indices position */
      for (j = 0; j < indices[i]; j++)
      {
        if (entry->next)
        {
          entry = entry->next;
        }
        else
        {
          return FALSE;
        }
      }

      /* descend if not at last level */
      if (i < depth - 1)
      {
        if (entry->first_child)
        {
          entry = entry->first_child;
        }
        else
        {
          return FALSE;
        }
      }
    }
    g_assert(gtk_tree_path_compare(path, entry->tree_path) == 0);
    g_assert(entry != NULL);

    /* set stamp and only need first user_data slot */
    iter->stamp = priv->stamp;
    iter->user_data = entry;
    iter->user_data2 = NULL;
    iter->user_data3 = NULL;

    return TRUE;
  }
  else
  {
    return FALSE;
  }
}
Beispiel #9
0
static VALUE
rg_depth(VALUE self)
{
    return INT2NUM(gtk_tree_path_get_depth(_SELF(self)));
}
Beispiel #10
0
static gboolean
button_press_callback (GtkTreeView *tree_view, GdkEventButton *event, FMListView *view)
{
    GtkTreeSelection    *selection;
    GtkTreePath         *path;
    GtkTreeIter         iter;
    GtkAction           *action;
    GOFFile             *file;

    selection = gtk_tree_view_get_selection (tree_view);
    /* check if the event is for the bin window */
    if (G_UNLIKELY (event->window != gtk_tree_view_get_bin_window (tree_view)))
        return FALSE;

    /* we unselect all selected items if the user clicks on an empty
     * area of the treeview and no modifier key is active.
     */
    if ((event->state & gtk_accelerator_get_default_mod_mask ()) == 0
        && !gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y, NULL, NULL, NULL, NULL))
    {
        gtk_tree_selection_unselect_all (selection);
    }

    /* open the context menu on right clicks */
    if (event->type == GDK_BUTTON_PRESS && event->button == 3)
    {
        if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y, &path, NULL, NULL, NULL))
        {
            /* select the path on which the user clicked if not selected yet */
            if (!gtk_tree_selection_path_is_selected (selection, path))
            {
                /* we don't unselect all other items if Control is active */
                if ((event->state & GDK_CONTROL_MASK) == 0)
                    gtk_tree_selection_unselect_all (selection);
                if (!gtk_tree_view_is_blank_at_pos (tree_view, event->x, event->y, NULL, NULL, NULL, NULL)	&& gtk_tree_path_get_depth (path) == 1) 
                    gtk_tree_selection_select_path (selection, path);
            }
            
            gtk_tree_path_free (path);
        }
        /* queue the menu popup */
        fm_directory_view_queue_popup (FM_DIRECTORY_VIEW (view), event);

        return TRUE;
    }
    else if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS) && event->button == 2)
    {
        /* determine the path to the item that was middle-clicked */
        if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y, &path, NULL, NULL, NULL))
        {
            /* select only the path to the item on which the user clicked */
            gtk_tree_selection_unselect_all (selection);
            gtk_tree_selection_select_path (selection, path);

            fm_directory_view_activate_selected_items (FM_DIRECTORY_VIEW (view), MARLIN_WINDOW_OPEN_FLAG_NEW_TAB);

            /* cleanup */
            gtk_tree_path_free (path);
        } 

        return TRUE;
    }

    return FALSE;
}
static void
signal_monitor_generic_handler (SignalMonitor *m,
                                SignalName     signal,
                                GtkTreeModel  *model,
                                GtkTreeIter   *iter,
                                GtkTreePath   *path,
                                int           *new_order)
{
  Signal *s;

  if (g_queue_is_empty (m->queue))
    {
      gchar *path_str;

      path_str = gtk_tree_path_to_string (path);
      g_error ("Signal queue empty, got signal %s path %s",
               signal_name_to_string (signal), path_str);
      g_free (path_str);

      g_assert_not_reached ();
    }

  if (m->client != model)
    {
      g_error ("Model mismatch; expected %p, got %p",
               m->client, model);
      g_assert_not_reached ();
    }

  s = g_queue_peek_tail (m->queue);

#if 0
  /* For debugging: output signals that are coming in.  Leaks memory. */
  g_print ("signal=%s path=%s\n", signal_name_to_string (signal),
           gtk_tree_path_to_string (path));
#endif

  if (s->signal != signal ||
      (gtk_tree_path_get_depth (s->path) == 0 &&
       gtk_tree_path_get_depth (path) != 0) ||
      (gtk_tree_path_get_depth (s->path) != 0 &&
       gtk_tree_path_compare (s->path, path) != 0))
    {
      gchar *path_str, *s_path_str;

      s_path_str = gtk_tree_path_to_string (s->path);
      path_str = gtk_tree_path_to_string (path);

      g_error ("Signals don't match; expected signal %s path %s, got signal %s path %s",
               signal_name_to_string (s->signal), s_path_str,
               signal_name_to_string (signal), path_str);

      g_free (s_path_str);
      g_free (path_str);

      g_assert_not_reached ();
    }

  if (signal == ROWS_REORDERED && s->new_order != NULL)
    {
      int i, len;

      g_assert (new_order != NULL);

      len = gtk_tree_model_iter_n_children (model, iter);
      g_assert (s->len == len);

      for (i = 0; i < len; i++)
        g_assert (s->new_order[i] == new_order[i]);
    }

  s = g_queue_pop_tail (m->queue);

  signal_free (s);
}
Beispiel #12
0
/**
@brief paste tree rows into @a treeview

Row(s) are inserted after the 1st selected row in @a treeview,
as child(ren) if the path depth is appropriate
It is assumed here that the buffer hash has pastable data

@param rowscopied list of copied value-arrays
@param treeview the treeview to be processed

@return
*/
void e2_tree_paste (GList *rowscopied, GtkTreeView *treeview)
{
	GtkTreeSelection *sel = gtk_tree_view_get_selection (treeview);
	if (gtk_tree_selection_count_selected_rows (sel) > 0)
	{
		//get source-view path for the 1st buffered item, the
		//root of the copied branch (or one of several roots)
		GArray *value_array = rowscopied->data;
		GValue *value = &g_array_index (value_array, GValue, 0);
//		gchar *pathstring = g_value_dup_string (value);
//		GtkTreePath *path = gtk_tree_path_new_from_string (pathstring);
		GtkTreePath *rootpath = (GtkTreePath *) g_value_get_pointer (value);
		gint copyrootdepth = gtk_tree_path_get_depth (rootpath);
//		gtk_tree_path_free (path);
		//store for references (hence iters) needed to preserve relations
		//among pasted rows
		GHashTable *ref_hash = NULL;
		GtkTreeRowReference *ref;

		GtkTreeModel *model;
		GList *selpaths = gtk_tree_selection_get_selected_rows (sel, &model);
		gint columns = gtk_tree_model_get_n_columns (model);
		GList *tmp;
		GtkTreeIter local1;
		GtkTreeIter local2;
		GtkTreeIter *iter = &local1;
		GtkTreeIter *parent = &local2;

		//find a selected item where it's valid to paste
		for (tmp = selpaths; tmp != NULL; tmp = tmp->next)
		{
			if (gtk_tree_model_get_iter (model, iter, (GtkTreePath *) tmp->data))
			{
				gint thisdepth = gtk_tree_path_get_depth (tmp->data);
				if (thisdepth == copyrootdepth)
				{	//the selected row is a valid sibling of the buffered row(s)
					//paste the root of the copied branch
					printd (DEBUG, "pasting branch root, at depth %d", thisdepth);
/*					if (gtk_tree_model_iter_parent (model, parent, iter))
					{	//pasted row (iter) will be _pre_pended to parent's children
						gtk_tree_store_insert_after (GTK_TREE_STORE (model), iter, parent, NULL);
					}
					else //parent is the root node
					{ */
					//pasted row (iter) will be inserted after selected row
						gtk_tree_store_insert_after (GTK_TREE_STORE (model), parent, NULL, iter);
						iter = parent;
//					}
					break;
				}
				else if (thisdepth == copyrootdepth - 1)
				{	//the selected item is a parent of the buffered row(s)
					//pasted row (iter) will be appended to parent's children
					printd (DEBUG, "pasting branch root, at depth %d", thisdepth);
					gtk_tree_store_insert_before (GTK_TREE_STORE (model), parent, iter, NULL);
					iter = parent;
					break;
				}
			}
			//keep looking ...
		}
		if (tmp != NULL)
		{	//found a place where it's ok to paste
			//populate the newly-added "root" iter
			gint i;
			for (i = 0; i < columns; i++)
			{
				value = &g_array_index (value_array, GValue, i+1);
				gtk_tree_store_set_value (GTK_TREE_STORE (model), iter, i, value);
			}

			//remember how to find the parent of each pasted iter
			//the hash key (a path from the source treeview) is used
			//determine parent/child relations between pasted rows
			ref_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
				g_free, (GDestroyNotify) gtk_tree_row_reference_free);
//			ref_hash = g_hash_table_new_full (g_direct_hash,
//				(GEqualFunc) _e2_tree_path_compare,
//				NULL,	//we don't want to damage the buffered paths
//				(GDestroyNotify) gtk_tree_row_reference_free);
			GtkTreePath *path = gtk_tree_model_get_path (model, iter);
			ref = gtk_tree_row_reference_new (model, path);
			gtk_tree_path_free (path);
//			g_hash_table_insert (ref_hash, pathstring, ref);
			gchar *rootstring = gtk_tree_path_to_string (rootpath);
			g_hash_table_insert (ref_hash, rootstring, ref);

			//now the rest of the list, if any
			//there may be descendant(s) and/or sibling(s) of the initial item
			GtkTreePath *src_path;
			gchar *ppstring;
			GList *tmp2 = rowscopied;
			while ((tmp2 = tmp2->next) != NULL)
			{
				value_array = tmp2->data;
				//get source-view path and find where it should sit in the new tree
				value = &g_array_index (value_array, GValue, 0);
//				pathstring = g_value_dup_string (value);
				src_path = (GtkTreePath *) g_value_get_pointer (value);
				path = gtk_tree_path_copy (src_path);
				//get former parent path string, by truncating the last segment
//				gchar *s = g_strrstr (pathstring, ":");
//				if (s != NULL)
//				{
//					*s = '\0';
				if (gtk_tree_path_up (path))
				{
					//try to find an already-pasted parent iter
					ppstring = gtk_tree_path_to_string (path);
					if (ppstring != NULL)
					{	//we're not at the root node now
						ref = g_hash_table_lookup (ref_hash, ppstring);
						gtk_tree_path_free (path);
						g_free (ppstring);
					}
					else
						ref = NULL;
					if (ref != NULL)
					{
						path = gtk_tree_row_reference_get_path (ref);
						gtk_tree_model_get_iter (model, parent, path);
						gtk_tree_path_free (path);
						//append row (iter) to parent's children
						gtk_tree_store_insert_before (
							GTK_TREE_STORE (model), iter, parent, NULL);
					}
					else
					{	//this is probably a sibling
						ref = g_hash_table_lookup (ref_hash, rootstring);
						path = gtk_tree_row_reference_get_path (ref);
						gtk_tree_model_get_iter (model, parent, path);
						gtk_tree_path_free (path);
						//append row (iter) to as a sibling
						gtk_tree_store_insert_after (
							GTK_TREE_STORE (model), iter, NULL, parent);
					}
				}
				else
				{
					//CHECKME probably can't be at a root already
					printd (DEBUG, "root node problem");
					continue;
				}
				//populate row
				for (i = 0; i < columns; i++)
				{
					value = &g_array_index (value_array, GValue, i+1);
					gtk_tree_store_set_value (GTK_TREE_STORE (model), iter, i, value);
				}
//				g_free (pathstring);
				//remember newly-added iter in case it's a parent
				path = gtk_tree_model_get_path (model, iter);
				ref = gtk_tree_row_reference_new (model, path);
				gtk_tree_path_free (path);
				ppstring = gtk_tree_path_to_string (src_path);
//				g_hash_table_insert (ref_hash, g_value_dup_string (value), ref);
				g_hash_table_insert (ref_hash, ppstring, ref);
			}
			//no change to (single row) selection, as all new rows are after
			if (ref_hash != NULL)
				g_hash_table_destroy (ref_hash);
		}
		g_list_foreach (selpaths, (GFunc) gtk_tree_path_free, NULL);
		g_list_free (selpaths);
	}
}
Beispiel #13
0
/*#
    @method get_depth GtkTreePath
    @brief Returns the current depth of path.
    @return The depth of path
 */
FALCON_FUNC TreePath::get_depth( VMARG )
{
    NO_ARGS
    MYSELF;
    vm->retval( gtk_tree_path_get_depth( self->getTreePath() ) );
}
Beispiel #14
0
/* 
 * key has been pressed while being in watch tree view
 */
static gboolean on_watch_key_pressed_callback(GtkWidget *widget, GdkEvent  *event, gpointer user_data)
{
	/* handling only Delete button pressing
	 * that means "delete selected rows" */
	int keyval = ((GdkEventKey*)event)->keyval;
	if (keyval != GDK_Delete)
		return FALSE;

	/* get selected rows */
	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree));
	GList *rows = gtk_tree_selection_get_selected_rows(selection, &wmodel);
	
	/* empty row path */
	GtkTreePath *empty_path = wtree_empty_path();

	/* check whether only empty row was selected */
	if (1 != gtk_tree_selection_count_selected_rows(selection) ||
	    gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path))
	{
		/* path reference to select after deleteing finishes */
		GtkTreeRowReference *reference_to_select = NULL;

		/* get references to the rows */
		GList *references = NULL;
		GList *iter = rows;
		while (iter)
		{
			GtkTreePath *path = (GtkTreePath*)iter->data;

			/* move up paths to the root elements */
			while (gtk_tree_path_get_depth(path) > 1)
				gtk_tree_path_up(path);

			/* add path reference if it's not an empty row*/
			if (gtk_tree_path_compare(path, empty_path))
				references = g_list_append(references, gtk_tree_row_reference_new(wmodel, path));

			iter = iter->next;
		}

		/* iterate through references and remove */
		iter = references;
		while (iter)
		{
			GtkTreeRowReference *reference = (GtkTreeRowReference*)iter->data;
			/* check for valid reference because two or more equal
			refernces could be put in the list if several child items
			of the same node were selected and the path for the
			current reference was already deleted */
			if (gtk_tree_row_reference_valid(reference))
			{
				GtkTreePath *path = gtk_tree_row_reference_get_path(reference);

				if (!reference_to_select)
				{
					/* select upper sibling of the upper
					selected row that has unselected upper sibling */
					GtkTreePath *sibling = gtk_tree_path_copy(path);
					if(gtk_tree_path_prev(sibling))
					{
						if (!gtk_tree_selection_path_is_selected(selection, sibling))
							reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling);
					}
					else if (gtk_tree_path_next(sibling), gtk_tree_path_compare(path, sibling))
						reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling);
				}

				/* get iterator */
				GtkTreeIter titer;
				gtk_tree_model_get_iter(wmodel, &titer, path);

				/* remove from the debug session, if it's active */
				if (DBS_STOPPED == debug_state)
				{

					gchar *internal = NULL;
					gtk_tree_model_get (
						wmodel,
						&titer,
						W_INTERNAL, &internal,
						-1);

					active_module->remove_watch(internal);

					g_free(internal);
				}


				gtk_tree_store_remove(wstore, &titer);
			}
			
			iter = iter->next;
		}

		/* if all (with or without empty row) was selected - set empty row
		as a path to be selected after deleting */
		if (!reference_to_select)
			reference_to_select = gtk_tree_row_reference_new (gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), wtree_empty_path());

		/* set selection */
		gtk_tree_selection_unselect_all(selection);
		GtkTreePath *path_to_select = gtk_tree_row_reference_get_path(reference_to_select);
		gtk_tree_selection_select_path(selection, path_to_select);
		gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path_to_select, NULL, TRUE, 0.5, 0.5);
		gtk_tree_path_free(path_to_select);	

		/* free references list */
		g_list_foreach (references, (GFunc)gtk_tree_row_reference_free, NULL);
		g_list_free (references);

		config_set_debug_changed();
	}

	/* free rows list */
	g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
	g_list_free (rows);

	return FALSE;
}
Beispiel #15
0
/*
 * key pressed event
 */
static gboolean on_key_pressed(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
	/* do not process event is page is readonly (debug is running) */
	if (readonly)
		return FALSE;

    guint keyval = ((GdkEventKey*)event)->keyval;

	/* get selected rows */
	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
	GList *rows = gtk_tree_selection_get_selected_rows(selection, &model);
	rows = g_list_sort(rows, (GCompareFunc)gtk_tree_path_compare);

	if (keyval == GDK_Delete && rows && g_list_length(rows))
	{
		/* "delete selected rows" */

		/* get new selection */
		GtkTreeRowReference *new_selection = NULL;
		GtkTreePath *first_path = (GtkTreePath*)rows->data;
		if (gtk_tree_path_get_depth(first_path) > 1)
		{
			new_selection = get_unselected_sibling(first_path);
		}
		if (!new_selection)
		{
			GtkTreePath *file_path = gtk_tree_path_copy(first_path);
			if (gtk_tree_path_get_depth(file_path) > 1)
			{
				gtk_tree_path_up(file_path);
			}
			new_selection = get_unselected_sibling(file_path);
			gtk_tree_path_free(file_path);
		}
		
		/* collect GList of breakpoints to remove
		if file row is met - add all unselected breaks to the list as well */
		GList *iter = rows;
		GList *breaks = NULL;
		while (iter)
		{
			GtkTreePath *path = (GtkTreePath*)iter->data;
			
			GtkTreeIter titer;
			gtk_tree_model_get_iter(model, &titer, path);
			
			if (1 == gtk_tree_path_get_depth(path))
			{
				GtkTreeIter citer;
				gtk_tree_model_iter_children(model, &citer, &titer);
				
				do
				{
					if (!gtk_tree_selection_iter_is_selected(selection, &citer))
					{
						gchar *file = NULL;
						gint line;

						gtk_tree_model_get(model, &titer, FILEPATH, &file, -1);
						gtk_tree_model_get(model, &citer, LINE, &line, -1);

						breakpoint *bp = breaks_lookup_breakpoint(file, line);
						
						breaks = g_list_append(breaks, bp);
						
						g_free(file);
					}
				}
				while(gtk_tree_model_iter_next(model, &citer));
			}
			else
			{
				GtkTreeIter piter;
				gtk_tree_model_iter_parent(model, &piter, &titer);
				
				gchar *file = NULL;
				gtk_tree_model_get(model, &piter, FILEPATH, &file, -1);

				gint line;
				gtk_tree_model_get(model, &titer, LINE, &line, -1);

				breakpoint *bp = breaks_lookup_breakpoint(file, line);
				
				breaks = g_list_append(breaks, bp);
				
				g_free(file);
			}
			iter = iter->next;
		}
		
		if (1 == g_list_length(breaks))
		{
			breakpoint *bp = (breakpoint*)breaks->data;
			g_list_free(breaks);
			breaks_remove(bp->file, bp->line);
		}
		else
		{
			breaks_remove_list(breaks);
		}

		if (new_selection)
		{
			/* get path to select */
			GtkTreePath *path = NULL;
			path = gtk_tree_row_reference_get_path(new_selection);

			gtk_tree_selection_select_path(selection, path);
			gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path, NULL, TRUE, 0.5, 0.5);
			gtk_tree_path_free(path);

			gtk_tree_row_reference_free(new_selection);
		}
	}

	/* free rows list */
	g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
	g_list_free (rows);

	return FALSE;
}