libyui-mga-gtk  1.1.0
YMGA_GCBTable.cc
1 /*
2  Copyright 2013 by Angelo Naselli <anaselli at linux dot it>
3 
4  This library is free software; you can redistribute it and/or modify
5  it under the terms of the GNU Lesser General Public License as
6  published by the Free Software Foundation; either version 2.1 of the
7  License, or (at your option) version 3.0 of the License. This library
8  is distributed in the hope that it will be useful, but WITHOUT ANY
9  WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11  License for more details. You should have received a copy of the GNU
12  Lesser General Public License along with this library; if not, write
13  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
14  Floor, Boston, MA 02110-1301 USA
15 */
16 
17 
18 /*-/
19 
20  File: YMGA_GCBTable.cc
21 
22  Author: Angelo Naselli <anaselli@linux.it>
23 
24 /-*/
25 
26 #include <yui/gtk/YGi18n.h>
27 
28 #define YUILogComponent "mga-gtk-ui"
29 
30 #include <yui/YUILog.h>
31 #include <yui/gtk/YGUI.h>
32 #include <yui/gtk/YGUtils.h>
33 #include <yui/gtk/YGWidget.h>
34 #include <YSelectionWidget.h>
35 #include <yui/gtk/YGSelectionStore.h>
36 #include <yui/gtk/ygtktreeview.h>
37 #include <string.h>
38 #include <yui/mga/YMGA_CBTable.h>
39 #include <YTable.h>
40 
41 #include <yui/gtk/YGDialog.h>
42 #include <gdk/gdkkeysyms.h>
43 
44 #include "YMGA_GCBTable.h"
45 
46 //**** YMGA_GTreeView implementation
47 
48 YMGA_GTreeView::YMGA_GTreeView (YWidget *ywidget, YWidget *parent, const std::string &label, bool tree)
49  : YGScrolledWidget (ywidget, parent, label, YD_VERT, YGTK_TYPE_TREE_VIEW, NULL),
50  YGSelectionStore (tree)
51 {
52  gtk_tree_view_set_headers_visible (getView(), FALSE);
53 
54  /* Yast tools expect the user to be unable to un-select the row. They
55  generally don't check to see if the returned value is -1. So, just
56  disallow un-selection. */
57  gtk_tree_selection_set_mode (getSelection(), GTK_SELECTION_BROWSE);
58 
59  connect (getSelection(), "changed", G_CALLBACK (selection_changed_cb), this);
60  connect (getWidget(), "row-activated", G_CALLBACK (activated_cb), this);
61  connect (getWidget(), "right-click", G_CALLBACK (right_click_cb), this);
62 
63  m_blockTimeout = 0; // GtkTreeSelection idiotically fires when showing widget
64  markColumn = -1;
65  m_count = NULL;
66  blockSelected();
67  g_signal_connect (getWidget(), "map", G_CALLBACK (block_init_cb), this);
68 }
69 
70 YMGA_GTreeView::~YMGA_GTreeView()
71 {
72  if (m_blockTimeout) g_source_remove (m_blockTimeout);
73 }
74 
75 void YMGA_GTreeView::addTextColumn (int iconCol, int textCol)
76 {
77  addTextColumn ("", YAlignUnchanged, iconCol, textCol);
78 }
79 
80 void YMGA_GTreeView::addTextColumn (const std::string &header, YAlignmentType align, int icon_col, int text_col)
81 {
82  gfloat xalign = -1;
83  switch (align) {
84  case YAlignBegin:
85  xalign = 0.0;
86  break;
87  case YAlignCenter:
88  xalign = 0.5;
89  break;
90  case YAlignEnd:
91  xalign = 1.0;
92  break;
93  case YAlignUnchanged:
94  break;
95  }
96 
97  GtkTreeViewColumn *column = gtk_tree_view_column_new();
98  gtk_tree_view_column_set_title (column, header.c_str());
99 
100  GtkCellRenderer *renderer;
101  renderer = gtk_cell_renderer_pixbuf_new();
102  gtk_tree_view_column_pack_start (column, renderer, FALSE);
103  gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", icon_col, NULL);
104 
105  renderer = gtk_cell_renderer_text_new();
106  gtk_tree_view_column_pack_start (column, renderer, TRUE);
107  gtk_tree_view_column_set_attributes (column, renderer, "text", text_col, NULL);
108  if (xalign != -1)
109  g_object_set (renderer, "xalign", xalign, NULL);
110 
111  gtk_tree_view_column_set_resizable (column, TRUE);
112  gtk_tree_view_append_column (getView(), column);
113  if (gtk_tree_view_get_search_column (getView()) == -1)
114  gtk_tree_view_set_search_column (getView(), text_col);
115 }
116 
117 void YMGA_GTreeView::addCheckColumn (int check_col)
118 {
119  addCheckColumn ("", check_col);
120 }
121 
122 void YMGA_GTreeView::addCheckColumn (const std::string &header, int check_col)
123 {
124  GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
125  g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (check_col));
126  GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
127  NULL, renderer, "active", check_col, NULL);
128 
129  gtk_tree_view_column_set_title (column, header.c_str());
130 
131  gtk_tree_view_column_set_cell_data_func (column, renderer, inconsistent_mark_cb, this, NULL);
132  g_signal_connect (G_OBJECT (renderer), "toggled",
133  G_CALLBACK (toggled_cb), this);
134 
135  gtk_tree_view_column_set_resizable (column, TRUE);
136  gtk_tree_view_append_column (getView(), column);
137  if (markColumn == -1)
138  markColumn = check_col;
139 }
140 
141 void YMGA_GTreeView::readModel()
142 {
143  gtk_tree_view_set_model (getView(), getModel());
144 }
145 
146 void YMGA_GTreeView::addCountWidget (YWidget *yparent)
147 {
148  bool mainWidget = !yparent || !strcmp (yparent->widgetClass(), "YVBox") || !strcmp (yparent->widgetClass(), "YReplacePoint");
149  if (mainWidget) {
150  m_count = gtk_label_new ("0");
151  GtkWidget *hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
152  gtk_box_set_homogeneous (GTK_BOX (hbox), FALSE);
153 
154  GtkWidget *label = gtk_label_new (_("Total selected:"));
155  //gtk_box_pack_start (GTK_BOX (hbox), gtk_event_box_new(), TRUE, TRUE, 0);
156  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
157  gtk_box_pack_start (GTK_BOX (hbox), m_count, FALSE, TRUE, 0);
158  gtk_box_pack_start (GTK_BOX (YGWidget::getWidget()), hbox, FALSE, TRUE, 0);
159  gtk_widget_show_all (hbox);
160  }
161 }
162 
163 void YMGA_GTreeView::syncCount()
164 {
165  if (!m_count) return;
166 
167  struct inner {
168  static gboolean foreach (
169  GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
170  {
171  YMGA_GTreeView *pThis = (YMGA_GTreeView *) _pThis;
172  gboolean mark;
173  gtk_tree_model_get (model, iter, pThis->markColumn, &mark, -1);
174  if (mark) {
175  int count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), "count"));
176  g_object_set_data (G_OBJECT (model), "count", GINT_TO_POINTER (count+1));
177  }
178  return FALSE;
179  }
180  };
181 
182  GtkTreeModel *model = getModel();
183  g_object_set_data (G_OBJECT (model), "count", 0);
184  gtk_tree_model_foreach (model, inner::foreach, this);
185 
186  int count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), "count"));
187  gchar *str = g_strdup_printf ("%d", count);
188  gtk_label_set_text (GTK_LABEL (m_count), str);
189  g_free (str);
190 }
191 
192 void YMGA_GTreeView::focusItem (YItem *item, bool select)
193 {
194  GtkTreeIter iter;
195  getTreeIter (item, &iter);
196  blockSelected();
197 
198  if (select) {
199  GtkTreePath *path = gtk_tree_model_get_path (getModel(), &iter);
200  gtk_tree_view_expand_to_path (getView(), path);
201 
202  if (gtk_tree_selection_get_mode (getSelection()) != GTK_SELECTION_MULTIPLE)
203  gtk_tree_view_scroll_to_cell (getView(), path, NULL, TRUE, 0.5, 0);
204  gtk_tree_path_free (path);
205 
206  gtk_tree_selection_select_iter (getSelection(), &iter);
207  }
208  else
209  gtk_tree_selection_unselect_iter (getSelection(), &iter);
210 }
211 
212 void YMGA_GTreeView::unfocusAllItems()
213 {
214  blockSelected();
215  gtk_tree_selection_unselect_all (getSelection());
216 }
217 
218 void YMGA_GTreeView::unmarkAll()
219 {
220  struct inner {
221  static gboolean foreach_unmark (
222  GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
223  {
224  YMGA_GTreeView *pThis = (YMGA_GTreeView *) _pThis;
225  pThis->setRowMark (iter, pThis->markColumn, FALSE);
226  return FALSE;
227  }
228  };
229 
230  gtk_tree_model_foreach (getModel(), inner::foreach_unmark, this);
231 }
232 
233 YItem *YMGA_GTreeView::getFocusItem()
234 {
235  GtkTreeIter iter;
236  if (gtk_tree_selection_get_selected (getSelection(), NULL, &iter))
237  return getYItem (&iter);
238  return NULL;
239 }
240 
241 
242 void YMGA_GTreeView::setMark (GtkTreeIter *iter, YItem *yitem, gint column, bool state, bool recursive)
243 {
244  setRowMark (iter, column, state);
245  yitem->setSelected (state);
246 
247  if (recursive)
248  for (YItemConstIterator it = yitem->childrenBegin();
249  it != yitem->childrenEnd(); it++) {
250  GtkTreeIter _iter;
251  getTreeIter (*it, &_iter);
252  setMark (&_iter, *it, column, state, true);
253  }
254 }
255 
256 void YMGA_GTreeView::toggleMark (GtkTreePath *path, gint column)
257 {
258  GtkTreeIter iter;
259  if (!gtk_tree_model_get_iter (getModel(), &iter, path))
260  return;
261  gboolean state;
262  gtk_tree_model_get (getModel(), &iter, column, &state, -1);
263  state = !state;
264 
265  YItem *yitem = getYItem (&iter);
266  YCBTableItem *pYCBTableItem = dynamic_cast<YCBTableItem*>(yitem);
267  if (pYCBTableItem)
268  {
269  YMGA_CBTable * pTable = dynamic_cast<YMGA_CBTable*>(this);
270  if (pTable)
271  {
272  if ( (pTable->tableMode() == YCBTableMode::YCBTableCheckBoxOnFirstColumn && column == 0)
273  ||
274  (pTable->tableMode() == YCBTableMode::YCBTableCheckBoxOnLastColumn && column == (pTable->columns()-1)*3 ))
275  {
276  setRowMark (&iter, column, state);
277  pYCBTableItem->check(state);
278  pTable->setChangedItem(pYCBTableItem);
279  emitEvent (YEvent::ValueChanged);
280  }
281  }
282  }
283  else
284  {
285  setMark (&iter, yitem, column, state, _recursiveSelection());
286  syncCount();
287  emitEvent (YEvent::ValueChanged);
288  }
289 }
290 
291 unsigned int YMGA_GTreeView::getMinSize (YUIDimension dim)
292 {
293  if (dim == YD_VERT)
294  return YGUtils::getCharsHeight (getWidget(), _shrinkable() ? 2 : 5);
295  return 80;
296 }
297 
298 gboolean YMGA_GTreeView::block_selected_timeout_cb (gpointer data)
299 {
300  YMGA_GTreeView *pThis = (YMGA_GTreeView *) data;
301  pThis->m_blockTimeout = 0;
302  return FALSE;
303 }
304 
305 void YMGA_GTreeView::blockSelected()
306 { // GtkTreeSelection only fires when idle; so set a timeout
307  if (m_blockTimeout) g_source_remove (m_blockTimeout);
308  m_blockTimeout = g_timeout_add_full (G_PRIORITY_LOW, 50, block_selected_timeout_cb, this, NULL);
309 }
310 
311 void YMGA_GTreeView::block_init_cb (GtkWidget *widget, YMGA_GTreeView *pThis)
312 {
313  pThis->blockSelected();
314 }
315 
316 // callbacks
317 
318 bool YMGA_GTreeView::all_marked (GtkTreeModel *model, GtkTreeIter *iter, int mark_col)
319 {
320  gboolean marked;
321  GtkTreeIter child_iter;
322  if (gtk_tree_model_iter_children (model, &child_iter, iter))
323  do {
324  gtk_tree_model_get (model, &child_iter, mark_col, &marked, -1);
325  if (!marked) return false;
326  all_marked (model, &child_iter, mark_col);
327  } while (gtk_tree_model_iter_next (model, &child_iter));
328  return true;
329 }
330 
331 void YMGA_GTreeView::inconsistent_mark_cb (GtkTreeViewColumn *column,
332  GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
333 { // used for trees -- show inconsistent if one node is check but another isn't
334  YMGA_GTreeView *pThis = (YMGA_GTreeView *) data;
335  gboolean marked;
336  gtk_tree_model_get (model, iter, pThis->markColumn, &marked, -1);
337  gboolean consistent = !marked || all_marked (model, iter, pThis->markColumn);
338  g_object_set (G_OBJECT (cell), "inconsistent", !consistent, NULL);
339 }
340 
341 void YMGA_GTreeView::selection_changed_cb (GtkTreeSelection *selection, YMGA_GTreeView *pThis)
342 {
343  struct inner {
344  static gboolean foreach_sync_select (
345  GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
346  {
347  YMGA_GTreeView *pThis = (YMGA_GTreeView *) _pThis;
348  GtkTreeSelection *selection = pThis->getSelection();
349  bool sel = gtk_tree_selection_iter_is_selected (selection, iter);
350  pThis->getYItem (iter)->setSelected (sel);
351  return FALSE;
352  }
353  };
354 
355  if (pThis->m_blockTimeout) return;
356  gtk_tree_model_foreach (pThis->getModel(), inner::foreach_sync_select, pThis);
357  if (pThis->_immediateMode())
358  pThis->emitEvent (YEvent::SelectionChanged, IF_NOT_PENDING_EVENT);
359 }
360 
361 void YMGA_GTreeView::activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
362  GtkTreeViewColumn *column, YMGA_GTreeView* pThis)
363 {
364  YMGA_CBTable *pTable = dynamic_cast<YMGA_CBTable*>(pThis);
365  if (pTable)
366  {
367  GtkTreeViewColumn* col = gtk_tree_view_get_column (pThis->getView(), pThis->markColumn);
368  if (col == column)
369  pThis->toggleMark (path, pThis->markColumn);
370  else
371  {
372  // for tree - expand/collpase double-clicked rows
373  if ( gtk_tree_view_row_expanded ( tree_view, path ) )
374  gtk_tree_view_collapse_row ( tree_view, path );
375  else
376  gtk_tree_view_expand_row ( tree_view, path, FALSE );
377 
378  pThis->emitEvent ( YEvent::Activated );
379  }
380  }
381  else //impossible
382  pThis->toggleMark (path, pThis->markColumn);
383 }
384 
385 void YMGA_GTreeView::toggled_cb (GtkCellRendererToggle *renderer, gchar *path_str,
386  YMGA_GTreeView *pThis)
387 {
388  GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
389  gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer), "column"));
390  pThis->toggleMark (path, column);
391  gtk_tree_path_free (path);
392 
393  // un/marking a sub-node can cause changes of "inconsistency"
394  if (gtk_tree_path_get_depth (path) >= 2)
395  gtk_widget_queue_draw (pThis->getWidget());
396 }
397 
398 void YMGA_GTreeView::right_click_cb (YGtkTreeView *view, gboolean outreach, YMGA_GTreeView *pThis)
399 {
400  pThis->emitEvent (YEvent::ContextMenuActivated);
401 }
402 
403 
404 //**** YMGA_GCBTable implementation
405 
406 YMGA_GCBTable::YMGA_GCBTable (YWidget *parent, YTableHeader *headers, YCBTableMode mode)
407  : YMGA_CBTable (NULL, headers, mode),
408  YMGA_GTreeView (this, parent, std::string(), false)
409 {
410  gtk_tree_view_set_headers_visible (getView(), TRUE);
411  ygtk_tree_view_set_empty_text (YGTK_TREE_VIEW (getView()), _("No entries."));
412  int columnNumber = columns();
413 
414  yuiMilestone() << " Slection mode " << mode << std::endl;
415 
416  GType types [columnNumber*3];
417  for (int i = 0; i < columnNumber; i++) {
418  int t = i*3;
419  types[t+0] = G_TYPE_BOOLEAN;
420  types[t+1] = GDK_TYPE_PIXBUF;
421  types[t+2] = G_TYPE_STRING;
422  if ( (i==0 && mode == YCBTableCheckBoxOnFirstColumn) ||
423  (i == columnNumber-1 && mode == YCBTableCheckBoxOnLastColumn))
424  addCheckColumn(header(i), t);
425  else
426  addTextColumn (header(i), alignment (i), t+1, t+2);
427  }
428  createStore (columnNumber*3, types);
429  readModel();
430  if (!keepSorting())
431  setSortable (true);
432 
433  yuiMilestone() << " columns " << columns() << " tot " << columnNumber << std::endl;
434 
435  // if last col is aligned: add some dummy so that it doesn't expand.
436  YAlignmentType lastAlign = alignment (columnNumber-1);
437  if (lastAlign == YAlignCenter || lastAlign == YAlignEnd)
438  gtk_tree_view_append_column (getView(), gtk_tree_view_column_new());
439 
440  g_signal_connect (getWidget(), "key-press-event", G_CALLBACK (key_press_event_cb), this);
441 }
442 
443 void YMGA_GCBTable::setSortable (bool sortable)
444 {
445  if (!sortable && !gtk_widget_get_realized (getWidget()))
446  return;
447  int n = 0;
448  GList *columns = gtk_tree_view_get_columns (getView());
449  int mode = tableMode();
450  int columnNumber = YMGA_GCBTable::columns();
451  for (GList *i = columns; i; i = i->next, n++) {
452  GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data;
453  if (n >= columnNumber)
454  break;
455  if (sortable) {
456  // offset 2 is text (G_TYPE_STRING)
457  int index = (n*3)+2;
458  if (! ( (n==0 && mode == YCBTableCheckBoxOnFirstColumn) ||
459  (n == columnNumber-1 && mode == YCBTableCheckBoxOnLastColumn)))
460  {
461  gtk_tree_sortable_set_sort_func (
462  GTK_TREE_SORTABLE (getModel()), index, tree_sort_cb,
463  GINT_TO_POINTER (index), NULL);
464  gtk_tree_view_column_set_sort_column_id (column, index);
465  }
466  }
467  else
468  gtk_tree_view_column_set_sort_column_id (column, -1);
469  }
470  g_list_free (columns);
471 }
472 
473 void YMGA_GCBTable::setCell (GtkTreeIter *iter, int column, const YTableCell *cell)
474 {
475  if (!cell) return;
476  std::string label (cell->label());
477 
478  int index = column * 3;
479  setRowText (iter, index+1, cell->iconName(), index+2, label, this);
480 }
481 
482 // YGTreeView
483 
484 bool YMGA_GCBTable::_immediateMode() {
485  return immediateMode();
486 }
487 
488 // YMGA_CBTable
489 
490 void YMGA_GCBTable::setKeepSorting (bool keepSorting)
491 {
492  YMGA_CBTable::setKeepSorting (keepSorting);
493  setSortable (!keepSorting);
494  if (!keepSorting) {
495  GtkTreeViewColumn *column = gtk_tree_view_get_column (getView(), 0);
496  if (column)
497  gtk_tree_view_column_clicked (column);
498  }
499 }
500 
501 void YMGA_GCBTable::cellChanged (const YTableCell *cell)
502 {
503  GtkTreeIter iter;
504  getTreeIter (cell->parent(), &iter);
505  int mode = tableMode();
506  int column = (mode == YCBTableCheckBoxOnLastColumn ? cell->column() : cell->column() +1);
507  setCell (&iter, column, cell);
508 }
509 
510 void YMGA_GCBTable::doAddItem (YItem *_item)
511 {
512  YCBTableItem *item = dynamic_cast <YCBTableItem *> (_item);
513  if (item) {
514  GtkTreeIter iter;
515  addRow (item, &iter);
516  int i = 0;
517  if (tableMode() == YCBTableMode::YCBTableCheckBoxOnFirstColumn )
518  {
519  setRowMark(&iter, i++, item->checked());
520  }
521  for (YTableCellIterator it = item->cellsBegin();
522  it != item->cellsEnd(); it++)
523  {
524  if (i >= columns())
525  {
526  yuiWarning() << "Item contains too many columns, current is " << i
527  << " but only " << columns() << " columns are configured" << std::endl;
528  }
529  else
530  setCell (&iter, i++, *it);
531  }
532  if (tableMode() == YCBTableMode::YCBTableCheckBoxOnLastColumn )
533  {
534  int col = columns() -1;
535  setRowMark(&iter, col*3, item->checked());
536  }
537  if (item->selected())
538  focusItem (item, true);
539  }
540  else
541  yuiError() << "Can only add YCBTableItems to a YTable.\n";
542 }
543 
544 void YMGA_GCBTable::checkItem ( YItem* item, bool checked )
545 {
546  GtkTreeIter iter;
547  YCBTableItem *pItem = dynamic_cast <YCBTableItem *> (item);
548 
549  getTreeIter ( item, &iter );
550  blockSelected();
551  setRowMark ( &iter, markColumn, checked );
552  pItem->check(checked);
553 }
554 
555 void YMGA_GCBTable::doSelectItem (YItem *item, bool select)
556 {
557  focusItem (item, select);
558 }
559 
560 void YMGA_GCBTable::doDeselectAllItems()
561 {
562  unfocusAllItems();
563 }
564 
565 // callbacks
566 
567 void YMGA_GCBTable::activateButton (YWidget *button)
568 {
569  YWidgetEvent *event = new YWidgetEvent (button, YEvent::Activated);
570  YGUI::ui()->sendEvent (event);
571 }
572 
573 void YMGA_GCBTable::hack_right_click_cb (YGtkTreeView* view, gboolean outreach, YMGA_GCBTable* pThis)
574 {
575  if (pThis->notifyContextMenu())
576  return YMGA_GTreeView::right_click_cb (view, outreach, pThis);
577 
578  // If no context menu is specified, hack one ;-)
579 
580  struct inner {
581  static void key_activate_cb (GtkMenuItem *item, YWidget *button)
582  {
583  activateButton (button);
584  }
585  static void appendItem (GtkWidget *menu, const gchar *stock, int key)
586  {
587  YWidget *button = YGDialog::currentDialog()->getFunctionWidget (key);
588  if (button) {
589  GtkWidget *item;
590  item = gtk_menu_item_new_with_mnemonic (stock);
591  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
592  g_signal_connect (G_OBJECT (item), "activate",
593  G_CALLBACK (key_activate_cb), button);
594  }
595  }
596  };
597 
598  GtkWidget *menu = gtk_menu_new();
599  YGDialog *dialog = YGDialog::currentDialog();
600  if (dialog->getClassWidgets ("YTable").size() == 1) {
601  // if more than one table exists, function keys would be ambiguous
602  if (dialog->getClassWidgets ("YTable").size() == 1) {
603  // if more than one table exists, function keys would be ambiguous
604  if (outreach) {
605  if (dialog->getFunctionWidget(3))
606  inner::appendItem (menu, "list-add", 3);
607  }
608  else {
609  if (dialog->getFunctionWidget(4))
610  inner::appendItem (menu, "edit-cut", 4);
611  if (dialog->getFunctionWidget(5))
612  inner::appendItem (menu, "list-remove", 5);
613  }
614  }
615  }
616 
617  menu = ygtk_tree_view_append_show_columns_item (YGTK_TREE_VIEW (view), menu);
618  ygtk_tree_view_popup_menu (view, menu);
619 }
620 
621 gboolean YMGA_GCBTable::key_press_event_cb (GtkWidget* widget, GdkEventKey* event, YMGA_GCBTable* pThis)
622 {
623  if (event->keyval == GDK_KEY_Delete) {
624  YWidget *button = YGDialog::currentDialog()->getFunctionWidget (5);
625  if (button)
626  activateButton (button);
627  else
628  gtk_widget_error_bell (widget);
629  return TRUE;
630  }
631  return FALSE;
632 }
633 
634 gint YMGA_GCBTable::tree_sort_cb (
635  GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer _index)
636 {
637  int index = GPOINTER_TO_INT (_index);
638  gchar *str_a, *str_b;
639  gtk_tree_model_get (model, a, index, &str_a, -1);
640  gtk_tree_model_get (model, b, index, &str_b, -1);
641  if (!str_a) str_a = g_strdup ("");
642  if (!str_b) str_b = g_strdup ("");
643  int ret = strcmp (str_a, str_b);
644  g_free (str_a);
645  g_free (str_b);
646  return ret;
647 }
648 
YMGA_GTreeView
Definition: YMGA_GCBTable.h:42
YMGA_GCBTable
Definition: YMGA_GCBTable.h:123