Add a new cell type for Transaction associations that

supports the use of glyphs
This commit is contained in:
Robert Fewell 2020-05-18 16:07:28 +01:00
parent 260c7b32dc
commit 785a6a8fa6
8 changed files with 450 additions and 1 deletions

View File

@ -1,4 +1,5 @@
set (register_core_SOURCES
assoccell.c
basiccell.c
cell-factory.c
cellblock.c
@ -18,6 +19,7 @@ set (register_core_SOURCES
set (register_core_HEADERS
assoccell.h
basiccell.h
cell-factory.h
cellblock.h

View File

@ -0,0 +1,289 @@
/********************************************************************\
* assoccell.c -- association checkbox cell *
* *
* 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, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
\********************************************************************/
/*
* FILE:
* assoccell.c
*
* FUNCTION:
* Implements a mouse-click cell that allows a series
* of values to be clicked through and return a glyth if
* font allows it.
*
* HISTORY:
* Copyright (c) 1998 Linas Vepstas
* Copyright (c) 2000 Dave Peticolas
* Copyright (c) 2001 Derek Atkins
* Copyright (c) 2020 Robert Fewell
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "basiccell.h"
#include "gnc-engine.h"
#include "assoccell.h"
#include "gnc-ui-util.h"
static void gnc_assoc_cell_set_value (BasicCell *_cell, const char *value);
const char *
gnc_assoc_get_glyph_from_flag (char association_flag)
{
switch (association_flag)
{
case WASSOC:
return GLYPH_LINK;
case FASSOC:
return GLYPH_PAPERCLIP;
default:
return " ";
}
}
static const char
gnc_assoc_get_flag_from_glyph (const char *glyph)
{
if (strcmp (glyph, GLYPH_LINK) == 0)
return WASSOC;
else if (strcmp (glyph, GLYPH_PAPERCLIP) == 0)
return FASSOC;
else
return ' ';
}
gboolean
gnc_assoc_get_use_glyphs (AssocCell *cell)
{
return cell->use_glyphs;
}
static const char *
gnc_assoc_cell_get_string (AssocCell *cell, char flag)
{
static char str[2] = { 0, 0 };
if (cell->use_glyphs)
return gnc_assoc_get_glyph_from_flag (flag);
if (cell->get_string != NULL)
return (cell->get_string)(flag);
str[0] = flag;
return str;
}
static gboolean
gnc_assoc_cell_enter (BasicCell *_cell,
int *cursor_position,
int *start_selection,
int *end_selection)
{
AssocCell *cell = (AssocCell *) _cell;
char * this_flag;
if (cell->confirm_cb &&
! (cell->confirm_cb (cell->flag, cell->confirm_data)))
return FALSE;
if (cell->read_only == TRUE)
return FALSE;
/* Find the current flag in the list of flags */
this_flag = strchr (cell->flag_order, cell->flag);
if (this_flag == NULL || *this_flag == '\0')
{
/* If it's not there (or the list is empty) use default_flag */
cell->flag = cell->default_flag;
}
else
{
/* It is in the list -- choose the -next- item in the list (wrapping
* around as necessary).
*/
this_flag++;
if (*this_flag != '\0')
cell->flag = *this_flag;
else
cell->flag = *(cell->flag_order);
}
/* And set the display */
gnc_assoc_cell_set_flag (cell, cell->flag);
return FALSE;
}
static void
gnc_assoc_cell_init (AssocCell *cell)
{
gnc_basic_cell_init (&cell->cell);
gnc_assoc_cell_set_flag (cell, '\0');
cell->confirm_cb = NULL;
cell->get_string = NULL;
cell->valid_flags = "";
cell->flag_order = "";
cell->read_only = FALSE;
cell->use_glyphs = FALSE;
cell->cell.enter_cell = gnc_assoc_cell_enter;
cell->cell.set_value = gnc_assoc_cell_set_value;
}
BasicCell *
gnc_assoc_cell_new (void)
{
AssocCell * cell;
cell = g_new0 (AssocCell, 1);
gnc_assoc_cell_init (cell);
return &cell->cell;
}
/* assumes we are given the untranslated form */
static void
gnc_assoc_cell_set_value (BasicCell *_cell, const char *value)
{
AssocCell *cell = (AssocCell *) _cell;
char flag;
if (!value || *value == '\0')
{
cell->flag = cell->default_flag;
gnc_basic_cell_set_value_internal (_cell, "");
return;
}
if (cell->use_glyphs)
flag = gnc_assoc_get_flag_from_glyph (value);
else
{
flag = cell->default_flag;
if (strchr (cell->valid_flags, *value) != NULL)
flag = *value;
}
gnc_assoc_cell_set_flag (cell, flag);
}
void
gnc_assoc_cell_set_flag (AssocCell *cell, char flag)
{
const char *string;
g_return_if_fail (cell != NULL);
cell->flag = flag;
string = gnc_assoc_cell_get_string (cell, flag);
gnc_basic_cell_set_value_internal (&cell->cell, string);
}
char
gnc_assoc_cell_get_flag (AssocCell *cell)
{
g_return_val_if_fail (cell != NULL, '\0');
return cell->flag;
}
void
gnc_assoc_cell_set_string_getter (AssocCell *cell,
AssocCellStringGetter get_string)
{
g_return_if_fail (cell != NULL);
cell->get_string = get_string;
}
void
gnc_assoc_cell_set_confirm_cb (AssocCell *cell, AssocCellConfirm confirm_cb,
gpointer data)
{
g_return_if_fail (cell != NULL);
cell->confirm_cb = confirm_cb;
cell->confirm_data = data;
}
void
gnc_assoc_cell_set_valid_flags (AssocCell *cell, const char *flags,
char default_flag)
{
g_return_if_fail (cell != NULL);
g_return_if_fail (flags != NULL);
cell->valid_flags = (char *)flags;
cell->default_flag = default_flag;
}
void
gnc_assoc_cell_set_flag_order (AssocCell *cell, const char *flags)
{
g_return_if_fail (cell != NULL);
g_return_if_fail (flags != NULL);
cell->flag_order = (char *)flags;
}
void
gnc_assoc_cell_set_read_only (AssocCell *cell, gboolean read_only)
{
g_return_if_fail (cell != NULL);
cell->read_only = read_only;
}
void
gnc_assoc_cell_set_use_glyphs (AssocCell *cell)
{
gboolean use_glyphs = TRUE;
gchar *test_text;
GtkWidget *label;
PangoLayout *test_layout;
gint count;
g_return_if_fail (cell != NULL);
label = gtk_label_new (NULL);
test_text = g_strconcat (GLYPH_LINK, ",", GLYPH_PAPERCLIP, NULL);
test_layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), test_text);
pango_layout_set_text (test_layout, test_text, strlen (test_text));
count = pango_layout_get_unknown_glyphs_count (test_layout);
if (count != 0)
use_glyphs = FALSE;
g_object_unref (test_layout);
g_free (test_text);
cell->use_glyphs = use_glyphs;
}

