static void raise_bus_cell_position (GtkWidget *widget, gpointer data) { bus_layout_D *dialog = (bus_layout_D *)data ; GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tview)) ; GtkTreeModel *tm = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tview)) ; GtkTreePath *tpBus = g_object_get_data (G_OBJECT (dialog->tview), "tpBus") ; GtkTreePath *tpSrc = NULL, *tpDst = NULL ; int icChildren = -1, Nix ; if (NULL == tpBus) return ; if (0 == (icChildren = gtk_tree_model_path_n_children (tm, tpBus))) return ; gtk_tree_path_down (tpDst = gtk_tree_path_copy (tpBus)) ; gtk_tree_path_next (tpSrc = gtk_tree_path_copy (tpDst)) ; for (Nix = 1 ; Nix < icChildren ; Nix++) { if (gtk_tree_selection_path_is_selected (sel, tpSrc)) { // swap the 2 rows swap_model_paths_contents (tm, tpSrc, tpDst) ; gtk_tree_selection_unselect_path (sel, tpSrc) ; gtk_tree_selection_select_path (sel, tpDst) ; } gtk_tree_path_next (tpSrc) ; gtk_tree_path_next (tpDst) ; } }
// This callback is responsible for enabling/disabling the appropriate buttons depending on // the contents of the selection static void tree_view_selection_changed (GtkTreeSelection *sel, gpointer data) { bus_layout_D *dialog = (bus_layout_D *)data ; gboolean bSomethingSelected = FALSE ; gboolean bBusSelected = FALSE ; gboolean bSelectionIsFromBus = FALSE ; gboolean bFirstSelected = FALSE ; gboolean bLastSelected = FALSE ; gboolean bFirstBusSelected = TRUE ; gboolean bLastBusSelected = TRUE ; GtkTreePath *tpSelBus = NULL, *tp = NULL ; GtkTreeModel *tm = NULL ; int icChildren = -1, Nix ; tm = gtk_tree_view_get_model (gtk_tree_selection_get_tree_view (sel)) ; if ((bSelectionIsFromBus = (NULL != (tpSelBus = get_selection_bus (sel, &bSomethingSelected))))) if (!(bFirstSelected = bLastSelected = bBusSelected = whole_bus_selected_p (sel, tm, tpSelBus))) if ((icChildren = gtk_tree_model_path_n_children (tm, tpSelBus)) > 0) { gtk_tree_path_down (tp = gtk_tree_path_copy (tpSelBus)) ; bFirstSelected = gtk_tree_selection_path_is_selected (sel, tp) ; for (Nix = 1 ; Nix < icChildren ; Nix++) gtk_tree_path_next (tp) ; bLastSelected = gtk_tree_selection_path_is_selected (sel, tp) ; gtk_tree_path_free (tp) ; } if (bSelectionIsFromBus) determine_first_or_last_bus (tm, tpSelBus, &bFirstBusSelected, &bLastBusSelected) ; gtk_widget_set_sensitive (dialog->btnCreateBus, bSomethingSelected && !bBusSelected) ; gtk_widget_set_sensitive (dialog->btnDeleteBus, bSelectionIsFromBus) ; gtk_widget_set_sensitive (dialog->btnMoveBusUp, bSelectionIsFromBus && !bFirstBusSelected) ; gtk_widget_set_sensitive (dialog->btnMoveBusDown, bSelectionIsFromBus && !bLastBusSelected) ; gtk_widget_set_sensitive (dialog->btnMoveCellsUp, bSelectionIsFromBus && !bFirstSelected) ; gtk_widget_set_sensitive (dialog->btnMoveCellsDown, bSelectionIsFromBus && !bLastSelected) ; gtk_widget_set_sensitive (dialog->lblBusName, bSelectionIsFromBus) ; gtk_widget_set_sensitive (dialog->txtBusName, bSelectionIsFromBus) ; // Fill in the text box with the name of the bus if (bSelectionIsFromBus) { GtkTreeIter itr ; char *psz = NULL ; gtk_tree_model_get_iter (tm, &itr, tpSelBus) ; gtk_tree_model_get (tm, &itr, BUS_LAYOUT_MODEL_COLUMN_NAME, &psz, -1) ; g_signal_handlers_block_matched (G_OBJECT (dialog->txtBusName), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, (gpointer)bus_name_changed, NULL) ; gtk_entry_set_text (GTK_ENTRY (dialog->txtBusName), psz) ; g_signal_handlers_unblock_matched (G_OBJECT (dialog->txtBusName), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, (gpointer)bus_name_changed, NULL) ; g_free (psz) ; } if (NULL != (tp = g_object_get_data (G_OBJECT (gtk_tree_selection_get_tree_view (sel)), "tpBus"))) gtk_tree_path_free (tp) ; g_object_set_data (G_OBJECT (gtk_tree_selection_get_tree_view (sel)), "tpBus", tpSelBus) ; }
static GList *get_bus_refs (GtkTreeModel *tm, GtkTreePath *tpBus) { int Nix, icChildren = -1 ; GList *llRefs = NULL ; GtkTreePath *tp = gtk_tree_path_copy (tpBus) ; icChildren = gtk_tree_model_path_n_children (tm, tp) ; gtk_tree_path_down (tp) ; for (Nix = 0 ; Nix < icChildren ; Nix++, gtk_tree_path_next (tp)) llRefs = g_list_prepend (llRefs, gtk_tree_row_reference_new (tm, tp)) ; gtk_tree_path_free (tp) ; return llRefs ; }
static void delete_bus_button_clicked (GtkWidget *widget, gpointer data) { int icChildren = -1 ; bus_layout_D *dialog = (bus_layout_D *)data ; GtkTreeModel *tm = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tview)) ; GtkTreePath *tpBus = g_object_get_data (G_OBJECT (dialog->tview), "tpBus") ; GtkTreeRowReference *trrBus = NULL ; GtkTreeIter itr, itrSrc ; GList *llBusRefs = NULL, *llItr = NULL ; GtkTreePath *tp = NULL ; if (NULL == tpBus) return ; icChildren = gtk_tree_model_path_n_children (tm, tpBus) ; // There should always be some children if (0 == icChildren) return ; trrBus = gtk_tree_row_reference_new (tm, tpBus) ; llBusRefs = get_bus_refs (tm, tpBus) ; for (llItr = llBusRefs ; llItr != NULL ; llItr = llItr->next) { gtk_tree_store_append (GTK_TREE_STORE (tm), &itr, NULL) ; gtk_tree_model_get_iter (tm, &itrSrc, tp = gtk_tree_row_reference_get_path (llItr->data)) ; gtk_tree_path_free (tp) ; swap_model_iters_contents (tm, &itrSrc, &itr) ; gtk_tree_row_reference_free (llItr->data) ; } g_list_free (llBusRefs) ; gtk_tree_model_get_iter (tm, &itrSrc, tp = gtk_tree_row_reference_get_path (trrBus)) ; gtk_tree_path_free (tp) ; gtk_tree_store_remove (GTK_TREE_STORE (tm), &itrSrc) ; gtk_tree_row_reference_free (trrBus) ; }
static void lower_bus_cell_position (GtkWidget *widget, gpointer data) { bus_layout_D *dialog = (bus_layout_D *)data ; GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tview)) ; GtkTreeModel *tm = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tview)) ; GtkTreePath *tpBus = g_object_get_data (G_OBJECT (dialog->tview), "tpBus") ; GtkTreePath *tpSrc = NULL, *tpDst = NULL ; int icChildren = -1, Nix ; if (NULL == tpBus) { fprintf (stderr, "lower_bus_cell_position: tpBus == NULL !\n") ; return ; } if (0 == (icChildren = gtk_tree_model_path_n_children (tm, tpBus))) { fprintf (stderr, "lower_bus_cell_position: tpBus has no children O_o\n") ; return ; } gtk_tree_path_down (tpDst = gtk_tree_path_copy (tpBus)) ; for (Nix = 1 ; Nix < icChildren ; Nix++) gtk_tree_path_next (tpDst) ; // St00pid short-circuit if statement to suppress a warning. if (gtk_tree_path_prev (tpSrc = gtk_tree_path_copy (tpDst))) ; for (Nix = 1 ; Nix < icChildren ; Nix++) { if (gtk_tree_selection_path_is_selected (sel, tpSrc)) { // swap the 2 rows swap_model_paths_contents (tm, tpSrc, tpDst) ; gtk_tree_selection_unselect_path (sel, tpSrc) ; gtk_tree_selection_select_path (sel, tpDst) ; } if (!gtk_tree_path_prev (tpSrc)) break ; if (!gtk_tree_path_prev (tpDst)) break ; } }
static gboolean whole_bus_selected_p (GtkTreeSelection *sel, GtkTreeModel *tm, GtkTreePath *tpSelBus) { int Nix ; int icChildren = -1 ; GtkTreePath *tp = NULL ; icChildren = gtk_tree_model_path_n_children (tm, tpSelBus) ; if (icChildren > 0) { gtk_tree_path_down (tp = gtk_tree_path_copy (tpSelBus)) ; for (Nix = 0 ; Nix < icChildren ; Nix++, gtk_tree_path_next (tp)) if (!gtk_tree_selection_path_is_selected (sel, tp)) break ; gtk_tree_path_free (tp) ; return (Nix == icChildren) ; } fprintf (stderr, "What ?! The bus had 0 children ?!\n") ; return TRUE ; }
// 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) ; }