2016-11-27 16:36:11 -06:00
// 26 june 2016
# include "uipriv_unix.h"
2018-06-04 22:46:30 -05:00
# include "table.h"
2018-06-04 22:39:52 -05:00
2018-08-05 17:39:29 -05:00
// TODO with GDK_SCALE set to 2 the 32x32 images are scaled up to 64x64?
2016-11-27 16:36:11 -06:00
struct uiTable {
uiUnixControl c ;
GtkWidget * widget ;
GtkContainer * scontainer ;
GtkScrolledWindow * sw ;
GtkWidget * treeWidget ;
GtkTreeView * tv ;
uiTableModel * model ;
2018-06-05 21:47:11 -05:00
GPtrArray * columnParams ;
2016-11-27 16:36:11 -06:00
int backgroundColumn ;
2018-06-24 17:23:25 -05:00
// keys are struct rowcol, values are gint
// TODO document this properly
GHashTable * indeterminatePositions ;
guint indeterminateTimer ;
2016-11-27 16:36:11 -06:00
} ;
// use the same size as GtkFileChooserWidget's treeview
// TODO refresh when icon theme changes
2018-06-05 21:00:54 -05:00
// TODO doesn't work when scaled?
2016-11-27 16:36:11 -06:00
// TODO is this even necessary?
static void setImageSize ( GtkCellRenderer * r )
{
gint size ;
gint width , height ;
gint xpad , ypad ;
size = 16 ; // fallback used by GtkFileChooserWidget
if ( gtk_icon_size_lookup ( GTK_ICON_SIZE_MENU , & width , & height ) ! = FALSE )
size = MAX ( width , height ) ;
gtk_cell_renderer_get_padding ( r , & xpad , & ypad ) ;
gtk_cell_renderer_set_fixed_size ( r ,
2 * xpad + size ,
2 * ypad + size ) ;
}
2018-06-05 21:00:54 -05:00
static void applyColor ( GtkTreeModel * m , GtkTreeIter * iter , int modelColumn , GtkCellRenderer * r , const char * prop , const char * propSet )
2016-11-27 16:36:11 -06:00
{
GValue value = G_VALUE_INIT ;
GdkRGBA * rgba ;
2018-06-05 21:00:54 -05:00
gtk_tree_model_get_value ( m , iter , modelColumn , & value ) ;
2016-11-27 16:36:11 -06:00
rgba = ( GdkRGBA * ) g_value_get_boxed ( & value ) ;
if ( rgba ! = NULL )
g_object_set ( r , prop , rgba , NULL ) ;
else
g_object_set ( r , propSet , FALSE , NULL ) ;
g_value_unset ( & value ) ;
}
2018-06-05 21:00:54 -05:00
static void setEditable ( uiTableModel * m , GtkTreeIter * iter , int modelColumn , GtkCellRenderer * r , const char * prop )
2016-11-27 16:36:11 -06:00
{
2018-06-24 10:41:19 -05:00
GtkTreePath * path ;
int row ;
2018-06-05 21:00:54 -05:00
gboolean editable ;
2016-11-27 16:36:11 -06:00
2018-06-24 10:41:19 -05:00
// TODO avoid the need for this
path = gtk_tree_model_get_path ( GTK_TREE_MODEL ( m ) , iter ) ;
row = gtk_tree_path_get_indices ( path ) [ 0 ] ;
editable = uiprivTableModelCellEditable ( m , row , modelColumn ) ! = 0 ;
2018-06-07 21:30:43 -05:00
g_object_set ( r , prop , editable , NULL ) ;
2018-06-05 21:00:54 -05:00
}
2016-11-27 16:36:11 -06:00
2018-06-05 21:00:54 -05:00
static void applyBackgroundColor ( uiTable * t , GtkTreeModel * m , GtkTreeIter * iter , GtkCellRenderer * r )
{
if ( t - > backgroundColumn ! = - 1 )
applyColor ( m , iter , t - > backgroundColumn ,
2016-11-27 16:36:11 -06:00
r , " cell-background-rgba " , " cell-background-set " ) ;
}
2018-06-23 19:19:30 -05:00
static void onEdited ( uiTableModel * m , int column , const char * pathstr , const uiTableValue * tvalue , GtkTreeIter * iter )
2016-11-27 16:36:11 -06:00
{
GtkTreePath * path ;
int row ;
path = gtk_tree_path_new_from_string ( pathstr ) ;
row = gtk_tree_path_get_indices ( path ) [ 0 ] ;
2018-06-05 21:00:54 -05:00
if ( iter ! = NULL )
2018-06-07 21:25:17 -05:00
gtk_tree_model_get_iter ( GTK_TREE_MODEL ( m ) , iter , path ) ;
2016-11-27 16:36:11 -06:00
gtk_tree_path_free ( path ) ;
2018-06-23 22:35:42 -05:00
uiprivTableModelSetCellValue ( m , row , column , tvalue ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-05 21:00:54 -05:00
struct textColumnParams {
uiTable * t ;
uiTableModel * m ;
int modelColumn ;
int editableColumn ;
uiTableTextColumnOptionalParams params ;
} ;
static void textColumnDataFunc ( GtkTreeViewColumn * c , GtkCellRenderer * r , GtkTreeModel * m , GtkTreeIter * iter , gpointer data )
{
struct textColumnParams * p = ( struct textColumnParams * ) data ;
GValue value = G_VALUE_INIT ;
const gchar * str ;
gtk_tree_model_get_value ( m , iter , p - > modelColumn , & value ) ;
str = g_value_get_string ( & value ) ;
g_object_set ( r , " text " , str , NULL ) ;
g_value_unset ( & value ) ;
2018-06-07 21:25:17 -05:00
setEditable ( p - > m , iter , p - > editableColumn , r , " editable " ) ;
2018-06-05 21:00:54 -05:00
if ( p - > params . ColorModelColumn ! = - 1 )
applyColor ( m , iter , p - > params . ColorModelColumn ,
r , " foreground-rgba " , " foreground-set " ) ;
applyBackgroundColor ( p - > t , m , iter , r ) ;
}
2018-06-07 21:25:17 -05:00
static void textColumnEdited ( GtkCellRendererText * r , gchar * path , gchar * newText , gpointer data )
2018-06-05 21:00:54 -05:00
{
struct textColumnParams * p = ( struct textColumnParams * ) data ;
2018-06-23 19:19:30 -05:00
uiTableValue * tvalue ;
2018-06-05 21:00:54 -05:00
GtkTreeIter iter ;
2018-06-23 19:19:30 -05:00
tvalue = uiNewTableValueString ( newText ) ;
onEdited ( p - > m , p - > modelColumn , path , tvalue , & iter ) ;
uiFreeTableValue ( tvalue ) ;
2018-06-05 21:00:54 -05:00
// and update the column TODO copy comment here
2018-06-07 21:25:17 -05:00
textColumnDataFunc ( NULL , GTK_CELL_RENDERER ( r ) , GTK_TREE_MODEL ( p - > m ) , & iter , data ) ;
2018-06-05 21:00:54 -05:00
}
struct imageColumnParams {
uiTable * t ;
int modelColumn ;
} ;
static void imageColumnDataFunc ( GtkTreeViewColumn * c , GtkCellRenderer * r , GtkTreeModel * m , GtkTreeIter * iter , gpointer data )
{
struct imageColumnParams * p = ( struct imageColumnParams * ) data ;
GValue value = G_VALUE_INIT ;
uiImage * img ;
//TODO setImageSize(r);
gtk_tree_model_get_value ( m , iter , p - > modelColumn , & value ) ;
img = ( uiImage * ) g_value_get_pointer ( & value ) ;
g_object_set ( r , " surface " ,
uiprivImageAppropriateSurface ( img , p - > t - > treeWidget ) ,
NULL ) ;
g_value_unset ( & value ) ;
applyBackgroundColor ( p - > t , m , iter , r ) ;
}
struct checkboxColumnParams {
uiTable * t ;
uiTableModel * m ;
int modelColumn ;
int editableColumn ;
} ;
static void checkboxColumnDataFunc ( GtkTreeViewColumn * c , GtkCellRenderer * r , GtkTreeModel * m , GtkTreeIter * iter , gpointer data )
{
struct checkboxColumnParams * p = ( struct checkboxColumnParams * ) data ;
GValue value = G_VALUE_INIT ;
gboolean active ;
gtk_tree_model_get_value ( m , iter , p - > modelColumn , & value ) ;
active = g_value_get_int ( & value ) ! = 0 ;
g_object_set ( r , " active " , active , NULL ) ;
g_value_unset ( & value ) ;
2018-06-07 21:25:17 -05:00
setEditable ( p - > m , iter , p - > editableColumn , r , " activatable " ) ;
2018-06-05 21:00:54 -05:00
applyBackgroundColor ( p - > t , m , iter , r ) ;
}
static void checkboxColumnToggled ( GtkCellRendererToggle * r , gchar * pathstr , gpointer data )
{
struct checkboxColumnParams * p = ( struct checkboxColumnParams * ) data ;
GValue value = G_VALUE_INIT ;
int v ;
2018-06-23 19:19:30 -05:00
uiTableValue * tvalue ;
2018-06-07 21:25:17 -05:00
GtkTreePath * path ;
2018-06-05 21:00:54 -05:00
GtkTreeIter iter ;
2018-06-07 21:25:17 -05:00
path = gtk_tree_path_new_from_string ( pathstr ) ;
gtk_tree_model_get_iter ( GTK_TREE_MODEL ( p - > m ) , & iter , path ) ;
gtk_tree_path_free ( path ) ;
gtk_tree_model_get_value ( GTK_TREE_MODEL ( p - > m ) , & iter , p - > modelColumn , & value ) ;
2018-06-05 21:00:54 -05:00
v = g_value_get_int ( & value ) ;
g_value_unset ( & value ) ;
2018-06-23 19:19:30 -05:00
tvalue = uiNewTableValueInt ( ! v ) ;
onEdited ( p - > m , p - > modelColumn , pathstr , tvalue , NULL ) ;
uiFreeTableValue ( tvalue ) ;
2018-06-05 21:00:54 -05:00
// and update the column TODO copy comment here
// TODO avoid fetching the model data twice
2018-06-07 21:25:17 -05:00
checkboxColumnDataFunc ( NULL , GTK_CELL_RENDERER ( r ) , GTK_TREE_MODEL ( p - > m ) , & iter , data ) ;
2018-06-05 21:00:54 -05:00
}
struct progressBarColumnParams {
uiTable * t ;
int modelColumn ;
} ;
2018-06-24 17:23:25 -05:00
struct rowcol {
int row ;
int col ;
} ;
static guint rowcolHash ( gconstpointer key )
{
const struct rowcol * rc = ( const struct rowcol * ) key ;
guint row , col ;
row = ( guint ) ( rc - > row ) ;
col = ( guint ) ( rc - > col ) ;
return row ^ col ;
}
static gboolean rowcolEqual ( gconstpointer a , gconstpointer b )
{
const struct rowcol * ra = ( const struct rowcol * ) a ;
const struct rowcol * rb = ( const struct rowcol * ) b ;
return ( ra - > row = = rb - > row ) & & ( ra - > col = = rb - > col ) ;
}
static void pulseOne ( gpointer key , gpointer value , gpointer data )
{
uiTable * t = uiTable ( data ) ;
struct rowcol * rc = ( struct rowcol * ) key ;
// TODO this is bad: it produces changed handlers for every table because that's how GtkTreeModel works, yet this is per-table because that's how it works
// however, a proper fix would require decoupling progress from normal integers, which we could do...
uiTableModelRowChanged ( t - > model , rc - > row ) ;
}
static gboolean indeterminatePulse ( gpointer data )
{
uiTable * t = uiTable ( data ) ;
g_hash_table_foreach ( t - > indeterminatePositions , pulseOne , t ) ;
return TRUE ;
}
2018-06-07 20:50:38 -05:00
static void progressBarColumnDataFunc ( GtkTreeViewColumn * c , GtkCellRenderer * r , GtkTreeModel * m , GtkTreeIter * iter , gpointer data )
2018-06-05 21:00:54 -05:00
{
struct progressBarColumnParams * p = ( struct progressBarColumnParams * ) data ;
GValue value = G_VALUE_INIT ;
int pval ;
2018-06-24 17:23:25 -05:00
struct rowcol * rc ;
gint * val ;
GtkTreePath * path ;
2018-06-05 21:00:54 -05:00
gtk_tree_model_get_value ( m , iter , p - > modelColumn , & value ) ;
pval = g_value_get_int ( & value ) ;
2018-06-24 17:23:25 -05:00
rc = uiprivNew ( struct rowcol ) ;
// TODO avoid the need for this
path = gtk_tree_model_get_path ( GTK_TREE_MODEL ( m ) , iter ) ;
rc - > row = gtk_tree_path_get_indices ( path ) [ 0 ] ;
rc - > col = p - > modelColumn ;
val = ( gint * ) g_hash_table_lookup ( p - > t - > indeterminatePositions , rc ) ;
2018-06-05 21:00:54 -05:00
if ( pval = = - 1 ) {
2018-06-24 17:23:25 -05:00
if ( val = = NULL ) {
val = uiprivNew ( gint ) ;
* val = 1 ;
g_hash_table_insert ( p - > t - > indeterminatePositions , rc , val ) ;
} else {
uiprivFree ( rc ) ;
( * val ) + + ;
if ( * val = = G_MAXINT )
* val = 1 ;
}
g_object_set ( r ,
" pulse " , * val ,
NULL ) ;
if ( p - > t - > indeterminateTimer = = 0 )
// TODO verify the timeout
p - > t - > indeterminateTimer = g_timeout_add ( 100 , indeterminatePulse , p - > t ) ;
} else {
if ( val ! = NULL ) {
g_hash_table_remove ( p - > t - > indeterminatePositions , rc ) ;
if ( g_hash_table_size ( p - > t - > indeterminatePositions ) = = 0 ) {
g_source_remove ( p - > t - > indeterminateTimer ) ;
p - > t - > indeterminateTimer = 0 ;
}
}
2018-07-08 20:50:16 -05:00
uiprivFree ( rc ) ;
2018-06-05 21:00:54 -05:00
g_object_set ( r ,
" pulse " , - 1 ,
" value " , pval ,
NULL ) ;
2018-06-24 17:23:25 -05:00
}
2018-06-05 21:00:54 -05:00
g_value_unset ( & value ) ;
applyBackgroundColor ( p - > t , m , iter , r ) ;
}
struct buttonColumnParams {
uiTable * t ;
uiTableModel * m ;
int modelColumn ;
int clickableColumn ;
} ;
2018-06-07 20:50:38 -05:00
static void buttonColumnDataFunc ( GtkTreeViewColumn * c , GtkCellRenderer * r , GtkTreeModel * m , GtkTreeIter * iter , gpointer data )
2018-06-05 21:00:54 -05:00
{
struct buttonColumnParams * p = ( struct buttonColumnParams * ) data ;
GValue value = G_VALUE_INIT ;
const gchar * str ;
gtk_tree_model_get_value ( m , iter , p - > modelColumn , & value ) ;
str = g_value_get_string ( & value ) ;
g_object_set ( r , " text " , str , NULL ) ;
g_value_unset ( & value ) ;
2018-06-07 21:25:17 -05:00
setEditable ( p - > m , iter , p - > clickableColumn , r , " sensitive " ) ;
2018-06-05 21:00:54 -05:00
applyBackgroundColor ( p - > t , m , iter , r ) ;
}
2018-06-07 20:50:38 -05:00
// TODO wrong type here
2018-06-07 21:25:17 -05:00
static void buttonColumnClicked ( GtkCellRenderer * r , gchar * pathstr , gpointer data )
2018-06-05 21:00:54 -05:00
{
struct buttonColumnParams * p = ( struct buttonColumnParams * ) data ;
2018-06-07 21:25:17 -05:00
onEdited ( p - > m , p - > modelColumn , pathstr , NULL , NULL ) ;
2018-06-05 21:00:54 -05:00
}
2018-06-07 20:50:38 -05:00
static GtkTreeViewColumn * addColumn ( uiTable * t , const char * name )
{
GtkTreeViewColumn * c ;
c = gtk_tree_view_column_new ( ) ;
gtk_tree_view_column_set_resizable ( c , TRUE ) ;
gtk_tree_view_column_set_title ( c , name ) ;
gtk_tree_view_append_column ( t - > tv , c ) ;
return c ;
}
2018-06-24 08:52:01 -05:00
static void addTextColumn ( uiTable * t , GtkTreeViewColumn * c , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * textParams )
2016-11-27 16:36:11 -06:00
{
2018-06-05 21:47:11 -05:00
struct textColumnParams * p ;
2016-11-27 16:36:11 -06:00
GtkCellRenderer * r ;
2018-06-05 21:47:11 -05:00
p = uiprivNew ( struct textColumnParams ) ;
p - > t = t ;
2018-06-07 21:25:17 -05:00
// TODO get rid of these fields AND rename t->model in favor of t->m
p - > m = t - > model ;
2018-06-05 21:47:11 -05:00
p - > modelColumn = textModelColumn ;
p - > editableColumn = textEditableModelColumn ;
2018-06-24 08:52:01 -05:00
if ( textParams ! = NULL )
p - > params = * textParams ;
2018-06-05 21:47:11 -05:00
else
2018-06-23 23:45:54 -05:00
p - > params = uiprivDefaultTextColumnOptionalParams ;
2016-11-27 16:36:11 -06:00
r = gtk_cell_renderer_text_new ( ) ;
2018-06-05 21:47:11 -05:00
gtk_tree_view_column_pack_start ( c , r , TRUE ) ;
gtk_tree_view_column_set_cell_data_func ( c , r , textColumnDataFunc , p , NULL ) ;
g_signal_connect ( r , " edited " , G_CALLBACK ( textColumnEdited ) , p ) ;
2018-06-07 21:25:17 -05:00
g_ptr_array_add ( t - > columnParams , p ) ;
2018-06-05 21:47:11 -05:00
}
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
// TODO rename modelCOlumn and params everywhere
2018-06-24 08:52:01 -05:00
void uiTableAppendTextColumn ( uiTable * t , const char * name , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * textParams )
2018-06-05 21:47:11 -05:00
{
GtkTreeViewColumn * c ;
2018-06-07 20:50:38 -05:00
c = addColumn ( t , name ) ;
2018-06-24 08:52:01 -05:00
addTextColumn ( t , c , textModelColumn , textEditableModelColumn , textParams ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-07 20:50:38 -05:00
static void addImageColumn ( uiTable * t , GtkTreeViewColumn * c , int imageModelColumn )
2016-11-27 16:36:11 -06:00
{
2018-06-07 20:50:38 -05:00
struct imageColumnParams * p ;
GtkCellRenderer * r ;
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
p = uiprivNew ( struct imageColumnParams ) ;
p - > t = t ;
p - > modelColumn = imageModelColumn ;
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
r = gtk_cell_renderer_pixbuf_new ( ) ;
gtk_tree_view_column_pack_start ( c , r , FALSE ) ;
gtk_tree_view_column_set_cell_data_func ( c , r , imageColumnDataFunc , p , NULL ) ;
2018-06-07 21:25:17 -05:00
g_ptr_array_add ( t - > columnParams , p ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-07 20:50:38 -05:00
void uiTableAppendImageColumn ( uiTable * t , const char * name , int imageModelColumn )
2016-11-27 16:36:11 -06:00
{
2018-06-07 20:50:38 -05:00
GtkTreeViewColumn * c ;
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
c = addColumn ( t , name ) ;
addImageColumn ( t , c , imageModelColumn ) ;
}
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
void uiTableAppendImageTextColumn ( uiTable * t , const char * name , int imageModelColumn , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * textParams )
{
GtkTreeViewColumn * c ;
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
c = addColumn ( t , name ) ;
addImageColumn ( t , c , imageModelColumn ) ;
addTextColumn ( t , c , textModelColumn , textEditableModelColumn , textParams ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-07 21:25:17 -05:00
static void addCheckboxColumn ( uiTable * t , GtkTreeViewColumn * c , int checkboxModelColumn , int checkboxEditableModelColumn )
2016-11-27 16:36:11 -06:00
{
2018-06-07 20:50:38 -05:00
struct checkboxColumnParams * p ;
2016-11-27 16:36:11 -06:00
GtkCellRenderer * r ;
2018-06-07 20:50:38 -05:00
p = uiprivNew ( struct checkboxColumnParams ) ;
p - > t = t ;
2018-06-07 21:25:17 -05:00
p - > m = t - > model ;
2018-06-07 20:50:38 -05:00
p - > modelColumn = checkboxModelColumn ;
p - > editableColumn = checkboxEditableModelColumn ;
2016-11-27 16:36:11 -06:00
r = gtk_cell_renderer_toggle_new ( ) ;
2018-06-07 20:50:38 -05:00
gtk_tree_view_column_pack_start ( c , r , FALSE ) ;
gtk_tree_view_column_set_cell_data_func ( c , r , checkboxColumnDataFunc , p , NULL ) ;
2018-06-07 21:25:17 -05:00
g_signal_connect ( r , " toggled " , G_CALLBACK ( checkboxColumnToggled ) , p ) ;
g_ptr_array_add ( t - > columnParams , p ) ;
2018-06-07 20:50:38 -05:00
}
void uiTableAppendCheckboxColumn ( uiTable * t , const char * name , int checkboxModelColumn , int checkboxEditableModelColumn )
{
GtkTreeViewColumn * c ;
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
c = addColumn ( t , name ) ;
addCheckboxColumn ( t , c , checkboxModelColumn , checkboxEditableModelColumn ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-07 20:50:38 -05:00
void uiTableAppendCheckboxTextColumn ( uiTable * t , const char * name , int checkboxModelColumn , int checkboxEditableModelColumn , int textModelColumn , int textEditableModelColumn , uiTableTextColumnOptionalParams * textParams )
2016-11-27 16:36:11 -06:00
{
2018-06-07 20:50:38 -05:00
GtkTreeViewColumn * c ;
c = addColumn ( t , name ) ;
addCheckboxColumn ( t , c , checkboxModelColumn , checkboxEditableModelColumn ) ;
addTextColumn ( t , c , textModelColumn , textEditableModelColumn , textParams ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-07 20:50:38 -05:00
void uiTableAppendProgressBarColumn ( uiTable * t , const char * name , int progressModelColumn )
2016-11-27 16:36:11 -06:00
{
2018-06-07 20:50:38 -05:00
GtkTreeViewColumn * c ;
struct progressBarColumnParams * p ;
GtkCellRenderer * r ;
c = addColumn ( t , name ) ;
p = uiprivNew ( struct progressBarColumnParams ) ;
p - > t = t ;
// TODO make progress and progressBar consistent everywhere
p - > modelColumn = progressModelColumn ;
r = gtk_cell_renderer_progress_new ( ) ;
gtk_tree_view_column_pack_start ( c , r , TRUE ) ;
gtk_tree_view_column_set_cell_data_func ( c , r , progressBarColumnDataFunc , p , NULL ) ;
2018-06-07 21:25:17 -05:00
g_ptr_array_add ( t - > columnParams , p ) ;
2016-11-27 16:36:11 -06:00
}
2018-06-24 08:52:01 -05:00
void uiTableAppendButtonColumn ( uiTable * t , const char * name , int buttonModelColumn , int buttonClickableModelColumn )
2016-11-27 16:36:11 -06:00
{
2018-06-07 20:50:38 -05:00
GtkTreeViewColumn * c ;
struct buttonColumnParams * p ;
GtkCellRenderer * r ;
2016-11-27 16:36:11 -06:00
2018-06-07 20:50:38 -05:00
c = addColumn ( t , name ) ;
p = uiprivNew ( struct buttonColumnParams ) ;
p - > t = t ;
2018-06-07 21:25:17 -05:00
p - > m = t - > model ;
2018-06-24 08:52:01 -05:00
p - > modelColumn = buttonModelColumn ;
2018-06-07 20:50:38 -05:00
p - > clickableColumn = buttonClickableModelColumn ;
r = uiprivNewCellRendererButton ( ) ;
gtk_tree_view_column_pack_start ( c , r , TRUE ) ;
gtk_tree_view_column_set_cell_data_func ( c , r , buttonColumnDataFunc , p , NULL ) ;
g_signal_connect ( r , " clicked " , G_CALLBACK ( buttonColumnClicked ) , p ) ;
2018-06-07 21:25:17 -05:00
g_ptr_array_add ( t - > columnParams , p ) ;
2016-11-27 16:36:11 -06:00
}
uiUnixControlAllDefaultsExceptDestroy ( uiTable )
static void uiTableDestroy ( uiControl * c )
{
uiTable * t = uiTable ( c ) ;
2018-07-08 20:50:16 -05:00
guint i ;
for ( i = 0 ; i < t - > columnParams - > len ; i + + )
uiprivFree ( g_ptr_array_index ( t - > columnParams , i ) ) ;
g_ptr_array_free ( t - > columnParams , TRUE ) ;
if ( g_hash_table_size ( t - > indeterminatePositions ) ! = 0 )
g_source_remove ( t - > indeterminateTimer ) ;
g_hash_table_destroy ( t - > indeterminatePositions ) ;
2016-11-27 16:36:11 -06:00
g_object_unref ( t - > widget ) ;
uiFreeControl ( uiControl ( t ) ) ;
}
2018-06-24 09:28:41 -05:00
uiTable * uiNewTable ( uiTableParams * p )
2016-11-27 16:36:11 -06:00
{
uiTable * t ;
uiUnixNewControl ( uiTable , t ) ;
2018-06-24 09:28:41 -05:00
t - > model = p - > Model ;
2018-06-07 21:25:17 -05:00
t - > columnParams = g_ptr_array_new ( ) ;
2018-06-24 09:28:41 -05:00
t - > backgroundColumn = p - > RowBackgroundColorModelColumn ;
2016-11-27 16:36:11 -06:00
t - > widget = gtk_scrolled_window_new ( NULL , NULL ) ;
t - > scontainer = GTK_CONTAINER ( t - > widget ) ;
t - > sw = GTK_SCROLLED_WINDOW ( t - > widget ) ;
gtk_scrolled_window_set_shadow_type ( t - > sw , GTK_SHADOW_IN ) ;
t - > treeWidget = gtk_tree_view_new_with_model ( GTK_TREE_MODEL ( t - > model ) ) ;
t - > tv = GTK_TREE_VIEW ( t - > treeWidget ) ;
// TODO set up t->tv
gtk_container_add ( t - > scontainer , t - > treeWidget ) ;
// and make the tree view visible; only the scrolled window's visibility is controlled by libui
gtk_widget_show ( t - > treeWidget ) ;
2018-06-24 17:23:25 -05:00
t - > indeterminatePositions = g_hash_table_new_full ( rowcolHash , rowcolEqual ,
uiprivFree , uiprivFree ) ;
2016-11-27 16:36:11 -06:00
return t ;
}