View File

@ -0,0 +1,100 @@
/********************************************************************\
* assoccell.h -- association checkbox cell *
* *
* 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, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
\********************************************************************/
/** @addtogroup Cell Cell
* @{
* @file assoccell.h
* @struct AssocCell
* @brief The AssocCell object implements a cell handler
* that will cycle through a series of single-character
* values when clicked upon by the mouse and will return a glyph
* if font can show it.
*/
/* HISTORY:
* Copyright (c) 1998 Linas Vepstas
* Copyright (c) 2000 Dave Peticolas
* Copyright (c) 2001 Derek Atkins
* Copyright (c) 2020 Robert Fewell
*/
#ifndef ASSOC_CELL_H
#define ASSOC_CELL_H
#include <glib.h>
#include "basiccell.h"
#define GLYPH_PAPERCLIP "\360\237\223\216" // Codepoint U+1F4CE
#define GLYPH_LINK "\360\237\224\227" // Codepoint U+1F517
typedef const char * (*AssocCellStringGetter) (char flag);
typedef gboolean (*AssocCellConfirm) (char old_flag, gpointer data);
typedef struct
{
BasicCell cell;
char flag; /** The actual flag value */
char * valid_flags; /** The list of valid flags */
char * flag_order; /** Automatic flag selection order */
char default_flag; /** Default flag for unknown user input */
AssocCellStringGetter get_string;
AssocCellConfirm confirm_cb;
gpointer confirm_data;
gboolean read_only;
gboolean use_glyphs;
} AssocCell;
BasicCell * gnc_assoc_cell_new (void);
void gnc_assoc_cell_set_flag (AssocCell *cell, char flag);
char gnc_assoc_cell_get_flag (AssocCell *cell);
void gnc_assoc_cell_set_confirm_cb (AssocCell *cell,
AssocCellConfirm confirm_cb,
gpointer data);
void gnc_assoc_cell_set_string_getter (AssocCell *cell,
AssocCellStringGetter getter);
/** note that @param flags is copied into the RecnCell directly, but
* remains the "property" of the caller. The caller must maintain the
* chars pointer, and the caller must setup a mechanism to 'free' the
* chars pointer. The rationale is that you may have many AssocCell
* objects that use the same set of flags.
*/
void gnc_assoc_cell_set_valid_flags (AssocCell *cell, const char *flags,
char default_flag);
void gnc_assoc_cell_set_flag_order (AssocCell *cell, const char *flags);
void gnc_assoc_cell_set_read_only (AssocCell *cell, gboolean read_only);
void gnc_assoc_cell_set_use_glyphs (AssocCell *cell);
gboolean gnc_assoc_get_use_glyphs (AssocCell *cell);
const char * gnc_assoc_get_glyph_from_flag (char association_flag);
/** @} */
#endif

