Author: rpmcruz
Date: Thu Dec 23 03:55:50 2010
New Revision: 63029
URL: http://svn.opensuse.org/viewcvs/yast?rev=63029&view=rev
Log:
* Implemented new YTree::multiselection flag.
* Cleaned that portion of the code considerably.
Added:
trunk/gtk/src/YGSelectionStore.cc
trunk/gtk/src/YGSelectionStore.h
trunk/gtk/src/YGTreeView.cc
Removed:
trunk/gtk/src/YGSelectionModel.cc
trunk/gtk/src/YGSelectionModel.h
trunk/gtk/src/YGTable.cc
Modified:
trunk/gtk/src/CMakeLists.txt
trunk/gtk/src/YGComboBox.cc
trunk/gtk/src/YGUI.h
Modified: trunk/gtk/src/CMakeLists.txt
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/CMakeLists.txt?rev=63029&r1=63028&r2=63029&view=diff
==============================================================================
--- trunk/gtk/src/CMakeLists.txt (original)
+++ trunk/gtk/src/CMakeLists.txt Thu Dec 23 03:55:50 2010
@@ -16,9 +16,9 @@
YGPushButton.cc
YGProgressBar.cc
YGRadioButton.cc
- YGSelectionModel.cc
- YGTable.cc
+ YGSelectionStore.cc
YGText.cc
+ YGTreeView.cc
YGUtils.cc
YGUI.cc
YGWidget.cc
Modified: trunk/gtk/src/YGComboBox.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGComboBox.cc?rev=63029&r1=63028&r2=63029&view=diff
==============================================================================
--- trunk/gtk/src/YGComboBox.cc (original)
+++ trunk/gtk/src/YGComboBox.cc Thu Dec 23 03:55:50 2010
@@ -7,33 +7,35 @@
#include
#include "YGUtils.h"
#include "YComboBox.h"
-#include "YGSelectionModel.h"
+#include "YGSelectionStore.h"
#include "YGWidget.h"
-class YGComboBox : public YComboBox, public YGLabeledWidget, public YGSelectionModel
+class YGComboBox : public YComboBox, public YGLabeledWidget, public YGSelectionStore
{
public:
YGComboBox (YWidget *parent, const string &label, bool editable)
- : YComboBox (NULL, label, editable)
- , YGLabeledWidget (this, parent, label, YD_HORIZ,
- editable ? GTK_TYPE_COMBO_BOX_ENTRY : GTK_TYPE_COMBO_BOX, NULL)
- , YGSelectionModel (this, true, false)
+ : YComboBox (NULL, label, editable),
+ YGLabeledWidget (this, parent, label, YD_HORIZ,
+ editable ? GTK_TYPE_COMBO_BOX_ENTRY : GTK_TYPE_COMBO_BOX, NULL),
+ YGSelectionStore (false)
{
+ const GType types[2] = { GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ createStore (2, types);
gtk_combo_box_set_model (getComboBox(), getModel());
- GtkCellRenderer* cell;
+
+ GtkCellRenderer* cell = gtk_cell_renderer_pixbuf_new();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (getWidget()), cell, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
+ "pixbuf", 0, NULL);
+
if (editable)
- gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (getWidget()),
- YGSelectionModel::LABEL_COLUMN);
+ gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (getWidget()), 1);
else {
- cell = gtk_cell_renderer_text_new ();
+ cell = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (getWidget()), cell, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
- "text", YGSelectionModel::LABEL_COLUMN, NULL);
+ "text", 1, NULL);
}
- cell = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (getWidget()), cell, FALSE);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
- "pixbuf", YGSelectionModel::ICON_COLUMN, NULL);
connect (getWidget(), "changed", G_CALLBACK (selected_changed_cb), this);
}
@@ -42,74 +44,70 @@
{ return GTK_COMBO_BOX (getWidget()); }
GtkEntry *getEntry()
+ { return GTK_ENTRY (gtk_bin_get_child (GTK_BIN (getWidget()))); }
+
+ // YGSelectionModel
+
+ void doAddItem (YItem *item)
{
- if (!GTK_IS_COMBO_BOX_ENTRY (getWidget())) {
- yuiError() << "YGComboBox: trying to edit read-only combo box\n";
- return NULL;
- }
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ setRowText (&iter, 0, item->iconName(), 1, item->label(), this);
+ }
- GtkWidget *entry = gtk_bin_get_child (GTK_BIN (getWidget()));
- if (!GTK_IS_ENTRY (entry)) {
- g_error ("YGComboBox: GtkComboBoxEntry doesn't have a GtkEntry as child");
- return NULL;
+ void doSelectItem (YItem *item, bool select)
+ {
+ if (select) {
+ BlockEvents block (this);
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ gtk_combo_box_set_active_iter (getComboBox(), &iter);
}
+ }
- return GTK_ENTRY (entry);
+ void doDeselectAllItems()
+ {
+ BlockEvents block (this);
+ gtk_combo_box_set_active (getComboBox(), -1);
}
- virtual string text()
+ YItem *doSelectedItem()
+ {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (getComboBox(), &iter))
+ return getYItem (&iter);
+ return NULL;
+ }
+
+ // YComboBox
+
+ virtual std::string text()
{
- gchar *str = 0;
+ gchar *str;
if (GTK_IS_COMBO_BOX_ENTRY (getWidget()))
str = gtk_combo_box_get_active_text (getComboBox());
else {
GtkTreeIter iter;
- if (gtk_combo_box_get_active_iter (getComboBox(), &iter)) {
- gchar *str = 0;
- gtk_tree_model_get (getModel(), &iter, LABEL_COLUMN, &str, -1);
- }
- }
- std::string ret;
- if (str) {
- ret = str;
- g_free (str);
+ if (gtk_combo_box_get_active_iter (getComboBox(), &iter))
+ gtk_tree_model_get (getModel(), &iter, 1, &str, -1);
+ else
+ return "";
}
+ std::string ret (str);
+ g_free (str);
return ret;
}
- virtual void setText (const string &value)
+ virtual void setText (const std::string &value)
{
BlockEvents block (this);
GtkTreeIter iter;
- if (findByText (value, &iter))
- doSelectItem (&iter);
+ if (findLabel (1, value, &iter))
+ gtk_combo_box_set_active_iter (getComboBox(), &iter);
else
gtk_entry_set_text (getEntry(), value.c_str());
}
- // YGSelectionModel
- virtual void doSelectItem (GtkTreeIter *iter)
- {
- BlockEvents block (this);
- gtk_combo_box_set_active_iter (getComboBox(), iter);
- }
-
- virtual void doUnselectAll()
- {
- BlockEvents block (this);
- gtk_combo_box_set_active (getComboBox(), -1);
- }
-
-
- virtual YItem *doSelectedItem()
- {
- GtkTreeIter iter;
- if (gtk_combo_box_get_active_iter (getComboBox(), &iter))
- return getItem (&iter);
- return NULL;
- }
-
- // YComboBox
virtual void setInputMaxLength (int length)
{
YComboBox::setInputMaxLength (length);
Added: trunk/gtk/src/YGSelectionStore.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGSelectionStore.cc?rev=63029&view=auto
==============================================================================
--- trunk/gtk/src/YGSelectionStore.cc (added)
+++ trunk/gtk/src/YGSelectionStore.cc Thu Dec 23 03:55:50 2010
@@ -0,0 +1,181 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include
+#include
+#include
+#include "YGUtils.h"
+#include "YGSelectionStore.h"
+
+static inline int getYItemCol (GtkTreeModel *model)
+{ return gtk_tree_model_get_n_columns (model) - 2; }
+
+static inline int getRowIdCol (GtkTreeModel *model)
+{ return gtk_tree_model_get_n_columns (model) - 1; }
+
+YGSelectionStore::YGSelectionStore (bool tree)
+: isTree (tree), m_nextRowId (0)
+{}
+
+YGSelectionStore::~YGSelectionStore()
+{ g_object_unref (G_OBJECT (m_model)); }
+
+void YGSelectionStore::createStore (int cols, const GType types[])
+{
+ int _cols = cols + 2;
+ GType _types[_cols];
+ for (int i = 0; i < cols; i++)
+ _types[i] = types[i];
+ _types[cols+0] = G_TYPE_POINTER; // pointer to YItem
+ _types[cols+1] = G_TYPE_POINTER; // some unique value identifying this row
+
+ if (isTree)
+ m_model = GTK_TREE_MODEL (gtk_tree_store_newv (_cols, _types));
+ else
+ m_model = GTK_TREE_MODEL (gtk_list_store_newv (_cols, _types));
+}
+
+void YGSelectionStore::addRow (YItem *item, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ if (isTree) {
+ GtkTreeStore *store = GTK_TREE_STORE (m_model);
+ gtk_tree_store_append (store, iter, parent);
+ gtk_tree_store_set (store, iter, getYItemCol (m_model), item,
+ getRowIdCol (m_model), m_nextRowId, -1);
+ }
+ else {
+ GtkListStore *store = getListStore();
+ gtk_list_store_append (store, iter);
+ gtk_list_store_set (store, iter, getYItemCol (m_model), item,
+ getRowIdCol (m_model), m_nextRowId, -1);
+ }
+ item->setData (m_nextRowId);
+ m_nextRowId = GINT_TO_POINTER (GPOINTER_TO_INT (m_nextRowId) + 1);
+}
+
+void YGSelectionStore::setRowText (GtkTreeIter *iter, int iconCol, const std::string &icon, int labelCol, const std::string &label, const YSelectionWidget *widget)
+{
+ GdkPixbuf *pixbuf = 0;
+ if (!icon.empty()) {
+ std::string path (widget->iconFullPath (icon));
+ pixbuf = YGUtils::loadPixbuf (path);
+ }
+
+ if (isTree)
+ gtk_tree_store_set (getTreeStore(), iter, iconCol, pixbuf,
+ labelCol, label.c_str(), -1);
+ else
+ gtk_list_store_set (getListStore(), iter, iconCol, pixbuf,
+ labelCol, label.c_str(), -1);
+}
+
+void YGSelectionStore::setRowMark (GtkTreeIter *iter, int markCol, bool mark)
+{
+ if (isTree)
+ gtk_tree_store_set (getTreeStore(), iter, markCol, mark, -1);
+ else
+ gtk_list_store_set (getListStore(), iter, markCol, mark, -1);
+}
+
+void YGSelectionStore::doDeleteAllItems()
+{
+ if (isTree)
+ gtk_tree_store_clear (getTreeStore());
+ else
+ gtk_list_store_clear (getListStore());
+ m_nextRowId = 0;
+}
+
+YItem *YGSelectionStore::getYItem (GtkTreeIter *iter)
+{
+ gpointer ptr;
+ gtk_tree_model_get (m_model, iter, getYItemCol (m_model), &ptr, -1);
+ return (YItem *) ptr;
+}
+
+static GtkTreeIter *found_iter;
+
+void YGSelectionStore::getTreeIter (const YItem *item, GtkTreeIter *iter)
+{
+ struct inner {
+ static gboolean foreach_find (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer find_id)
+ {
+ gpointer id;
+ gtk_tree_model_get (model, iter, getRowIdCol (model), &id, -1);
+ if (id == find_id) {
+ found_iter = gtk_tree_iter_copy (iter);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ };
+
+ found_iter = NULL;
+ gtk_tree_model_foreach (m_model, inner::foreach_find, item->data());
+ *iter = *found_iter;
+ gtk_tree_iter_free (found_iter);
+}
+
+GtkListStore *YGSelectionStore::getListStore()
+{ return GTK_LIST_STORE (m_model); }
+
+GtkTreeStore *YGSelectionStore::getTreeStore()
+{ return GTK_TREE_STORE (m_model); }
+
+bool YGSelectionStore::isEmpty()
+{
+ GtkTreeIter iter;
+ return !gtk_tree_model_get_iter_first (m_model, &iter);
+}
+
+int YGSelectionStore::getTreeDepth()
+{
+ struct inner {
+ static gboolean foreach_max_depth (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _depth)
+ {
+ int *depth = (int *) _depth;
+ *depth = MAX (*depth, gtk_tree_path_get_depth (path));
+ return FALSE;
+ }
+ };
+
+ int depth = 0;
+ gtk_tree_model_foreach (m_model, inner::foreach_max_depth, &depth);
+ return depth;
+}
+
+#include
+static int find_col;
+
+bool YGSelectionStore::findLabel (int labelCol, const std::string &label, GtkTreeIter *iter)
+{
+ struct inner {
+ static gboolean foreach_find (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _value)
+ {
+ gchar *value = (gchar *) _value;
+ gchar *v;
+ gtk_tree_model_get (model, iter, find_col, &v, -1);
+ if (!strcmp (v, value)) {
+ found_iter = gtk_tree_iter_copy (iter);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ };
+
+ find_col = labelCol;
+ found_iter = NULL;
+ gtk_tree_model_foreach (m_model, inner::foreach_find, (gpointer) label.c_str());
+ if (found_iter) {
+ *iter = *found_iter;
+ gtk_tree_iter_free (found_iter);
+ }
+ return found_iter != NULL;
+}
+
Added: trunk/gtk/src/YGSelectionStore.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGSelectionStore.h?rev=63029&view=auto
==============================================================================
--- trunk/gtk/src/YGSelectionStore.h (added)
+++ trunk/gtk/src/YGSelectionStore.h Thu Dec 23 03:55:50 2010
@@ -0,0 +1,64 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Provides a basic model common to YSelectedWidget widgets. */
+
+#ifndef YGSELECTION_STORE_H
+#define YGSELECTION_STORE_H
+
+#include
+struct YItem;
+struct YSelectionWidget;
+
+struct YGSelectionStore
+{
+ YGSelectionStore (bool tree);
+ virtual ~YGSelectionStore();
+
+ GtkTreeModel *getModel() { return m_model; }
+ void createStore (int cols, const GType types[]);
+
+ void addRow (YItem *item, GtkTreeIter *iter, GtkTreeIter *parent = 0);
+ void setRowText (GtkTreeIter *iter, int iconCol, const std::string &icon,
+ int labelCol, const std::string &label, const YSelectionWidget *widget);
+ void setRowMark (GtkTreeIter *iter, int markCol, bool mark);
+ void doDeleteAllItems();
+
+ YItem *getYItem (GtkTreeIter *iter);
+ void getTreeIter (const YItem *item, GtkTreeIter *iter);
+
+ GtkListStore *getListStore();
+ GtkTreeStore *getTreeStore();
+
+ bool isEmpty();
+ int getTreeDepth();
+
+ bool findLabel (int labelCol, const std::string &label, GtkTreeIter *iter);
+
+protected:
+ GtkTreeModel *m_model;
+ bool isTree;
+ gpointer m_nextRowId;
+};
+
+#define YGSELECTION_WIDGET_IMPL(ParentClass) \
+ virtual void addItem(YItem *item) { \
+ ParentClass::addItem (item); \
+ doAddItem (item); \
+ } \
+ virtual void deleteAllItems() { \
+ ParentClass::deleteAllItems(); \
+ doDeleteAllItems(); \
+ } \
+ virtual void selectItem (YItem *item, bool select) { \
+ ParentClass::selectItem (item, select); \
+ doSelectItem (item, select); \
+ } \
+ virtual void deselectAllItems() { \
+ ParentClass::deselectAllItems(); \
+ doDeselectAllItems(); \
+ }
+
+#endif /*YGSELECTION_STORE_H*/
+
Added: trunk/gtk/src/YGTreeView.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGTreeView.cc?rev=63029&view=auto
==============================================================================
--- trunk/gtk/src/YGTreeView.cc (added)
+++ trunk/gtk/src/YGTreeView.cc Thu Dec 23 03:55:50 2010
@@ -0,0 +1,728 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YSelectionWidget.h"
+#include "YGSelectionStore.h"
+#include "ygtktreeview.h"
+
+/* A generic widget for table related widgets. */
+
+class YGTreeView : public YGScrolledWidget, public YGSelectionStore
+{
+protected:
+ guint m_blockTimeout;
+
+public:
+ YGTreeView (YWidget *ywidget, YWidget *parent, const string &label, bool tree)
+ : YGScrolledWidget (ywidget, parent, label, YD_VERT, YGTK_TYPE_TREE_VIEW, NULL),
+ YGSelectionStore (tree)
+ {
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (getWidget()), FALSE);
+
+ /* Yast tools expect the user to be unable to un-select the row. They
+ generally don't check to see if the returned value is -1. So, just
+ disallow un-selection. */
+ gtk_tree_selection_set_mode (getSelection(), GTK_SELECTION_BROWSE);
+
+ connect (getSelection(), "changed", G_CALLBACK (selection_changed_cb), this);
+ connect (getWidget(), "row-activated", G_CALLBACK (activated_cb), this);
+ connect (getWidget(), "right-click", G_CALLBACK (right_click_cb), this);
+
+ m_blockTimeout = 0; // GtkTreeSelection idiotically fires when showing widget
+ g_signal_connect (getWidget(), "map", G_CALLBACK (block_init_cb), this);
+ }
+
+ virtual ~YGTreeView()
+ { if (m_blockTimeout) g_source_remove (m_blockTimeout); }
+
+ inline GtkTreeView *getView()
+ { return GTK_TREE_VIEW (getWidget()); }
+ inline GtkTreeSelection *getSelection()
+ { return gtk_tree_view_get_selection (getView()); }
+
+ void addTextColumn (int iconCol, int textCol)
+ { addTextColumn ("", YAlignUnchanged, iconCol, textCol); }
+
+ void addTextColumn (const std::string &header, YAlignmentType align, int icon_col, int text_col)
+ {
+ gfloat xalign = -1;
+ switch (align) {
+ case YAlignBegin: xalign = 0.0; break;
+ case YAlignCenter: xalign = 0.5; break;
+ case YAlignEnd: xalign = 1.0; break;
+ case YAlignUnchanged: break;
+ }
+
+ GtkTreeViewColumn *column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column, header.c_str());
+
+ GtkCellRenderer *renderer;
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", icon_col, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer, "text", text_col, NULL);
+ if (xalign != -1)
+ g_object_set (renderer, "xalign", xalign, NULL);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (getView(), column);
+ }
+
+ void addCheckColumn (int check_col)
+ {
+ GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
+ g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (check_col));
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "active", check_col, NULL);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (toggled_cb), this);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (getView(), column);
+ }
+
+ void readModel()
+ { gtk_tree_view_set_model (getView(), getModel()); }
+
+ void focusItem (YItem *item, bool select)
+ {
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ blockSelected();
+
+ if (select) {
+ GtkTreePath *path = gtk_tree_model_get_path (getModel(), &iter);
+ gtk_tree_view_expand_to_path (getView(), path);
+
+ if (gtk_tree_selection_get_mode (getSelection()) != GTK_SELECTION_MULTIPLE)
+ gtk_tree_view_scroll_to_cell (getView(), path, NULL, TRUE, 0.5, 0);
+ gtk_tree_path_free (path);
+
+ gtk_tree_selection_select_iter (getSelection(), &iter);
+ }
+ else
+ gtk_tree_selection_unselect_iter (getSelection(), &iter);
+ }
+
+ void unfocusAllItems()
+ {
+ blockSelected();
+ gtk_tree_selection_unselect_all (getSelection());
+ }
+
+ void unmarkAll()
+ {
+ struct inner {
+ static gboolean foreach_unmark (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTreeView *pThis = (YGTreeView *) _pThis;
+ pThis->setRowMark (iter, pThis->markColumn(), FALSE);
+ return FALSE;
+ }
+ };
+
+ gtk_tree_model_foreach (getModel(), inner::foreach_unmark, this);
+ }
+
+ virtual bool _immediateMode() { return true; }
+ virtual bool _shrinkable() { return false; }
+
+ virtual int markColumn() { return -1; }
+
+ void toggleMark (GtkTreePath *path, gint column)
+ {
+ GtkTreeIter iter;
+ if (!gtk_tree_model_get_iter (getModel(), &iter, path))
+ return;
+
+ gboolean state;
+ gtk_tree_model_get (getModel(), &iter, column, &state, -1);
+ state = !state;
+ setRowMark (&iter, column, state);
+ getYItem (&iter)->setSelected (state);
+ emitEvent (YEvent::ValueChanged);
+ }
+
+ // YGWidget
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ {
+ if (dim == YD_VERT)
+ return YGUtils::getCharsHeight (getWidget(), _shrinkable() ? 2 : 5);
+ return 80;
+ }
+
+protected:
+ static gboolean block_selected_timeout_cb (gpointer data)
+ {
+ YGTreeView *pThis = (YGTreeView *) data;
+ pThis->m_blockTimeout = 0;
+ return FALSE;
+ }
+
+ void blockSelected()
+ { // GtkTreeSelection only fires when idle; so set a timeout
+ if (m_blockTimeout) g_source_remove (m_blockTimeout);
+ m_blockTimeout = g_timeout_add_full (G_PRIORITY_LOW, 250, block_selected_timeout_cb, this, NULL);
+ }
+
+ static void block_init_cb (GtkWidget *widget, YGTreeView *pThis)
+ { pThis->blockSelected(); }
+
+ // callbacks
+
+ static void selection_changed_cb (GtkTreeSelection *selection, YGTreeView *pThis)
+ {
+ struct inner {
+ static gboolean foreach_sync_select (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTreeView *pThis = (YGTreeView *) _pThis;
+ GtkTreeSelection *selection = pThis->getSelection();
+ bool sel = gtk_tree_selection_iter_is_selected (selection, iter);
+ pThis->getYItem (iter)->setSelected (sel);
+ return FALSE;
+ }
+ };
+
+ if (pThis->m_blockTimeout) return;
+ if (pThis->markColumn() < 0)
+ gtk_tree_model_foreach (pThis->getModel(), inner::foreach_sync_select, pThis);
+ if (pThis->_immediateMode())
+ pThis->emitEvent (YEvent::SelectionChanged, IF_NOT_PENDING_EVENT);
+ }
+
+ static void activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
+ GtkTreeViewColumn *column, YGTreeView* pThis)
+ {
+ if (pThis->markColumn() >= 0)
+ pThis->toggleMark (path, pThis->markColumn());
+ else {
+ // for tree - expand/collpase double-clicked rows
+ if (gtk_tree_view_row_expanded (tree_view, path))
+ gtk_tree_view_collapse_row (tree_view, path);
+ else
+ gtk_tree_view_expand_row (tree_view, path, FALSE);
+
+ pThis->emitEvent (YEvent::Activated);
+ }
+ }
+
+ static void toggled_cb (GtkCellRendererToggle *renderer, gchar *path_str,
+ YGTreeView *pThis)
+ {
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer), "column"));
+ pThis->toggleMark (path, column);
+ gtk_tree_path_free (path);
+ }
+
+ static void right_click_cb (YGtkTreeView *view, gboolean outreach, YGTreeView *pThis)
+ { pThis->emitEvent (YEvent::ContextMenuActivated); }
+};
+
+#include "YTable.h"
+#include "YGDialog.h"
+#include
+#include
+
+class YGTable : public YTable, public YGTreeView
+{
+public:
+ YGTable (YWidget *parent, YTableHeader *headers, bool multiSelection)
+ : YTable (NULL, headers, multiSelection),
+ YGTreeView (this, parent, std::string(), false)
+ {
+ gtk_tree_view_set_headers_visible (getView(), TRUE);
+ gtk_tree_view_set_rules_hint (getView(), columns() > 1);
+ ygtk_tree_view_set_empty_text (YGTK_TREE_VIEW (getView()), _("No entries."));
+ if (multiSelection)
+ gtk_tree_selection_set_mode (getSelection(), GTK_SELECTION_MULTIPLE);
+
+ GType types [columns()*2];
+ for (int i = 0; i < columns(); i++) {
+ int t = i*2;
+ types[t+0] = GDK_TYPE_PIXBUF;
+ types[t+1] = G_TYPE_STRING;
+ addTextColumn (header(i), alignment (i), t, t+1);
+ }
+ createStore (columns()*2, types);
+ readModel();
+ if (!keepSorting())
+ setSortable (true);
+
+ // if last col is aligned: add some dummy so that it doesn't expand.
+ YAlignmentType lastAlign = alignment (columns()-1);
+ if (lastAlign == YAlignCenter || lastAlign == YAlignEnd)
+ gtk_tree_view_append_column (getView(), gtk_tree_view_column_new());
+
+ g_signal_connect (getWidget(), "key-press-event", G_CALLBACK (key_press_event_cb), this);
+ }
+
+ void setSortable (bool sortable)
+ {
+ if (!sortable && !GTK_WIDGET_REALIZED (getWidget()))
+ return;
+ int n = 0;
+ GList *columns = gtk_tree_view_get_columns (getView());
+ for (GList *i = columns; i; i = i->next, n++) {
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data;
+ if (n >= YGTable::columns())
+ break;
+ if (sortable) {
+ int index = (n*2)+1;
+ if (!sortable)
+ index = -1;
+ gtk_tree_sortable_set_sort_func (
+ GTK_TREE_SORTABLE (getModel()), index, tree_sort_cb,
+ GINT_TO_POINTER (index), NULL);
+ gtk_tree_view_column_set_sort_column_id (column, index);
+ }
+ else
+ gtk_tree_view_column_set_sort_column_id (column, -1);
+ }
+ g_list_free (columns);
+ }
+
+ void setCell (GtkTreeIter *iter, int column, const YTableCell *cell)
+ {
+ std::string label (cell->label());
+ if (label == "X")
+ label = YUI::app()->glyph (YUIGlyph_CheckMark);
+
+ int index = column * 2;
+ setRowText (iter, index, cell->iconName(), index+1, label, this);
+ }
+
+ // YGTreeView
+
+ virtual bool _immediateMode() { return immediateMode(); }
+
+ // YTable
+
+ virtual void setKeepSorting (bool keepSorting)
+ {
+ YTable::setKeepSorting (keepSorting);
+ setSortable (!keepSorting);
+ if (!keepSorting) {
+ GtkTreeViewColumn *column = gtk_tree_view_get_column (getView(), 0);
+ if (column)
+ gtk_tree_view_column_clicked (column);
+ }
+ }
+
+ virtual void cellChanged (const YTableCell *cell)
+ {
+ GtkTreeIter iter;
+ getTreeIter (cell->parent(), &iter);
+ setCell (&iter, cell->column(), cell);
+ }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *_item)
+ {
+ YTableItem *item = dynamic_cast (_item);
+ if (item) {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ for (int i = 0; i < columns(); i++)
+ setCell (&iter, i, item->cell(i));
+ if (item->selected())
+ focusItem (item, true);
+ }
+ else
+ yuiError() << "Can only add YTableItems to a YTable.\n";
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ { focusItem (item, select); }
+
+ void doDeselectAllItems()
+ { unfocusAllItems(); }
+
+ // callbacks
+
+ static void activateButton (YWidget *button)
+ {
+ YWidgetEvent *event = new YWidgetEvent (button, YEvent::Activated);
+ YGUI::ui()->sendEvent (event);
+ }
+
+ static void hack_right_click_cb (YGtkTreeView *view, gboolean outreach, YGTable *pThis)
+ {
+ if (pThis->notifyContextMenu())
+ return YGTreeView::right_click_cb (view, outreach, pThis);
+
+ // If no context menu is specified, hack one ;-)
+
+ struct inner {
+ static void key_activate_cb (GtkMenuItem *item, YWidget *button)
+ { activateButton (button); }
+ static void appendItem (GtkWidget *menu, const gchar *stock, int key)
+ {
+ YWidget *button = YGDialog::currentDialog()->getFunctionWidget (key);
+ if (button) {
+ GtkWidget *item;
+ item = gtk_image_menu_item_new_from_stock (stock, NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (key_activate_cb), button);
+ }
+ }
+ };
+
+ GtkWidget *menu = gtk_menu_new();
+ YGDialog *dialog = YGDialog::currentDialog();
+ if (dialog->getClassWidgets ("YTable").size() == 1) {
+ // if more than one table exists, function keys would be ambiguous
+ if (outreach) {
+ if (dialog->getFunctionWidget(3))
+ inner::appendItem (menu, GTK_STOCK_ADD, 3);
+ }
+ else {
+ if (dialog->getFunctionWidget(4))
+ inner::appendItem (menu, GTK_STOCK_EDIT, 4);
+ if (dialog->getFunctionWidget(5))
+ inner::appendItem (menu, GTK_STOCK_DELETE, 5);
+ }
+ }
+
+ menu = ygtk_tree_view_append_show_columns_item (YGTK_TREE_VIEW (view), menu);
+ ygtk_tree_view_popup_menu (view, menu);
+ }
+
+ static gboolean key_press_event_cb (GtkWidget *widget, GdkEventKey *event, YGTable *pThis)
+ {
+ if (event->keyval == GDK_Delete) {
+ YWidget *button = YGDialog::currentDialog()->getFunctionWidget (5);
+ if (button)
+ activateButton (button);
+ else
+ gtk_widget_error_bell (widget);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ static gint tree_sort_cb (
+ GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer _index)
+ {
+ int index = GPOINTER_TO_INT (_index);
+ gchar *str_a, *str_b;
+ gtk_tree_model_get (model, a, index, &str_a, -1);
+ gtk_tree_model_get (model, b, index, &str_b, -1);
+ if (!str_a) str_a = g_strdup ("");
+ if (!str_b) str_b = g_strdup ("");
+ int ret = strcmp (str_a, str_b);
+ g_free (str_a); g_free (str_b);
+ return ret;
+ }
+
+ YGLABEL_WIDGET_IMPL (YTable)
+ YGSELECTION_WIDGET_IMPL (YTable)
+};
+
+YTable *YGWidgetFactory::createTable (YWidget *parent, YTableHeader *headers,
+ bool multiSelection)
+{
+ return new YGTable (parent, headers, multiSelection);
+}
+
+#include "YSelectionBox.h"
+
+class YGSelectionBox : public YSelectionBox, public YGTreeView
+{
+public:
+ YGSelectionBox (YWidget *parent, const string &label)
+ : YSelectionBox (NULL, label),
+ YGTreeView (this, parent, label, false)
+ {
+ GType types [2] = { GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ addTextColumn (0, 1);
+ createStore (2, types);
+ readModel();
+ }
+
+ // YGTreeView
+
+ virtual bool _shrinkable() { return shrinkable(); }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *item)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ setRowText (&iter, 0, item->iconName(), 1, item->label(), this);
+ if (item->selected())
+ focusItem (item, true);
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ { focusItem (item, select); }
+
+ void doDeselectAllItems()
+ { unfocusAllItems(); }
+
+ YGLABEL_WIDGET_IMPL (YSelectionBox)
+ YGSELECTION_WIDGET_IMPL (YSelectionBox)
+};
+
+YSelectionBox *YGWidgetFactory::createSelectionBox (YWidget *parent, const string &label)
+{ return new YGSelectionBox (parent, label); }
+
+#include "YMultiSelectionBox.h"
+
+class YGMultiSelectionBox : public YMultiSelectionBox, public YGTreeView
+{
+public:
+ YGMultiSelectionBox (YWidget *parent, const string &label)
+ : YMultiSelectionBox (NULL, label),
+ YGTreeView (this, parent, label, false)
+ {
+ GType types [3] = { G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ addCheckColumn (0);
+ addTextColumn (1, 2);
+ createStore (3, types);
+ readModel();
+ }
+
+ // YGTreeView
+
+ virtual bool _shrinkable() { return shrinkable(); }
+ virtual int markColumn() { return 0; }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *item)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ setRowMark (&iter, 0, item->selected());
+ setRowText (&iter, 1, item->iconName(), 2, item->label(), this);
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ {
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ setRowMark (&iter, 0, select);
+ }
+
+ void doDeselectAllItems()
+ { unmarkAll(); }
+
+ // YMultiSelectionBox
+
+ virtual YItem *currentItem()
+ {
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (getSelection(), NULL, &iter))
+ return getYItem (&iter);
+ return NULL;
+ }
+
+ virtual void setCurrentItem (YItem *item)
+ { focusItem (item, true); }
+
+ YGLABEL_WIDGET_IMPL (YMultiSelectionBox)
+ YGSELECTION_WIDGET_IMPL (YMultiSelectionBox)
+};
+
+YMultiSelectionBox *YGWidgetFactory::createMultiSelectionBox (YWidget *parent, const string &label)
+{ return new YGMultiSelectionBox (parent, label); }
+
+#include "YTree.h"
+#include "YTreeItem.h"
+
+class YGTree : public YTree, public YGTreeView
+{
+public:
+#if YAST2_VERSION >= 2019002
+ YGTree (YWidget *parent, const string &label, bool multiselection)
+ : YTree (NULL, label, multiselection),
+#else
+ YGTree (YWidget *parent, const string &label)
+ : YTree (NULL, label),
+#endif
+ YGTreeView (this, parent, label, true)
+ {
+#if YAST2_VERSION >= 2019002
+ if (multiselection) {
+ GType types [3] = { GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN };
+ addCheckColumn (2);
+ addTextColumn (0, 1);
+ createStore (3, types);
+ }
+ else
+#else
+ {
+ GType types [2] = { GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ addTextColumn (0, 1);
+ createStore (2, types);
+ }
+#endif
+ readModel();
+
+ g_signal_connect (getWidget(), "row-collapsed", G_CALLBACK (row_collapsed_cb), this);
+ g_signal_connect (getWidget(), "row-expanded", G_CALLBACK (row_expanded_cb), this);
+ }
+
+ void addNode (YItem *item, GtkTreeIter *parent)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter, parent);
+ setRowText (&iter, 0, item->iconName(), 1, item->label(), this);
+ if (item->selected()) {
+#if YAST2_VERSION >= 2019002
+ if (hasMultiSelection())
+ setRowMark (&iter, 2, item->selected());
+ else
+#endif
+ focusItem (item, true);
+ }
+/* if (((YTreeItem *) item)->isOpen())
+ expand (&iter);*/
+ for (YItemConstIterator it = item->childrenBegin();
+ it != item->childrenEnd(); it++)
+ addNode (*it, &iter);
+ }
+
+/*
+ void expand (GtkTreeIter *iter)
+ {
+ GtkTreePath *path = gtk_tree_model_get_path (getModel(), iter);
+ gtk_tree_view_expand_row (getView(), path, FALSE);
+ gtk_tree_path_free (path);
+ }
+
+ bool isReallyOpen (YTreeItem *item) // are parents open as well?
+ {
+ for (YTreeItem *i = item; i; i = i->parent())
+ if (!i->isOpen())
+ return false;
+ return true;
+ }
+*/
+
+ // YTree
+
+ virtual void rebuildTree()
+ {
+ doDeleteAllItems();
+ for (YItemConstIterator it = YTree::itemsBegin(); it != YTree::itemsEnd(); it++)
+ addNode (*it, NULL);
+
+ int depth = getTreeDepth();
+ gtk_tree_view_set_show_expanders (getView(), depth > 1);
+ gtk_tree_view_set_enable_tree_lines (getView(), depth > 3);
+
+ // for whatever reason, we need to expand nodes only after the model
+ // is fully initialized
+ struct inner {
+ static gboolean foreach_sync_open (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTree *pThis = (YGTree *) _pThis;
+ YTreeItem *item = (YTreeItem *) pThis->getYItem (iter);
+ if (item->isOpen())
+ gtk_tree_view_expand_row (pThis->getView(), path, FALSE);
+ return FALSE;
+ }
+ };
+
+ gtk_tree_model_foreach (getModel(), inner::foreach_sync_open, this);
+ }
+
+ // YGTreeView
+
+#if YAST2_VERSION >= 2019002
+ virtual int markColumn() { return hasMultiSelection() ? 2 : -1; }
+#endif
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *item) {} // rebuild will be called anyway
+
+ void doSelectItem (YItem *item, bool select)
+ {
+#if YAST2_VERSION >= 2019002
+ if (hasMultiSelection()) {
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ setRowMark (&iter, 2, select);
+ }
+ else
+#endif
+ focusItem (item, select);
+ }
+
+ void doDeselectAllItems()
+ {
+#if YAST2_VERSION >= 2019002
+ if (hasMultiSelection())
+ unmarkAll();
+ else
+#endif
+ unfocusAllItems();
+ }
+
+ // callbacks
+
+ void reportRowOpen (GtkTreeIter *iter, bool open)
+ {
+ YTreeItem *item = static_cast (getYItem (iter));
+ item->setOpen (open);
+ }
+
+ static void row_collapsed_cb (GtkTreeView *view, GtkTreeIter *iter,
+ GtkTreePath *path, YGTree *pThis)
+ { pThis->reportRowOpen (iter, false); }
+
+ static void row_expanded_cb (GtkTreeView *view, GtkTreeIter *iter,
+ GtkTreePath *path, YGTree *pThis)
+ { pThis->reportRowOpen (iter, true); }
+
+#if 0
+ // we do a bit of a work-around here to mimic -qt behavior... A node can
+ // be initialized as open, yet its parent, or some grand-parent, be closed.
+ // We thus honor the open state when its parent gets open.
+ YTreeItem *item = static_cast (pThis->getYItem (iter));
+ for (YItemConstIterator it = item->childrenBegin();
+ it != item->childrenEnd(); it++) {
+ const YTreeItem *child = static_cast (*it);
+ if (child->isOpen()) {
+ GtkTreeIter iter;
+ if (pThis->getIter (child, &iter))
+ pThis->expand (&iter);
+ }
+ }
+#endif
+
+ YGLABEL_WIDGET_IMPL (YTree)
+ YGSELECTION_WIDGET_IMPL (YTree)
+};
+
+#if YAST2_VERSION >= 2019002
+YTree *YGWidgetFactory::createTree (YWidget *parent, const string &label, bool multiselection)
+{ return new YGTree (parent, label, multiselection); }
+#else
+YTree *YGWidgetFactory::createTree (YWidget *parent, const string &label)
+{ return new YGTree (parent, label); }
+#endif
+
Modified: trunk/gtk/src/YGUI.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUI.h?rev=63029&r1=63028&r2=63029&view=diff
==============================================================================
--- trunk/gtk/src/YGUI.h (original)
+++ trunk/gtk/src/YGUI.h Thu Dec 23 03:55:50 2010
@@ -89,12 +89,12 @@
virtual YRadioButton *createRadioButton (YWidget *parent, const string &label, bool isChecked);
virtual YComboBox *createComboBox (YWidget *parent, const string & label, bool editable);
virtual YSelectionBox *createSelectionBox (YWidget *parent, const string &label);
- virtual YTree *createTree (YWidget *parent, const string &label);
-#if YAST2_VERSION >= 2017005
- virtual YTable *createTable (YWidget *parent, YTableHeader *headers, bool multiSelection);
+#if YAST2_VERSION >= 2019002
+ virtual YTree *createTree (YWidget *parent, const string &label, bool multiselection);
#else
- virtual YTable *createTable (YWidget *parent, YTableHeader *headers);
+ virtual YTree *createTree (YWidget *parent, const string &label);
#endif
+ virtual YTable *createTable (YWidget *parent, YTableHeader *headers, bool multiSelection);
virtual YProgressBar *createProgressBar (YWidget *parent, const string &label, int maxValue);
virtual YBusyIndicator *createBusyIndicator (YWidget *parent, const string &label, int timeout);
virtual YRichText *createRichText (YWidget *parent, const string &text, bool plainTextMode);
@@ -110,9 +110,7 @@
virtual YWidget *createPkgSpecial (YWidget * parent, const string & subwidgetName) RET (NULL) // for ncurses
virtual YLayoutBox *createLayoutBox (YWidget *parent, YUIDimension dimension);
-#if YAST2_VERSION >= 2017006
virtual YButtonBox *createButtonBox (YWidget *parent);
-#endif
virtual YSpacing *createSpacing (YWidget *parent, YUIDimension dim, bool stretchable, YLayoutSize_t size);
virtual YEmpty *createEmpty (YWidget *parent);
@@ -224,9 +222,7 @@
virtual bool richTextSupportsTable() RET (false)
#endif
-#if YAST2_VERSION > 2018003
virtual bool openContextMenu (const YItemCollection &itemCollection);
-#endif
private:
// for screenshots:
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org