Exemplo n.º 1
0
static void
gnc_table_move_cursor_internal (Table *table,
                                VirtualLocation new_virt_loc,
                                gboolean do_move_gui)
{
    int cell_row, cell_col;
    VirtualLocation virt_loc;
    VirtualCell *vcell;
    CellBlock *curs;

    ENTER("new_virt=(%d %d) do_move_gui=%d\n",
          new_virt_loc.vcell_loc.virt_row,
          new_virt_loc.vcell_loc.virt_col, do_move_gui);

    /* call the callback, allowing the app to commit any changes
     * associated with the current location of the cursor. Note that
     * this callback may recursively call this routine. */
    if (table->control->move_cursor && table->control->allow_move)
    {
        table->control->move_cursor (&new_virt_loc, table->control->user_data);

        /* The above callback can cause this routine to be called
         * recursively. As a result of this recursion, the cursor may
         * have gotten repositioned. We need to make sure we make
         * passive again. */
        if (do_move_gui)
            gnc_table_refresh_current_cursor_gui (table, FALSE);
    }

    /* invalidate the cursor for now; we'll fix it back up below */
    gnc_virtual_location_init (&table->current_cursor_loc);

    curs = table->current_cursor;
    table->current_cursor = NULL;

    /* check for out-of-bounds conditions (which may be deliberate) */
    if ((new_virt_loc.vcell_loc.virt_row < 0) ||
            (new_virt_loc.vcell_loc.virt_col < 0))
    {
        /* if the location is invalid, then we should take this
         * as a command to unmap the cursor gui. */
        if (do_move_gui && curs)
        {
            for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
                for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
                {
                    BasicCell *cell;

                    cell = gnc_cellblock_get_cell (curs, cell_row, cell_col);
                    if (cell)
                    {
                        cell->changed = FALSE;
                        cell->conditionally_changed = FALSE;

                        if (cell->gui_move)
                            cell->gui_move (cell);
                    }
                }
        }

        LEAVE("out of bounds\n");
        return;
    }

    if (!gnc_table_virtual_loc_valid (table, new_virt_loc, TRUE))
    {
        PWARN("bad table location");
        LEAVE("");
        return;
    }

    /* ok, we now have a valid position. Find the new cursor to use,
     * and initialize its cells */
    vcell = gnc_table_get_virtual_cell (table, new_virt_loc.vcell_loc);
    curs = vcell->cellblock;
    table->current_cursor = curs;

    /* record the new position */
    table->current_cursor_loc = new_virt_loc;

    virt_loc.vcell_loc = new_virt_loc.vcell_loc;

    /* update the cell values to reflect the new position */
    for (cell_row = 0; cell_row < curs->num_rows; cell_row++)
        for (cell_col = 0; cell_col < curs->num_cols; cell_col++)
        {
            BasicCell *cell;
            CellIOFlags io_flags;

            virt_loc.phys_row_offset = cell_row;
            virt_loc.phys_col_offset = cell_col;

            cell = gnc_cellblock_get_cell(curs, cell_row, cell_col);
            if (cell)
            {
                /* if a cell has a GUI, move that first, before setting
                 * the cell value.  Otherwise, we'll end up putting the
                 * new values in the old cell locations, and that would
                 * lead to confusion of all sorts. */
                if (do_move_gui && cell->gui_move)
                    cell->gui_move (cell);

                /* OK, now copy the string value from the table at large
                 * into the cell handler. */
                io_flags = gnc_table_get_io_flags (table, virt_loc);
                if (io_flags & XACC_CELL_ALLOW_SHADOW)
                {
                    const char *entry;
                    gboolean conditionally_changed = FALSE;

                    entry = gnc_table_get_entry_internal (table, virt_loc,
                                                          &conditionally_changed);

                    gnc_basic_cell_set_value (cell, entry);

                    cell->changed = FALSE;
                    cell->conditionally_changed = conditionally_changed;
                }
            }
        }

    LEAVE("did move\n");
}
Exemplo n.º 2
0
/* Returned result should not be touched by the caller.
 * NULL return value means the edit was rejected. */