View File

@ -23,6 +23,7 @@
#include <config.h>
#include "assoccell.h"
#include "basiccell.h"
#include "cell-factory.h"
#include "combocell.h"
@ -57,6 +58,8 @@ gnc_register_init (void)
gnc_register_add_cell_type (RECN_CELL_TYPE_NAME, gnc_recn_cell_new);
gnc_register_add_cell_type (ASSOC_CELL_TYPE_NAME, gnc_assoc_cell_new);
gnc_register_add_cell_type (QUICKFILL_CELL_TYPE_NAME,
gnc_quickfill_cell_new);

View File

@ -67,6 +67,7 @@
#define NUM_CELL_TYPE_NAME "num-cell"
#define PRICE_CELL_TYPE_NAME "price-cell"
#define RECN_CELL_TYPE_NAME "recn-cell"
#define ASSOC_CELL_TYPE_NAME "assoc-cell"
#define QUICKFILL_CELL_TYPE_NAME "quickfill-cell"
#define FORMULA_CELL_TYPE_NAME "formula-cell"
#define CHECKBOX_CELL_TYPE_NAME "checkbox-cell"

View File

@ -902,6 +902,36 @@ gnc_get_reconcile_flag_order (void)
return flags;
}
const char *
gnc_get_association_str (char association_flag)
{
switch (association_flag)
{
case WASSOC:
return C_("Association flag for 'web'", "w");
case FASSOC:
return C_("Association flag for 'file'", "f");
case ' ':
return " ";
default:
PERR("Bad association flag");
return NULL;
}
}
const char *
gnc_get_association_valid_flags (void)
{
static const char flags[] = { FASSOC, WASSOC, ' ', 0 };
return flags;
}
const char *
gnc_get_association_flag_order (void)
{
static const char flags[] = { FASSOC, WASSOC, ' ', 0 };
return flags;
}
static const char *
equity_base_name (GNCEquityType equity_type)
@ -1522,7 +1552,7 @@ PrintAmountInternal(char *buf, gnc_numeric val, const GNCPrintAmountInfo *info)
}
min_dp = info->min_decimal_places;
max_dp = info->max_decimal_places;
/* Don to limit the number of decimal places _UNLESS_ force_fit is
* true. */
if (!info->force_fit)

View File

@ -189,6 +189,29 @@ const char * gnc_get_reconcile_str (char reconciled_flag);
const char * gnc_get_reconcile_valid_flags (void);
const char * gnc_get_reconcile_flag_order (void);
#define WASSOC 'w'
#define FASSOC 'f'
/** Get a string containing association valid flags
*
* @return a string containing the list of associated flags
*/
const char *gnc_get_association_valid_flags (void);
/** Get a string containing association flag order
*
* @return a string containing the association flag change order
*/
const char *gnc_get_association_flag_order (void);
/** Get a string representing the association type
*
* @param association_flag The flag to convert into a string
*
* @return the i18n'd association string
*/
const char *gnc_get_association_str (char association_flag);
typedef enum
{
EQUITY_OPENING_BALANCE,

View File

@ -396,6 +396,7 @@ gnucash/register/ledger-core/split-register-load.c
gnucash/register/ledger-core/split-register-model.c
gnucash/register/ledger-core/split-register-model-save.c
gnucash/register/ledger-core/split-register-util.c
gnucash/register/register-core/assoccell.c
gnucash/register/register-core/basiccell.c
gnucash/register/register-core/cellblock.c
gnucash/register/register-core/cell-factory.c