const char *
gnc_table_modify_update (Table *table,
                         VirtualLocation virt_loc,
                         const char *change,
                         int change_len,
                         const char *newval,
                         int newval_len,
                         int *cursor_position,
                         int *start_selection,
                         int *end_selection,
                         gboolean *cancelled)
{
    gboolean changed = FALSE;
    CellModifyVerifyFunc mv;
    BasicCell *cell;
    CellBlock *cb;
    int cell_row;
    int cell_col;
    char * old_value;

    g_return_val_if_fail (table, NULL);
    g_return_val_if_fail (table->model, NULL);

    if (gnc_table_model_read_only (table->model))
    {
        PWARN ("change to read-only table");
        return NULL;
    }

    cb = table->current_cursor;

    cell_row = virt_loc.phys_row_offset;
    cell_col = virt_loc.phys_col_offset;

    ENTER ("");

    if (!gnc_table_confirm_change (table, virt_loc))
    {
        if (cancelled)
            *cancelled = TRUE;

        LEAVE("change cancelled");
        return NULL;
    }

    if (cancelled)
        *cancelled = FALSE;

    /* OK, if there is a callback for this cell, call it */
    cell = gnc_cellblock_get_cell (cb, cell_row, cell_col);
    if (!cell)
    {
        LEAVE("no cell");
        return NULL;
    }

    mv = cell->modify_verify;

    old_value = g_strdup (cell->value);

    if (mv)
    {
        mv (cell, change, change_len, newval, newval_len,
            cursor_position, start_selection, end_selection);
    }
    else
    {
        gnc_basic_cell_set_value (cell, newval);
    }

    if (g_strcmp0 (old_value, cell->value) != 0)
    {
        changed = TRUE;
        cell->changed = TRUE;
    }

    g_free (old_value);

    if (table->gui_handlers.redraw_help)
        table->gui_handlers.redraw_help (table);

    LEAVE ("change %d %d (relrow=%d relcol=%d) val=%s\n",
           virt_loc.vcell_loc.virt_row,
           virt_loc.vcell_loc.virt_col,
           cell_row, cell_col,
           cell->value ? cell->value : "(null)");

    if (changed)
        return cell->value;
    else
        return NULL;
}
Exemplo n.º 3
0
gboolean
gnc_table_direct_update (Table *table,
                         VirtualLocation virt_loc,
                         char **newval_ptr,
                         int *cursor_position,
                         int *start_selection,
                         int *end_selection,
                         gpointer gui_data)
{
    gboolean result;
    BasicCell *cell;
    CellBlock *cb;
    int cell_row;
    int cell_col;
    char * old_value;

    g_return_val_if_fail (table, FALSE);
    g_return_val_if_fail (table->model, FALSE);

    if (gnc_table_model_read_only (table->model))
    {
        PWARN ("input to read-only table");
        return FALSE;
    }

    cb = table->current_cursor;

    cell_row = virt_loc.phys_row_offset;
    cell_col = virt_loc.phys_col_offset;

    cell = gnc_cellblock_get_cell (cb, cell_row, cell_col);
    if (!cell)
        return FALSE;

    ENTER ("");

    if (cell->direct_update == NULL)
    {
        LEAVE("no direct update");
        return FALSE;
    }

    old_value = g_strdup (cell->value);

    result = cell->direct_update (cell, cursor_position, start_selection,
                                  end_selection, gui_data);

    if (g_strcmp0 (old_value, cell->value) != 0)
    {
        if (!gnc_table_confirm_change (table, virt_loc))
        {
            gnc_basic_cell_set_value (cell, old_value);
            *newval_ptr = NULL;
            result = TRUE;
        }
        else
        {
            cell->changed = TRUE;
            *newval_ptr = cell->value;
        }
    }
    else
        *newval_ptr = NULL;

    g_free (old_value);

    if (table->gui_handlers.redraw_help)
        table->gui_handlers.redraw_help (table);

    LEAVE("");
    return result;
}
Exemplo n.º 4
0
static void
gnc_date_cell_modify_verify (BasicCell *_cell,
                             const char *change,
                             int change_len,
                             const char *newval,
                             int newval_len,
                             int *cursor_position,
                             int *start_selection,
                             int *end_selection)
{
    DateCell *cell = (DateCell *) _cell;
    PopBox *box = cell->cell.gui_private;
    gboolean accept = FALSE;

    if (box->in_date_select)
    {
        gnc_basic_cell_set_value (_cell, newval);
        return;
    }

    /* if user hit backspace, accept the change */
    if (change == NULL)
        accept = TRUE;
    else if (change_len == 0)
        accept = TRUE;
    else
    {
        int count = 0;
        unsigned char separator = dateSeparator ();
        gboolean ok = TRUE;
        const gchar *c;
        gunichar uc;

        /* accept only numbers or a date separator. Note that the
         * separator of '-' (for DATE_FORMAT_ISO) takes precedence
         * over the accelerator below! */
        c = change;
        while (*c)
        {
            uc = g_utf8_get_char (c);

            if (!g_unichar_isdigit (uc) && (separator != uc))
                ok = FALSE;

            if (separator == uc)
                count++;

            c = g_utf8_next_char (c);
        }

        c = _cell->value;
        while (*c)
        {
            uc = g_utf8_get_char (c);

            if (separator == uc)
                count++;

            c = g_utf8_next_char (c);
        }

        if (2 < count)
            ok = FALSE;

        if (ok)
            accept = TRUE;
    }

    /* keep a copy of the new value */
    if (accept)
    {

        gnc_basic_cell_set_value_internal (&cell->cell, newval);
        gnc_parse_date (&(box->date), newval);

        if (!box->date_picker)
            return;

        block_picker_signals (cell);
        gnc_date_picker_set_date (box->date_picker,
                                  box->date.tm_mday,
                                  box->date.tm_mon,
                                  box->date.tm_year + 1900);
        unblock_picker_signals (cell);
    }
}