Author: rpmcruz
Date: Thu Dec 20 21:38:55 2007
New Revision: 43214
URL: http://svn.opensuse.org/viewcvs/yast?rev=43214&view=rev
Log:
Moving unstable-libyui to main.
Added:
trunk/gtk/src/ygtkimage.c
trunk/gtk/src/ygtkimage.h
trunk/gtk/src/ygtkzyppwrapper.cc
trunk/gtk/src/ygtkzyppwrapper.h
trunk/gtk/src/yzyppwrapper.cc
trunk/gtk/src/yzyppwrapper.h
Added: trunk/gtk/src/ygtkimage.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkimage.c?rev=43214&view=auto
==============================================================================
--- trunk/gtk/src/ygtkimage.c (added)
+++ trunk/gtk/src/ygtkimage.c Thu Dec 20 21:38:55 2007
@@ -0,0 +1,285 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkImage widget */
+// check the header file for information about this widget
+
+#include
+#include "ygdkmngloader.h"
+#include "ygtkimage.h"
+#include
+
+G_DEFINE_TYPE (YGtkImage, ygtk_image, GTK_TYPE_DRAWING_AREA)
+
+static void ygtk_image_init (YGtkImage *image)
+{
+}
+
+static void ygtk_image_free_pixbuf (YGtkImage *image)
+{
+ if (image->animated) {
+ if (image->animation) {
+ g_object_unref (G_OBJECT (image->animation->pixbuf));
+ if (image->animation->timeout_id)
+ g_source_remove (image->animation->timeout_id);
+ g_free (image->animation);
+ image->animation = NULL;
+ }
+ }
+ else {
+ if (image->pixbuf) {
+ g_object_unref (G_OBJECT (image->pixbuf));
+ image->pixbuf = NULL;
+ }
+ }
+}
+
+static void ygtk_image_destroy (GtkObject *object)
+{
+ YGtkImage *image = YGTK_IMAGE (object);
+ if (image->alt_text)
+ g_free (image->alt_text);
+ image->alt_text = NULL;
+ ygtk_image_free_pixbuf (image);
+ GTK_OBJECT_CLASS (ygtk_image_parent_class)->destroy (object);
+}
+
+static void ygtk_image_set_pixbuf (YGtkImage *image, GdkPixbuf *pixbuf, const char *error_msg)
+{
+ ygtk_image_free_pixbuf (image);
+ gtk_widget_queue_resize (GTK_WIDGET (image));
+
+ if (pixbuf) {
+ image->animated = FALSE;
+ image->pixbuf = pixbuf;
+ image->loaded = TRUE;
+ }
+/* else
+ g_warning ("Couldn't load image - %s", error_msg);*/
+}
+
+static gboolean ygtk_image_advance_frame_cb (gpointer data)
+{
+ YGtkImage *image = (YGtkImage *) data;
+ struct _YGtkImageAnimation *animation = image->animation;
+
+ if (!animation->frame) // no frame yet loaded
+ animation->frame = gdk_pixbuf_animation_get_iter (animation->pixbuf, NULL);
+ else
+ if (gdk_pixbuf_animation_iter_advance (animation->frame, NULL))
+ gtk_widget_queue_draw (GTK_WIDGET (image));
+
+ // shedule next frame
+ int delay = gdk_pixbuf_animation_iter_get_delay_time (animation->frame);
+ if (delay != -1)
+ animation->timeout_id = g_timeout_add (delay, ygtk_image_advance_frame_cb, data);
+ return FALSE;
+}
+
+static void ygtk_image_set_animation (YGtkImage *image, GdkPixbufAnimation *pixbuf,
+ const char *error_msg)
+{
+ ygtk_image_free_pixbuf (image);
+ gtk_widget_queue_resize (GTK_WIDGET (image));
+
+ if (pixbuf) {
+ image->animated = TRUE;
+ image->animation = g_new0 (struct _YGtkImageAnimation, 1);
+ image->animation->pixbuf = pixbuf;
+ image->loaded = TRUE;
+ ygtk_image_advance_frame_cb (image);
+ }
+/* else
+ g_warning ("Couldn't load image - %s", error_msg);*/
+}
+
+void ygtk_image_set_from_file (YGtkImage *image, const char *filename, gboolean anim)
+{
+ GError *error = 0;
+ if (anim) {
+ GdkPixbufAnimation *pixbuf;
+ if (ygdk_mng_pixbuf_is_file_mng (filename))
+ pixbuf = ygdk_mng_pixbuf_new_from_file (filename, &error);
+ else
+ pixbuf = gdk_pixbuf_animation_new_from_file (filename, &error);
+ ygtk_image_set_animation (image, pixbuf, error ? error->message : "(undefined)");
+ }
+ else {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+ ygtk_image_set_pixbuf (image, pixbuf, error ? error->message : "(undefined)");
+ }
+}
+
+static void ygtk_image_loaded_cb (GdkPixbufLoader *loader, YGtkImage *image)
+{
+ if (image->animated) {
+ if (image->animation) {
+ // a new frame loaded -- just redraw the widget
+ if (gdk_pixbuf_animation_iter_on_currently_loading_frame
+ (image->animation->frame))
+ gtk_widget_queue_draw (GTK_WIDGET (image));
+ }
+ else {
+ GdkPixbufAnimation *pixbuf = gdk_pixbuf_loader_get_animation (loader);
+ g_object_ref (G_OBJECT (pixbuf));
+ ygtk_image_set_animation (image, pixbuf, "on block data reading callback");
+ }
+ }
+ else {
+ GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ g_object_ref (G_OBJECT (pixbuf));
+ ygtk_image_set_pixbuf (image, pixbuf, "on block data reading callback");
+ }
+}
+
+void ygtk_image_set_from_data (YGtkImage *image, const guint8 *data, long data_size, gboolean anim)
+{
+ GError *error = 0;
+ if (anim && ygdk_mng_pixbuf_is_data_mng (data, data_size)) {
+ GdkPixbufAnimation *pixbuf;
+ pixbuf = ygdk_mng_pixbuf_new_from_data (data, data_size, &error);
+ ygtk_image_set_animation (image, pixbuf, error ? error->message : "(undefined)");
+ }
+ else {
+ image->animated = anim;
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+ g_signal_connect (G_OBJECT (loader), "area-prepared",
+ G_CALLBACK (ygtk_image_loaded_cb), image);
+ if (!gdk_pixbuf_loader_write (loader, data, data_size, &error))
+ g_warning ("Could not load image from data blocks: %s", error->message);
+ gdk_pixbuf_loader_close (loader, &error);
+ }
+}
+
+void ygtk_image_set_props (YGtkImage *image, YGtkImageAlign align, const gchar *alt_text)
+{
+ image->align = align;
+ if (image->alt_text)
+ g_free (image->alt_text);
+ image->alt_text = g_strdup (alt_text);
+ gtk_widget_queue_draw (GTK_WIDGET (image));
+}
+
+static void ygtk_image_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ YGtkImage *image = YGTK_IMAGE (widget);
+ int width = 0, height = 0;
+ if (image->loaded) {
+ if (image->animated) {
+ width = gdk_pixbuf_animation_get_width (image->animation->pixbuf);
+ height = gdk_pixbuf_animation_get_height (image->animation->pixbuf);
+ }
+ else {
+ width = gdk_pixbuf_get_width (image->pixbuf);
+ height = gdk_pixbuf_get_height (image->pixbuf);
+ }
+ }
+ else if (image->alt_text) {
+ PangoLayout *layout;
+ layout = gtk_widget_create_pango_layout (widget, image->alt_text);
+ pango_layout_get_pixel_size (layout, &width, &height);
+ }
+ requisition->width = width;
+ requisition->height = height;
+}
+
+static GdkPixbuf *ygtk_image_render_state (GtkWidget *widget, GdkPixbuf *pixbuf)
+{
+ // as in GtkImage
+ GtkIconSource *source = gtk_icon_source_new();
+ GdkPixbuf *rendered;
+ gtk_icon_source_set_pixbuf (source, pixbuf);
+ gtk_icon_source_set_size (source, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ gtk_icon_source_set_size_wildcarded (source, FALSE);
+ rendered = gtk_style_render_icon (widget->style, source,
+ gtk_widget_get_direction (widget), GTK_WIDGET_STATE (widget),
+ /* arbitrary */ (GtkIconSize)-1, widget, "gtk-image");
+ gtk_icon_source_free (source);
+ return rendered;
+}
+
+static gboolean ygtk_image_expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ YGtkImage *image = YGTK_IMAGE (widget);
+ int width, height;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ cairo_t *cr = gdk_cairo_create (widget->window);
+
+ if (!image->loaded && image->alt_text) {
+ // show alt text if no image was loaded
+ PangoLayout *layout;
+ layout = gtk_widget_create_pango_layout (widget, image->alt_text);
+
+ int x, y;
+ x = (width - widget->requisition.width) / 2;
+ y = (height - widget->requisition.height) / 2;
+
+ cairo_move_to (cr, x, y);
+ pango_cairo_show_layout (cr, layout);
+
+ g_object_unref (layout);
+ cairo_destroy (cr);
+ return TRUE;
+ }
+
+ GdkPixbuf *pixbuf;
+ if (image->animated)
+ pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (image->animation->frame);
+ else
+ pixbuf = image->pixbuf;
+
+ gboolean needs_transform = GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL;
+ if (needs_transform)
+ pixbuf = ygtk_image_render_state (widget, pixbuf);
+ int x = 0, y = 0;
+ if (image->align == CENTER_IMAGE_ALIGN) {
+ x = (width - widget->requisition.width) / 2;
+ y = (height - widget->requisition.height) / 2;
+ }
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
+
+ switch (image->align) {
+ case CENTER_IMAGE_ALIGN:
+ break;
+ case SCALE_IMAGE_ALIGN:
+ {
+ double scale_x = (double) gdk_pixbuf_get_width (pixbuf) / width;
+ double scale_y = (double) gdk_pixbuf_get_height (pixbuf) / height;
+ cairo_matrix_t matrix;
+ cairo_matrix_init_scale (&matrix, scale_x, scale_y);
+ cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
+ break;
+ }
+ case TILE_IMAGE_ALIGN:
+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+ break;
+ }
+
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+ if (needs_transform)
+ g_object_unref (G_OBJECT (pixbuf));
+ return FALSE;
+}
+
+GtkWidget* ygtk_image_new (void)
+{
+ return g_object_new (YGTK_TYPE_IMAGE, NULL);
+}
+
+static void ygtk_image_class_init (YGtkImageClass *klass)
+{
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->expose_event = ygtk_image_expose_event;
+ widget_class->size_request = ygtk_image_size_request;
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_image_destroy;
+}
+
Added: trunk/gtk/src/ygtkimage.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkimage.h?rev=43214&view=auto
==============================================================================
--- trunk/gtk/src/ygtkimage.h (added)
+++ trunk/gtk/src/ygtkimage.h Thu Dec 20 21:38:55 2007
@@ -0,0 +1,75 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* GtkImage doesn't provide all the functionality asked by libyui,
+ such as scaling and tiling. Thus, YGtkImage is a more powerful
+ GtkImage.
+*/
+
+#ifndef YGTK_IMAGE_H
+#define YGTK_IMAGE_H
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_IMAGE (ygtk_image_get_type ())
+#define YGTK_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_IMAGE, YGtkImage))
+#define YGTK_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_IMAGE, YGtkImageClass))
+#define YGTK_IS_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_IMAGE))
+#define YGTK_IS_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_IMAGE))
+#define YGTK_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_IMAGE, YGtkImageClass))
+
+typedef enum {
+ CENTER_IMAGE_ALIGN, SCALE_IMAGE_ALIGN, TILE_IMAGE_ALIGN
+} YGtkImageAlign;
+
+struct _YGtkImageAnimation {
+ GdkPixbufAnimation *pixbuf;
+ GdkPixbufAnimationIter *frame;
+ guint timeout_id;
+};
+
+typedef struct _YGtkImage
+{
+ GtkDrawingArea parent;
+
+ // properties:
+ YGtkImageAlign align;
+
+ gboolean animated;
+ union {
+ GdkPixbuf *pixbuf;
+ struct _YGtkImageAnimation *animation;
+ };
+
+ gboolean loaded;
+ gchar *alt_text;
+
+} YGtkImage;
+
+typedef struct _YGtkImageClass
+{
+ GtkDrawingAreaClass parent_class;
+} YGtkImageClass;
+
+GtkWidget* ygtk_image_new (void);
+GType ygtk_image_get_type (void) G_GNUC_CONST;
+
+void ygtk_image_set_from_file (YGtkImage *image, const char *filename, gboolean anim);
+void ygtk_image_set_from_data (YGtkImage *image, const guint8 *data, long size, gboolean anim);
+void ygtk_image_set_props (YGtkImage *image, YGtkImageAlign align, const gchar *alt_text);
+
+// as we don't have a window,
+
+G_END_DECLS
+
+#endif /* YGTK_IMAGE_H */
+
Added: trunk/gtk/src/ygtkzyppwrapper.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkzyppwrapper.cc?rev=43214&view=auto
==============================================================================
--- trunk/gtk/src/ygtkzyppwrapper.cc (added)
+++ trunk/gtk/src/ygtkzyppwrapper.cc Thu Dec 20 21:38:55 2007
@@ -0,0 +1,333 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkZyppWrapper, gtk+ hooks for zypp wrapper */
+// check the header file for information about these hooks
+
+#include
+#include "ygtkzyppwrapper.h"
+#include "YGUtils.h"
+
+#include "icons/pkg-installed.xpm"
+#include "icons/pkg-installed-upgradable.xpm"
+#include "icons/pkg-installed-upgradable-locked.xpm"
+#include "icons/pkg-installed-locked.xpm"
+#include "icons/pkg-available.xpm"
+#include "icons/pkg-available-locked.xpm"
+#include "icons/pkg-install.xpm"
+#include "icons/pkg-remove.xpm"
+#include "icons/pkg-install-auto.xpm"
+#include "icons/pkg-remove-auto.xpm"
+#include "icons/pkg-3D.xpm"
+
+// bridge as we don't want to mix c++ class polymorphism and gobject
+struct YGtkZyppModel::PoolNotify : public Ypp::Pool::Listener {
+YGtkZyppModel *model;
+ virtual void entryChanged (Ypp::Pool::Iter iter, Ypp::Package *package)
+ { ygtk_zypp_model_entry_changed (model, iter); }
+ virtual void entryInserted (Ypp::Pool::Iter iter, Ypp::Package *package)
+ { ygtk_zypp_model_entry_inserted (model, iter); }
+ virtual void entryDeleted (Ypp::Pool::Iter iter, Ypp::Package *package)
+ { ygtk_zypp_model_entry_deleted (model, iter); }
+};
+
+// Icons resources
+struct PackageIcons {
+ GdkPixbuf *installed, *installed_upgradable, *installed_locked,
+ *installed_upgradable_locked, *available, *available_locked,
+ *to_install, *to_remove, *to_auto_install, *to_auto_remove,
+ *is_3D;
+ PackageIcons() {
+ installed = gdk_pixbuf_new_from_xpm_data (pkg_installed_xpm);
+ installed_upgradable =
+ gdk_pixbuf_new_from_xpm_data (pkg_installed_upgradable_xpm);
+ installed_locked = gdk_pixbuf_new_from_xpm_data (pkg_installed_locked_xpm);
+ installed_upgradable_locked =
+ gdk_pixbuf_new_from_xpm_data (pkg_installed_upgradable_locked_xpm);
+ available = gdk_pixbuf_new_from_xpm_data (pkg_available_xpm);
+ available_locked = gdk_pixbuf_new_from_xpm_data (pkg_available_locked_xpm);
+ to_install = gdk_pixbuf_new_from_xpm_data (pkg_install_xpm);
+ to_remove = gdk_pixbuf_new_from_xpm_data (pkg_remove_xpm);
+ to_auto_install = gdk_pixbuf_new_from_xpm_data (pkg_install_auto_xpm);
+ to_auto_remove = gdk_pixbuf_new_from_xpm_data (pkg_remove_auto_xpm);
+ is_3D = gdk_pixbuf_new_from_xpm_data (pkg_3D_xpm);
+ }
+ ~PackageIcons() {
+ g_object_unref (G_OBJECT (installed));
+ g_object_unref (G_OBJECT (installed_upgradable));
+ g_object_unref (G_OBJECT (installed_upgradable_locked));
+ g_object_unref (G_OBJECT (installed_locked));
+ g_object_unref (G_OBJECT (available));
+ g_object_unref (G_OBJECT (available_locked));
+ g_object_unref (G_OBJECT (to_install));
+ g_object_unref (G_OBJECT (to_remove));
+ g_object_unref (G_OBJECT (to_auto_install));
+ g_object_unref (G_OBJECT (to_auto_remove));
+ g_object_unref (G_OBJECT (is_3D));
+ }
+};
+
+static PackageIcons *icons = NULL;
+void ygtk_zypp_model_finish()
+{
+ delete icons; icons = NULL;
+ Ypp::finish();
+}
+
+static void ygtk_zypp_model_tree_model_init (GtkTreeModelIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (YGtkZyppModel, ygtk_zypp_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, ygtk_zypp_model_tree_model_init))
+
+static void ygtk_zypp_model_init (YGtkZyppModel *zmodel)
+{
+ if (!icons)
+ icons = new PackageIcons();
+}
+
+static void ygtk_zypp_model_finalize (GObject *object)
+{
+ YGtkZyppModel *zmodel = YGTK_ZYPP_MODEL (object);
+ delete zmodel->notify;
+ zmodel->notify = NULL;
+ delete zmodel->pool;
+ zmodel->pool = NULL;
+ G_OBJECT_CLASS (ygtk_zypp_model_parent_class)->finalize (object);
+}
+
+static GtkTreeModelFlags ygtk_zypp_model_get_flags (GtkTreeModel *)
+{
+ return GtkTreeModelFlags (GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY);
+}
+
+static gboolean ygtk_zypp_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ YGtkZyppModel *zmodel = YGTK_ZYPP_MODEL (model);
+ gint row = gtk_tree_path_get_indices (path)[0];
+
+ iter->user_data = (gpointer) zmodel->pool->getIter (row);
+ return iter->user_data != NULL;
+}
+
+static GtkTreePath *ygtk_zypp_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ YGtkZyppModel *zmodel = YGTK_ZYPP_MODEL (model);
+ int row = zmodel->pool->getIndex (iter->user_data);
+fprintf (stderr, "get index: %d\n", row);
+
+ GtkTreePath *path = gtk_tree_path_new();
+ gtk_tree_path_append_index (path, row);
+ return path;
+}
+
+static gboolean ygtk_zypp_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ YGtkZyppModel *zmodel = YGTK_ZYPP_MODEL (model);
+ iter->user_data = zmodel->pool->getNext (iter->user_data);
+ return iter->user_data != NULL;
+}
+
+void ygtk_zypp_model_entry_changed (YGtkZyppModel *model, Ypp::Pool::Iter it)
+{
+ GtkTreeIter iter;
+ iter.user_data = it;
+ GtkTreePath *path = ygtk_zypp_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+}
+
+void ygtk_zypp_model_entry_inserted (YGtkZyppModel *model, Ypp::Pool::Iter it)
+{
+fprintf (stderr, "inserted row\n");
+ GtkTreeIter iter;
+ iter.user_data = it;
+ GtkTreePath *path = ygtk_zypp_model_get_path (GTK_TREE_MODEL (model), &iter);
+fprintf (stderr, "signal\n");
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+fprintf (stderr, "done\n");
+ gtk_tree_path_free (path);
+}
+
+void ygtk_zypp_model_entry_deleted (YGtkZyppModel *model, Ypp::Pool::Iter it)
+{
+ GtkTreeIter iter;
+ iter.user_data = it;
+ GtkTreePath *path = ygtk_zypp_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+}
+
+static gint ygtk_zypp_model_get_n_columns (GtkTreeModel *model)
+{
+ return YGtkZyppModel::TOTAL_COLUMNS;
+}
+
+static GType ygtk_zypp_model_get_column_type (GtkTreeModel *tree_model, gint column)
+{
+ switch (column)
+ {
+ case YGtkZyppModel::ICON_COLUMN:
+ return GDK_TYPE_PIXBUF;
+ case YGtkZyppModel::NAME_COLUMN:
+ case YGtkZyppModel::NAME_DESCRIPTION_COLUMN:
+ return G_TYPE_STRING;
+ case YGtkZyppModel::PTR_COLUMN:
+ return G_TYPE_POINTER;
+ case YGtkZyppModel::SPECIAL_ICON_COLUMN:
+ return GDK_TYPE_PIXBUF;
+ }
+ return 0;
+}
+
+static void ygtk_zypp_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
+ gint column, GValue *value)
+{
+ YGtkZyppModel *zmodel = YGTK_ZYPP_MODEL (model);
+ Ypp::Package *package = zmodel->pool->get (iter->user_data);
+
+ g_value_init (value, ygtk_zypp_model_get_column_type (model, column));
+ switch (column)
+ {
+ case YGtkZyppModel::ICON_COLUMN:
+ {
+ GdkPixbuf *pixbuf;
+ bool locked = package->isLocked();
+ bool auto_ = package->isAuto();
+ if (package->toInstall()) {
+ if (auto_)
+ pixbuf = icons->to_auto_install;
+ else
+ pixbuf = icons->to_install;
+ }
+ else if (package->toRemove()) {
+ if (auto_)
+ pixbuf = icons->to_auto_remove;
+ else
+ pixbuf = icons->to_remove;
+ }
+ else if (package->hasUpgrade()) {
+ if (locked)
+ pixbuf = icons->installed_upgradable_locked;
+ else
+ pixbuf = icons->installed_upgradable;
+ }
+ else if (package->isInstalled()) {
+ if (locked)
+ pixbuf = icons->installed_locked;
+ else
+ pixbuf = icons->installed;
+ }
+ else {
+ if (locked)
+ pixbuf = icons->available_locked;
+ else
+ pixbuf = icons->available;
+ }
+ g_value_set_object (value, (GObject *) pixbuf);
+ break;
+ }
+ case YGtkZyppModel::NAME_COLUMN:
+ {
+ std::string name = package->name();
+ const unsigned int max_width = 15;
+ if (name.size() > max_width) {
+ name.erase (max_width-3);
+ name += "...";
+ }
+ g_value_set_string (value, g_strdup (name.c_str()));
+ break;
+ }
+ case YGtkZyppModel::NAME_DESCRIPTION_COLUMN:
+ {
+ std::string str = package->name();
+ std::string summary = package->summary();
+ if (!summary.empty()) {
+ YGUtils::escapeMarkup (summary);
+ str += "\n<small>" + summary + "</small>";
+ }
+ g_value_set_string (value, g_strdup (str.c_str()));
+ break;
+ }
+ case YGtkZyppModel::PTR_COLUMN:
+ {
+ void *ptr;
+ ptr = (void *) package;
+ g_value_set_pointer (value, ptr);
+ break;
+ }
+ case YGtkZyppModel::SPECIAL_ICON_COLUMN:
+ {
+ if (package->is3D())
+ g_value_set_object (value, (GObject *) icons->is_3D);
+ else
+ g_value_set_object (value, NULL);
+ break;
+ }
+ default:
+ g_warning ("YGtkZyppModel column %d doesn't exist.", column);
+ break;
+ }
+}
+
+static gboolean ygtk_zypp_model_iter_children (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ return FALSE;
+}
+
+static gboolean ygtk_zypp_model_iter_has_child (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static gint ygtk_zypp_model_iter_n_children (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ return 0;
+}
+
+static gboolean ygtk_zypp_model_iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeIter *parent, gint n)
+{
+ return FALSE;
+}
+
+static gboolean ygtk_zypp_model_iter_parent (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+YGtkZyppModel *ygtk_zypp_model_new (Ypp::Query *query)
+{
+ YGtkZyppModel *zmodel = (YGtkZyppModel *) g_object_new (YGTK_TYPE_ZYPP_MODEL, NULL);
+ zmodel->notify = new YGtkZyppModel::PoolNotify();
+ zmodel->notify->model = zmodel;
+ zmodel->pool = new Ypp::Pool (query);
+ zmodel->pool->setListener (zmodel->notify);
+ return zmodel;
+}
+
+static void ygtk_zypp_model_class_init (YGtkZyppModelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = ygtk_zypp_model_finalize;
+}
+
+static void ygtk_zypp_model_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = ygtk_zypp_model_get_flags;
+ iface->get_n_columns = ygtk_zypp_model_get_n_columns;
+ iface->get_column_type = ygtk_zypp_model_get_column_type;
+ iface->get_iter = ygtk_zypp_model_get_iter;
+ iface->get_path = ygtk_zypp_model_get_path;
+ iface->get_value = ygtk_zypp_model_get_value;
+ iface->iter_next = ygtk_zypp_model_iter_next;
+ iface->iter_children = ygtk_zypp_model_iter_children;
+ iface->iter_has_child = ygtk_zypp_model_iter_has_child;
+ iface->iter_n_children = ygtk_zypp_model_iter_n_children;
+ iface->iter_nth_child = ygtk_zypp_model_iter_nth_child;
+ iface->iter_parent = ygtk_zypp_model_iter_parent;
+}
+
Added: trunk/gtk/src/ygtkzyppwrapper.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkzyppwrapper.h?rev=43214&view=auto
==============================================================================
--- trunk/gtk/src/ygtkzyppwrapper.h (added)
+++ trunk/gtk/src/ygtkzyppwrapper.h Thu Dec 20 21:38:55 2007
@@ -0,0 +1,54 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Contains ZyppWrapper query results in a GtkTreeModel.
+*/
+
+#ifndef YGTK_ZYPP_WRAPPER_H
+#define YGTK_ZYPP_WRAPPER_H
+
+#include "yzyppwrapper.h"
+#include
+
+#define YGTK_TYPE_ZYPP_MODEL (ygtk_zypp_model_get_type ())
+#define YGTK_ZYPP_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_ZYPP_MODEL, YGtkZyppModel))
+#define YGTK_ZYPP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_ZYPP_MODEL, YGtkZyppModelClass))
+#define YGTK_IS_ZYPP_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), YGTK_TYPE_ZYPP_MODEL))
+#define YGTK_IS_ZYPP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), YGTK_TYPE_ZYPP_MODEL))
+#define YGTK_ZYPP_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_ZYPP_MODEL, YGtkZyppModelClass))
+
+struct YGtkZyppModel
+{
+ GObject parent;
+
+ enum Columns {
+ ICON_COLUMN, NAME_COLUMN, NAME_DESCRIPTION_COLUMN, PTR_COLUMN,
+ SPECIAL_ICON_COLUMN, TOTAL_COLUMNS
+ };
+
+ Ypp::Pool *pool;
+
+ struct PoolNotify;
+ PoolNotify *notify;
+};
+
+struct YGtkZyppModelClass
+{
+ GObjectClass parent_class;
+};
+
+YGtkZyppModel *ygtk_zypp_model_new (Ypp::Query *query);
+GType ygtk_zypp_model_get_type (void) G_GNUC_CONST;
+// besides calling Ypp for cleaning, it also cleans the icons of this hook
+void ygtk_zypp_model_finish();
+
+void ygtk_zypp_model_entry_changed (YGtkZyppModel *model, Ypp::Pool::Iter iter);
+void ygtk_zypp_model_entry_inserted (YGtkZyppModel *model, Ypp::Pool::Iter iter);
+void ygtk_zypp_model_entry_deleted (YGtkZyppModel *model, Ypp::Pool::Iter iter);
+
+#endif /*YGTK_ZYPP_WRAPPER_H*/
+
Added: trunk/gtk/src/yzyppwrapper.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/yzyppwrapper.cc?rev=43214&view=auto
==============================================================================
--- trunk/gtk/src/yzyppwrapper.cc (added)
+++ trunk/gtk/src/yzyppwrapper.cc Thu Dec 20 21:38:55 2007
@@ -0,0 +1,1478 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Ypp, zypp wrapper */
+// check the header file for information about this wrapper
+
+#include
+#include "YGi18n.h"
+#include "yzyppwrapper.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include "YGUtils.h"
+
+//** Zypp shortcuts
+
+typedef zypp::ResPoolProxy ZyppPool;
+inline ZyppPool zyppPool() { return zypp::getZYpp()->poolProxy(); }
+typedef zypp::ui::Selectable::Ptr ZyppSelectable;
+typedef zypp::ui::Selectable* ZyppSelectablePtr;
+typedef zypp::ResObject::constPtr ZyppObject;
+typedef zypp::ResObject* ZyppObjectPtr;
+typedef zypp::Package::constPtr ZyppPackage;
+typedef zypp::Patch::constPtr ZyppPatch;
+typedef zypp::Pattern::constPtr ZyppPattern;
+typedef zypp::Language::constPtr ZyppLanguage;
+inline ZyppPackage tryCastToZyppPkg (ZyppObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Package> (obj); }
+inline ZyppPatch tryCastToZyppPatch (ZyppObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Patch> (obj); }
+inline ZyppPattern tryCastToZyppPattern (ZyppObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Pattern> (obj); }
+inline ZyppLanguage tryCastToZyppLanguage (ZyppObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Language> (obj); }
+
+//** Utilities
+
+// converts a set of tree representation in a form of a strings to a tree structure.
+// String tree representations are, for instance, filenames: /dir1/dir2/file
+struct StringTree {
+ typedef int (*Compare)(const char *, const char *);
+ Compare compare;
+ char delim;
+ GNode *root;
+
+ StringTree (Compare compare, char delim)
+ : compare (compare), delim (delim)
+ {
+ // the root is a dummy node to keep GNode happy
+ root = g_node_new (NULL);
+ }
+
+ ~StringTree()
+ {
+ struct inner {
+ static void free (GNode *node, void *_data)
+ { delete ((Ypp::Node *) node->data); }
+ };
+ g_node_children_foreach (root, G_TRAVERSE_ALL, inner::free, NULL);
+ g_node_destroy (root);
+ }
+
+ Ypp::Node *getFirst()
+ {
+ return (Ypp::Node *) root->children->data;
+ }
+
+ Ypp::Node *add (const std::string &tree_str)
+ {
+ const std::list std::string nodes_str = YGUtils::splitString (tree_str, delim);
+ GNode *parent = root, *sibling = 0;
+ Ypp::Node *ret = 0;
+
+ std::list std::string::const_iterator it;
+ for (it = nodes_str.begin(); it != nodes_str.end(); it++) {
+ bool found = false;
+ for (sibling = parent->children; sibling; sibling = sibling->next) {
+ Ypp::Node *yNode = (Ypp::Node *) sibling->data;
+ int cmp = (*compare) (it->c_str(), yNode->name.c_str());
+ if (cmp == 0) {
+ found = true;
+ ret = yNode;
+ break;
+ }
+ else if (cmp < 0)
+ break;
+ }
+ if (!found)
+ break;
+ parent = sibling;
+ }
+
+ for (; it != nodes_str.end(); it++) {
+ Ypp::Node *yNode = new Ypp::Node();
+ GNode *n = g_node_new ((void *) yNode);
+ yNode->name = *it;
+ yNode->impl = (void *) n;
+ g_node_insert_before (parent, sibling, n);
+ parent = n;
+ sibling = NULL;
+ ret = yNode;
+ }
+ return ret;
+ }
+};
+
+//** Singleton
+
+static Ypp *ypp = 0;
+
+Ypp *Ypp::get()
+{
+ if (!ypp)
+ ypp = new Ypp();
+ return ypp;
+}
+
+void Ypp::finish()
+{
+ delete ypp; ypp = NULL;
+}
+
+// Ypp::Impl declaration, to expose some methods for usage
+struct Ypp::Impl
+{
+public:
+ Impl();
+ ~Impl();
+
+ const Repository *getRepository (int nb);
+ int getRepository (const std::string &zyppId);
+ Disk *getDisk();
+
+ // for Packages
+ bool acceptLicense (Ypp::Package *package, const std::string &license);
+ void packageModified (Ypp::Package *package);
+
+ // for Pools
+ void addPool (Pool::Impl *pool);
+ void removePool (Pool::Impl *pool);
+ GSList *getPackages (Package::Type type);
+
+private:
+ bool resolveProblems();
+ Node *addCategory (Package::Type type, const std::string &str, Package *package);
+ void polishCategories (Ypp::Package::Type type);
+
+ void startTransactions();
+ void finishTransactions();
+
+ friend class Ypp;
+ GSList *packages [Package::TOTAL_TYPES]; // primitive pools
+ StringTree *categories [Package::TOTAL_TYPES];
+ GSList *repos;
+ Disk *disk;
+ Interface *interface;
+ GSList *pools;
+ bool inTransaction;
+ GSList *transactions;
+};
+
+//** Package
+
+struct Ypp::Package::Impl
+{
+ Impl (ZyppSelectable sel)
+ : zyppSel (sel), index (-1), availableVersions (NULL), installedVersion (NULL), is3D (false)
+ {
+ // don't use getAvailableVersion(0) for hasUpgrade() has its inneficient.
+ // let's just cache candidate() at start, which should point to the newest version.
+ hasUpgrade = false;
+ ZyppObject candidate = zyppSel->candidateObj();
+ ZyppObject installed = zyppSel->installedObj();
+ if (!!candidate && !!installed)
+ hasUpgrade = zypp::Edition::compare (candidate->edition(), installed->edition()) > 0;
+ setUnmodified();
+ }
+
+ ~Impl()
+ {
+ delete installedVersion;
+ for (GSList *i = availableVersions; i; i = i->next)
+ delete ((Version *) i->data);
+ g_slist_free (availableVersions);
+ }
+
+ inline bool isModified()
+ { return curStatus != zyppSel->status(); }
+ inline void setUnmodified()
+ { curStatus = zyppSel->status(); }
+
+ std::string name, summary;
+ ZyppSelectable zyppSel;
+ int index; // used for Pools syncing
+ Type type;
+ Ypp::Node *category;
+ GSList *availableVersions;
+ Version *installedVersion;
+ bool hasUpgrade;
+ bool is3D;
+ zypp::ui::Status curStatus; // so we know if resolver touched it
+};
+
+Ypp::Package::Package (Ypp::Package::Impl *impl)
+: impl (impl)
+{}
+Ypp::Package::~Package()
+{ delete impl; }
+
+Ypp::Package::Type Ypp::Package::type()
+{ return impl->type; }
+
+const std::string &Ypp::Package::name()
+{
+ std::string &ret = impl->name;
+ if (ret.empty()) {
+ ZyppSelectable sel = impl->zyppSel;
+ ZyppObject obj = sel->theObj();
+ switch (impl->type) {
+ case PATTERN_TYPE:
+ ret = obj->summary();
+ case LANGUAGE_TYPE:
+ ret = obj->description();
+ default:
+ ret = sel->name();
+ }
+ }
+ return ret;
+}
+
+const std::string &Ypp::Package::summary()
+{
+ std::string &ret = impl->summary;
+ if (ret.empty()) {
+ if (impl->type == PACKAGE_TYPE)
+ ret = impl->zyppSel->theObj()->summary();
+ }
+ return ret;
+}
+
+std::string Ypp::Package::description()
+{
+ ZyppObject object = impl->zyppSel->theObj();
+ std::string text = object->description(), br = "<br>";
+ if (impl->type == PACKAGE_TYPE) {
+ // if it has this header, then it is HTML
+ const char *header = "<!-- DT:Rich -->", header_len = 16;
+ if (!text.compare (0, header_len, header, header_len))
+ text.erase (0, header_len);
+ else {
+ // add breakline for every double one...
+ YGUtils::replace (text, "\n\n", 2, "<br>");
+/* std::string::size_type i = 0;
+ while ((i = text.find ("\n\n", i)) < std::string::npos) {
+ text.erase (i, 2); // remove it, so we don't trip on it again
+ text.insert (i, "<br>");
+ }*/
+ }
+
+ ZyppPackage package = tryCastToZyppPkg (object);
+ std::string url = package->url(), license = package->license();
+ if (!url.empty())
+ text += br + _("Website: ") + url;
+ if (!license.empty())
+ text += br + _("License: ") + license;
+ }
+ text += br + _("Size: ") + object->size().asString();
+ return text;
+}
+
+std::string Ypp::Package::filelist()
+{
+ std::string text;
+ ZyppObject object = impl->zyppSel->installedObj();
+ ZyppPackage package = tryCastToZyppPkg (object);
+ if (package) {
+ StringTree tree (YGUtils::strcmp, '/');
+
+ const std::list std::string &filesList = package->filenames();
+ for (std::list std::string::const_iterator it = filesList.begin();
+ it != filesList.end(); it++)
+ tree.add (*it);
+
+ struct inner {
+ static std::string getPath (GNode *node)
+ {
+ Node *yNode = (Node *) node->data;
+ if (!yNode)
+ return std::string();
+ return getPath (node->parent) + "/" + yNode->name;
+ }
+ static bool hasNextLeaf (GNode *node)
+ {
+ GNode *i;
+ for (i = node->next; i; i = i->next)
+ if (!i->children)
+ return true;
+ return false;
+ }
+ static bool hasPrevLeaf (GNode *node)
+ {
+ GNode *i;
+ for (i = node->prev; i; i = i->prev)
+ if (!i->children)
+ return true;
+ return false;
+ }
+ static gboolean traverse (GNode *node, void *_data)
+ {
+ Node *yNode = (Node *) node->data;
+ if (yNode) {
+ std::string *str = (std::string *) _data;
+ if (!hasPrevLeaf (node)) {
+ std::string path = getPath (node->parent);
+ *str += "<a href=" + path + ">" + path + "</a>";
+ *str += "<blockquote>";
+ }
+ else
+ *str += ", ";
+ *str += yNode->name;
+
+ if (!hasNextLeaf (node))
+ *str += "</blockquote>";
+ }
+ return FALSE;
+ }
+ };
+ g_node_traverse (tree.root, G_LEVEL_ORDER, G_TRAVERSE_LEAFS, -1,
+ inner::traverse, (void *) &text);
+ }
+ return text;
+}
+
+std::string Ypp::Package::changelog()
+{
+ string text;
+ ZyppObject object = impl->zyppSel->installedObj();
+ ZyppPackage package = tryCastToZyppPkg (object);
+ if (package) {
+ const std::list zypp::ChangelogEntry &changelogList = package->changelog();
+ for (std::list zypp::ChangelogEntry::const_iterator it = changelogList.begin();
+ it != changelogList.end(); it++) {
+ std::string author = it->author(), changes = it->text();
+ YGUtils::escapeMarkup (author);
+ YGUtils::escapeMarkup (changes);
+ YGUtils::replace (changes, "\n", 1, "<br>");
+ text += it->date().asString() + author + ":<br>"
+ + "<blockquote>" + changes + "</blockqute>";
+ }
+ }
+ return text;
+}
+
+std::string Ypp::Package::authors()
+{
+fprintf (stderr, "authors %s\n", name().c_str());
+ std::string text;
+ ZyppObject object = impl->zyppSel->theObj();
+ ZyppPackage package = tryCastToZyppPkg (object);
+ if (package) {
+ std::string packager = package->packager(), authors;
+ YGUtils::escapeMarkup (packager);
+ const std::list std::string &authorsList = package->authors();
+ for (std::list std::string::const_iterator it = authorsList.begin();
+ it != authorsList.end(); it++) {
+ std::string author = *it;
+ YGUtils::escapeMarkup (author);
+ if (!authors.empty())
+ authors += "<br>";
+ authors += author;
+fprintf (stderr, "\t add author %s\n", author.c_str());
+ }
+ // Some packagers put Authors over the Descriptions field. This seems to be rare
+ // on, so I'm not even going to bother.
+
+ if (!packager.empty())
+ text += _("Packaged by:") + ("<blockquote>" + packager) + "</blockquote>";
+ if (!authors.empty())
+ text += _("Developed by:") + ("<blockquote>" + authors) + "</blockquote>";
+ }
+ return text;
+}
+
+std::string Ypp::Package::provides()
+{
+ std::string text;
+ ZyppObject object = impl->zyppSel->theObj();
+ const zypp::CapSet &capSet = object->dep (zypp::Dep::PROVIDES);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++) {
+ if (!text.empty())
+ text += "\n";
+ text += it->asString();
+ }
+ return text;
+}
+
+std::string Ypp::Package::requires()
+{
+ std::string text;
+ ZyppObject object = impl->zyppSel->theObj();
+ const zypp::CapSet &capSet = object->dep (zypp::Dep::REQUIRES);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++) {
+ if (!text.empty())
+ text += "\n";
+ text += it->asString();
+ }
+ return text;
+}
+
+Ypp::Node *Ypp::Package::category()
+{
+ return impl->category;
+}
+
+bool Ypp::Package::is3D()
+{
+ return impl->is3D;
+}
+
+
+bool Ypp::Package::isInstalled()
+{
+ return impl->zyppSel->hasInstalledObj();
+}
+
+bool Ypp::Package::hasUpgrade()
+{
+ return impl->hasUpgrade;
+}
+
+bool Ypp::Package::isLocked()
+{
+ zypp::ui::Status status = impl->zyppSel->status();
+ return status == zypp::ui::S_Taboo || status == zypp::ui::S_Protected;
+}
+
+bool Ypp::Package::toInstall (int *nb)
+{
+ if (nb) {
+ ZyppObject candidate = impl->zyppSel->candidateObj();
+ for (int i = 0; getAvailableVersion (i); i++) {
+ const Version *version = getAvailableVersion (i);
+ ZyppObject i_obj = (ZyppObjectPtr) version->impl;
+ if (i_obj == candidate) {
+ *nb = i;
+ break;
+ }
+ }
+ }
+ return impl->zyppSel->toInstall();
+}
+
+bool Ypp::Package::toRemove()
+{
+ return impl->zyppSel->toDelete();
+}
+
+bool Ypp::Package::isModified()
+{
+ return impl->zyppSel->toModify();
+}
+
+bool Ypp::Package::isAuto()
+{
+ zypp::ui::Status status = impl->zyppSel->status();
+ return status == zypp::ui::S_AutoInstall || status == zypp::ui::S_AutoUpdate ||
+ status == zypp::ui::S_AutoDel;
+}
+
+void Ypp::Package::install (int nb)
+{
+ if (isLocked())
+ return;
+ if (!impl->zyppSel->hasLicenceConfirmed())
+ {
+ const std::string &license = impl->zyppSel->candidateObj()->licenseToConfirm();
+ if (!license.empty())
+ if (!ypp->impl->acceptLicense (this, license))
+ return;
+ impl->zyppSel->setLicenceConfirmed();
+ }
+
+ zypp::ui::Status status = impl->zyppSel->status();
+ switch (status) {
+ // not applicable
+ case zypp::ui::S_Protected:
+ case zypp::ui::S_Taboo:
+ case zypp::ui::S_Install:
+ case zypp::ui::S_Update:
+ break;
+ // undo
+ case zypp::ui::S_Del:
+ status = zypp::ui::S_KeepInstalled;
+ break;
+ // nothing to do about it
+ case zypp::ui::S_AutoDel:
+ break;
+ // action
+ case zypp::ui::S_NoInst:
+ case zypp::ui::S_AutoInstall:
+ status = zypp::ui::S_Install;
+ break;
+ case zypp::ui::S_KeepInstalled:
+ case zypp::ui::S_AutoUpdate:
+ status = zypp::ui::S_Update;
+ break;
+ }
+
+ impl->zyppSel->set_status (status);
+ if (toInstall()) {
+ const Version *version = getAvailableVersion (nb);
+ ZyppObject candidate = (ZyppObjectPtr) version->impl;
+ if (!impl->zyppSel->setCandidate (candidate)) {
+ y2warning ("Error: Could not set package '%s' candidate to '%s'\n",
+ name().c_str(), version->number.c_str());
+ return;
+ }
+ }
+
+ ypp->impl->packageModified (this);
+}
+
+void Ypp::Package::remove()
+{
+ zypp::ui::Status status = impl->zyppSel->status();
+ switch (status) {
+ // not applicable
+ case zypp::ui::S_Protected:
+ case zypp::ui::S_Taboo:
+ case zypp::ui::S_NoInst:
+ case zypp::ui::S_Del:
+ break;
+ // undo
+ case zypp::ui::S_Install:
+ status = zypp::ui::S_NoInst;
+ break;
+ // nothing to do about it
+ case zypp::ui::S_AutoInstall:
+ case zypp::ui::S_AutoUpdate:
+ break;
+ case zypp::ui::S_Update:
+ status = zypp::ui::S_KeepInstalled;
+ break;
+ // action
+ case zypp::ui::S_KeepInstalled:
+ case zypp::ui::S_AutoDel:
+ status = zypp::ui::S_Del;
+ break;
+ }
+
+ impl->zyppSel->set_status (status);
+ ypp->impl->packageModified (this);
+}
+
+void Ypp::Package::undo()
+{
+ zypp::ui::Status status = impl->zyppSel->status();
+ switch (status) {
+ // not applicable
+ case zypp::ui::S_Protected:
+ case zypp::ui::S_Taboo:
+ case zypp::ui::S_NoInst:
+ case zypp::ui::S_KeepInstalled:
+ break;
+
+ // undo
+ case zypp::ui::S_Install:
+ status = zypp::ui::S_NoInst;
+ break;
+ case zypp::ui::S_Update:
+ case zypp::ui::S_Del:
+ status = zypp::ui::S_KeepInstalled;
+ break;
+
+ // for auto status, undo them by locking them
+ case zypp::ui::S_AutoInstall:
+ status = zypp::ui::S_Taboo;
+ break;
+ case zypp::ui::S_AutoUpdate:
+ case zypp::ui::S_AutoDel:
+ status = zypp::ui::S_Protected;
+ break;
+ }
+
+ impl->zyppSel->set_status (status);
+ ypp->impl->packageModified (this);
+}
+
+void Ypp::Package::lock (bool lock)
+{
+ undo();
+
+ zypp::ui::Status status;
+ if (lock)
+ status = isInstalled() ? zypp::ui::S_Protected : zypp::ui::S_Taboo;
+ else
+ status = isInstalled() ? zypp::ui::S_KeepInstalled : zypp::ui::S_NoInst;
+
+ impl->zyppSel->set_status (status);
+ ypp->impl->packageModified (this);
+}
+
+static Ypp::Package::Version *constructVersion (ZyppObject object)
+{
+ Ypp::Package::Version *version = new Ypp::Package::Version();
+ version->number = object->edition().version();
+ version->repo = ypp->impl->getRepository (object->repository().info().alias());
+ version->cmp = 0;
+ version->impl = (void *) get_pointer (object);
+ return version;
+}
+
+const Ypp::Package::Version *Ypp::Package::getInstalledVersion()
+{
+ if (!impl->installedVersion) {
+ const ZyppObject installedObj = impl->zyppSel->installedObj();
+ if (installedObj)
+ impl->installedVersion = constructVersion (installedObj);
+ }
+ return impl->installedVersion;
+}
+
+const Ypp::Package::Version *Ypp::Package::getAvailableVersion (int nb)
+{
+ if (!impl->availableVersions) {
+ const ZyppObject installedObj = impl->zyppSel->installedObj();
+ for (zypp::ui::Selectable::available_iterator it = impl->zyppSel->availableBegin();
+ it != impl->zyppSel->availableEnd(); it++) {
+ Version *version = constructVersion (*it);
+ if (installedObj)
+ version->cmp = zypp::Edition::compare ((*it)->edition(), installedObj->edition());
+ impl->availableVersions = g_slist_append (impl->availableVersions, version);
+ }
+ struct inner {
+ static gint version_compare (gconstpointer pa, gconstpointer pb)
+ {
+ ZyppObjectPtr a = (ZyppObjectPtr) ((Version *) pa)->impl;
+ ZyppObjectPtr b = (ZyppObjectPtr) ((Version *) pb)->impl;
+ // swapped arguments, as we want them sorted from newer to older
+ return zypp::Edition::compare (b->edition(), a->edition());
+ }
+ };
+ impl->availableVersions = g_slist_sort (impl->availableVersions,
+ inner::version_compare);
+ }
+ return (Version *) g_slist_nth_data (impl->availableVersions, nb);
+}
+
+bool Ypp::Package::isOnRepository (int repo_nb)
+{
+ int i;
+ for (i = 0; getAvailableVersion (i); i++)
+ if (getAvailableVersion (i)->repo == repo_nb)
+ return true;
+ // if there are no availables, answer yes to all repos
+ return i == 0;
+}
+
+//** Query
+
+struct Ypp::Query::Impl
+{
+ template <typename T>
+ struct Key
+ {
+ Key()
+ : defined (false)
+ {}
+ void define (T v)
+ {
+ defined = true;
+ value = v;
+ }
+ bool is (const T &v) const
+ {
+// if (!defined) return true;
+ return value == v;
+ }
+ bool defined;
+ T value;
+ };
+
+ Key Ypp::Package::Type type;
+ Key std::string > name;
+ Key category;
+ Key <bool> isInstalled;
+ Key <bool> hasUpgrade;
+ Key <bool> isModified;
+ Key onRepositories;
+
+ Impl()
+ {}
+
+ bool match (Package *package)
+ {
+ bool match = true;
+// we must avoid passing values by copy, as well as zypp calls
+ if (match && type.defined)
+ match = type.is (package->type());
+ if (match && isInstalled.defined)
+ match = isInstalled.is (package->isInstalled());
+ if (match && hasUpgrade.defined)
+ match = hasUpgrade.is (package->hasUpgrade());
+ if (match && isModified.defined)
+ match = isModified.is (package->isModified());
+ if (match && name.defined) {
+ const std::list std::string &names = name.value;
+ std::list std::string::const_iterator it;
+ for (it = names.begin(); it != names.end(); it++) {
+ if (!YGUtils::contains (package->name(), *it) &&
+ !YGUtils::contains (package->summary(), *it) &&
+ !YGUtils::contains (package->provides(), *it)) {
+ match = false;
+ break;
+ }
+ }
+ }
+ if (match && category.defined) {
+ Ypp::Node *query_category = category.value;
+ Ypp::Node *pkg_category = package->category();
+ GNode *node = (GNode *) query_category->impl;
+ if (!g_node_find (node, G_PRE_ORDER, G_TRAVERSE_ALL, pkg_category))
+ match = false;
+ }
+ if (match && onRepositories.defined) {
+ const std::list <int> &repos = onRepositories.value;
+ std::list <int>::const_iterator it;
+ for (it = repos.begin(); it != repos.end(); it++)
+ if (package->isOnRepository (*it))
+ break;
+ match = it != repos.end();
+ }
+ return match;
+ }
+};
+
+Ypp::Query::Query (Ypp::Package::Type type)
+{
+ impl = new Impl();
+ impl->type.define (type);
+}
+Ypp::Query::~Query()
+{ delete impl; }
+
+void Ypp::Query::setName (std::string value)
+{ impl->name.define (YGUtils::splitString (value, ' ')); }
+void Ypp::Query::setCategory (Ypp::Node *value)
+{ impl->category.define (value); }
+void Ypp::Query::setIsInstalled (bool value)
+{ impl->isInstalled.define (value); }
+void Ypp::Query::setHasUpgrade (bool value)
+{ impl->hasUpgrade.define (value); }
+void Ypp::Query::setIsModified (bool value)
+{ impl->isModified.define (value); }
+void Ypp::Query::setRepositories (std::list <int> value)
+{ impl->onRepositories.define (value); }
+
+//** Pool
+
+struct Ypp::Pool::Impl
+{
+Query *query;
+GSList *packages;
+Pool::Listener *listener;
+
+ Impl (Query *query)
+ : query (query), listener (NULL)
+ {
+ packages = buildPool (query);
+fprintf (stderr, "created pool, adding to Ypp\n");
+ ypp->impl->addPool (this);
+ }
+
+ ~Impl()
+ {
+fprintf (stderr, "destroyed pool, removing from Ypp\n");
+ ypp->impl->removePool (this);
+ delete query;
+ g_slist_free (packages);
+ }
+
+ void packageModified (Package *package)
+ {
+ bool match = query->impl->match (package);
+ int cmp = 1;
+ GSList *i;
+ for (i = packages; i; i = i->next) {
+ Package *pkg = (Package *) i->data;
+ if (pkg->impl->index == package->impl->index)
+ cmp = 0;
+ if (pkg->impl->index >= package->impl->index)
+ break;
+ }
+ if (cmp == 0) {
+ if (match) { // modified
+fprintf (stderr, "pool (%d) - touched: %s\n", g_slist_length (packages), package->name().c_str());
+ if (listener)
+ listener->entryChanged ((Iter) i, package);
+ }
+ else { // removed
+fprintf (stderr, "pool (%d) - remove: %s\n", g_slist_length (packages), package->name().c_str());
+ if (listener)
+ listener->entryDeleted ((Iter) i, package);
+ packages = g_slist_delete_link (packages, i);
+ }
+ }
+ else {
+ if (match) { // inserted
+fprintf (stderr, "pool (%d) - insert: %s\n", g_slist_length (packages), package->name().c_str());
+ if (i == NULL) {
+ packages = g_slist_append (packages, (gpointer) package);
+ i = g_slist_last (packages);
+ }
+ else {
+ packages = g_slist_insert_before (packages, i, (gpointer) package);
+ int index = g_slist_position (packages, i) - 1;
+ i = g_slist_nth (packages, index);
+ }
+ if (listener)
+ listener->entryInserted ((Iter) i, package);
+ }
+ }
+ }
+
+private:
+ static GSList *buildPool (Query *query) // at construction
+ {
+long time1 = time(NULL);
+fprintf (stderr, "build pool...\n");
+ GSList *pool = NULL;
+ GSList *entire_pool = ypp->impl->getPackages (query->impl->type.value);
+ int index = 0;
+ for (GSList *i = entire_pool; i; i = i->next) {
+ Package *pkg = (Package *) i->data;
+ if (query->impl->match (pkg))
+ pool = g_slist_append (pool, i->data);
+ if (pkg->impl->index == -1)
+ pkg->impl->index = index++;
+ }
+fprintf (stderr, "delta time: %ld\n", time(NULL)-time1);
+ return pool;
+ }
+};
+
+Ypp::Pool::Pool (Query *query)
+{ impl = new Impl (query); }
+Ypp::Pool::~Pool()
+{ delete impl; }
+
+Ypp::Pool::Iter Ypp::Pool::getFirst()
+{ return impl->packages; }
+
+Ypp::Pool::Iter Ypp::Pool::getNext (Ypp::Pool::Iter iter)
+{ return ((GSList *) iter)->next; }
+
+Ypp::Package *Ypp::Pool::get (Ypp::Pool::Iter iter)
+{ return (Ypp::Package *) ((GSList *) iter)->data; }
+
+int Ypp::Pool::getIndex (Ypp::Pool::Iter iter)
+{ return g_slist_position (impl->packages, (GSList *) iter); }
+
+Ypp::Pool::Iter Ypp::Pool::getIter (int index)
+{ return g_slist_nth (impl->packages, index); }
+
+void Ypp::Pool::setListener (Ypp::Pool::Listener *listener)
+{ impl->listener = listener; }
+
+//** Misc
+
+struct Ypp::Disk::Impl
+{
+Ypp::Disk::Listener *listener;
+GSList *partitions;
+
+ Impl()
+ : partitions (NULL)
+ {
+ if (zypp::getZYpp()->diskUsage().empty())
+ zypp::getZYpp()->setPartitions (
+ zypp::DiskUsageCounter::detectMountPoints());
+ }
+
+ ~Impl()
+ {
+ clearPartitions();
+ }
+
+ void packageModified (Package *package)
+ {
+ clearPartitions();
+ if (listener)
+ listener->update();
+ }
+
+ void clearPartitions()
+ {
+ for (GSList *i = partitions; i; i = i->next)
+ delete ((Partition *) i->data);
+ g_slist_free (partitions);
+ partitions = NULL;
+ }
+
+ const Partition *getPartition (int nb)
+ {
+ if (!partitions) {
+ typedef zypp::DiskUsageCounter::MountPoint ZyppDu;
+ typedef zypp::DiskUsageCounter::MountPointSet ZyppDuSet;
+ typedef zypp::DiskUsageCounter::MountPointSet::iterator ZyppDuSetIterator;
+
+ ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
+ for (ZyppDuSetIterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
+ if (!it->readonly) {
+ // partition fields: dir, used_size, total_size (size on Kb)
+ Ypp::Disk::Partition *partition = new Partition();
+ partition->path = it->dir;
+ partition->used = it->pkg_size;
+ partition->total = it->total_size;
+ partition->used_str =
+ zypp::ByteCount (partition->used, zypp::ByteCount::K).asString();
+ partition->total_str =
+ zypp::ByteCount (partition->total, zypp::ByteCount::K).asString();
+ partitions = g_slist_append (partitions, (gpointer) partition);
+ }
+ }
+ }
+ return (Partition *) g_slist_nth_data (partitions, nb);
+ }
+};
+
+Ypp::Disk::Disk()
+{ impl = new Impl(); }
+Ypp::Disk::~Disk()
+{ delete impl; }
+
+void Ypp::Disk::setListener (Ypp::Disk::Listener *listener)
+{ impl->listener = listener; }
+
+const Ypp::Disk::Partition *Ypp::Disk::getPartition (int nb)
+{ return impl->getPartition (nb); }
+
+Ypp::Node *Ypp::getFirstCategory (Ypp::Package::Type type)
+{
+ return impl->categories[type]->getFirst();
+}
+
+Ypp::Node *Ypp::Node::next()
+{
+ GNode *ret = ((GNode *) impl)->next;
+ if (ret) return (Ypp::Node *) ret->data;
+ return NULL;
+}
+
+Ypp::Node *Ypp::Node::child()
+{
+ GNode *ret = ((GNode *) impl)->children;
+ if (ret) return (Ypp::Node *) ret->data;
+ return NULL;
+}
+
+struct CatConversor {
+ const char *from, *to;
+};
+static const CatConversor catConversor[] = {
+ { "Amusements/Games/3D", "Games/Action" },
+ { "Amusements/Games/Board/Puzzle", "Games/Logic" },
+ { "Amusements/Games/Board/Card", "Games/Card" },
+ { "Amusements/Games", "Games" },
+ { "Amusements", "Games" },
+ { "Applications/Publishing", "Office" },
+ { "Applications/Internet", "Network" },
+ { "Applications", "" },
+ { "Development/C", "Development/Libraries/C and C++" },
+ { "Development/Python", "Development/Libraries/Python" },
+ { "Development/Libraries/C", "Development/Libraries/C and C++" },
+ { "Libraries", "Development/Libraries" },
+ { "Productivity/Multimedia/Player", "Multimedia/Sound/Players" },
+ { "Productivity/Multimedia/Audio", "Multimedia/Sound/Players" },
+ { "Video", "Multimedia/Video" },
+ { "Productivity/Multimedia", "Multimedia" },
+ { "Productivity/Graphics", "Multimedia/Graphics" },
+ { "Productivity/Networking", "Network" },
+ { "Productivity/Network", "Network" },
+ { "Productivity/Office", "Office" },
+ { "Productivity/Publishing", "Office/Publishing" },
+ { "Productivity/Telephony", "Network/Telephony" },
+ { "Productivity", "Utilities" },
+ { "System/Emulators", "Emulators" },
+ { "System/GUI", "Utilities/GUI" },
+ { "System/Video", "Emulators" },
+ { "System/Libraries", "Development/Libraries/C and C++/System" },
+ { "X11/Applications/Multimedia", "Multimedia" },
+ { "X11/GNOME/Multimedia", "Multimedia" },
+ { "X11/Applications", "Utilities/GUI" },
+};
+#define CAT_CONVERSOR_SIZE (sizeof (catConversor)/sizeof (CatConversor))
+struct TypoConversor {
+ const char *from, *to, len;
+};
+static const TypoConversor catTypos[] = {
+ { "Others", "Other", 6 }, { "Utilites", "Utilities", 8 },
+ { "AOLInstantMessenge", "AOLInstantMessenger", 18 },
+ { "Library", "Libraries", 7 }, { "Libs", "Libraries", 4 },
+};
+#define CAT_TYPOS_SIZE (sizeof (catTypos)/sizeof (TypoConversor))
+
+Ypp::Node *Ypp::Impl::addCategory (Ypp::Package::Type type,
+ const std::string &category_str, Package *pkg)
+{
+ struct inner {
+ static int cmp (const char *a, const char *b)
+ {
+ // Other group should always go as last
+ if (!strcmp (a, "Other"))
+ return !strcmp (b, "Other") ? 0 : 1;
+ if (!strcmp (b, "Other"))
+ return -1;
+ return YGUtils::strcmp (a, b);
+ }
+
+ // Package categories guide-line don't seem to be enforced, some categories
+ // are duplicated, or don't make much sense. Let's try to cut on that.
+
+ static std::string treatCategory (const std::string &category, Package *pkg)
+ {
+ std::string ret (category);
+
+ // typos (end group only)
+ for (unsigned int c = 0; c < CAT_TYPOS_SIZE; c++) {
+ const char *from = catTypos[c].from, from_len = catTypos[c].len;
+ int ret_index = ret.length() - from_len;
+
+ if (ret_index >= 0 && ret.compare (ret_index, from_len, from, from_len) == 0) {
+ const char *to = catTypos[c].to;
+ ret.erase (ret_index);
+ ret.append (to);
+ break;
+ }
+ }
+
+ for (unsigned int c = 0; c < CAT_CONVERSOR_SIZE; c++) {
+ const char *from = catConversor[c].from;
+ unsigned int i;
+ for (i = 0; from[i] && i < ret.length(); i++)
+ if (from[i] != ret[i])
+ break;
+ if (!from[i] && (i == ret.length() || ret[i] == '/')) {
+ const char *to = catConversor[c].to;
+ ret.erase (0, i);
+ ret.insert (0, to);
+ if (c == 0 && pkg)
+ pkg->impl->is3D = true;
+ break;
+ }
+ }
+ return ret;
+ }
+ };
+
+ if (!categories[type])
+ categories[type] = new StringTree (inner::cmp, '/');
+ if (type == Package::PACKAGE_TYPE)
+ return categories[type]->add (inner::treatCategory (category_str, pkg));
+ else
+ return categories[type]->add (category_str);
+}
+
+void Ypp::Impl::polishCategories (Ypp::Package::Type type)
+{
+ // some treatment on categories
+ // Put all packages under a node (as opposite to packages on a leaf) to
+ // the Other category.
+ if (type == Package::PACKAGE_TYPE) {
+ GSList *pool = ypp->impl->getPackages (type);
+ for (GSList *i = pool; i; i = i->next) {
+ Package *pkg = (Package *) i->data;
+ Ypp::Node *ynode = pkg->category();
+ if (ynode->child()) {
+ GNode *node = (GNode *) ynode->impl;
+ GNode *last = g_node_last_child (node);
+ if (((Ypp::Node *) last->data)->name == "Other")
+ pkg->impl->category = (Ypp::Node *) last->data;
+ else {
+ // must create a "Other" node
+ fprintf (stderr, "creating Other\n");
+ Ypp::Node *yN = new Ypp::Node();
+ GNode *n = g_node_new ((void *) yN);
+ yN->name = "Other";
+ yN->impl = (void *) n;
+ g_node_insert_before (node, NULL, n);
+ pkg->impl->category = yN;
+ }
+ }
+ }
+ }
+}
+
+//** Ypp top methods & internal connections
+
+Ypp::Impl::Impl()
+: repos (NULL), disk (NULL), interface (NULL), pools (NULL),
+ inTransaction (false), transactions (NULL)
+{
+ for (int i = 0; i < Package::TOTAL_TYPES; i++) {
+ packages[i] = NULL;
+ categories[i] = NULL;
+ }
+}
+
+Ypp::Impl::~Impl()
+{
+ struct inner {
+ static void free_package (void *data, void *_data)
+ { delete ((Package *) data); }
+ static void free_repo (void *data, void *_data)
+ { delete ((Repository *) data); }
+ };
+
+ for (int t = 0; t < Package::TOTAL_TYPES; t++) {
+ g_slist_foreach (packages[t], inner::free_package, NULL);
+ g_slist_free (packages[t]);
+ delete categories[t];
+ }
+
+ g_slist_foreach (repos, inner::free_repo, NULL);
+ g_slist_free (repos);
+
+ // don't delete pools as they don't actually belong to Ypp, just listeners
+ g_slist_free (pools);
+ delete disk;
+}
+
+const Ypp::Repository *Ypp::Impl::getRepository (int nb)
+{
+ if (!repos) {
+ zypp::RepoManager manager;
+ std::list zypp::RepoInfo zrepos = manager.knownRepositories();
+ for (std::list zypp::RepoInfo::const_iterator it = zrepos.begin();
+ it != zrepos.end(); it++) {
+ if (it->enabled()) {
+ Repository *repo = new Repository();
+ repo->name = it->name();
+ repo->alias = it->alias();
+ repos = g_slist_append (repos, repo);
+ }
+ }
+ }
+ return (Repository *) g_slist_nth_data (repos, nb);
+}
+
+int Ypp::Impl::getRepository (const std::string &alias)
+{
+ for (int i = 0; getRepository (i); i++)
+ if (getRepository (i)->alias == alias)
+ return i;
+ return -1; /*error*/
+}
+
+Ypp::Disk *Ypp::Impl::getDisk()
+{
+ if (!disk)
+ disk = new Disk();
+ return disk;
+}
+
+bool Ypp::Impl::acceptLicense (Ypp::Package *package, const std::string &license)
+{
+ if (interface)
+ interface->acceptLicense (package, license);
+ return false;
+}
+
+Ypp::Problem::Solution *Ypp::Problem::getSolution (int nb)
+{
+ return (Ypp::Problem::Solution *) g_slist_nth_data ((GSList *) impl, nb);
+}
+
+bool Ypp::Impl::resolveProblems()
+{
+ zypp::Resolver_Ptr zResolver = zypp::getZYpp()->resolver();
+ bool resolved = false;
+ while (true) {
+ if (zResolver->resolvePool()) {
+ resolved = true;
+ break;
+ }
+ zypp::ResolverProblemList zProblems = zResolver->problems();
+ if ((resolved = zProblems.empty()))
+ break;
+
+ if (!interface)
+ break;
+
+ std::list problems;
+ for (zypp::ResolverProblemList::iterator it = zProblems.begin();
+ it != zProblems.end(); it++) {
+ Problem *problem = new Problem();
+ problem->description = (*it)->description();
+ problem->details = (*it)->details();
+ GSList *solutions = NULL;
+ zypp::ProblemSolutionList zSolutions = (*it)->solutions();
+ for (zypp::ProblemSolutionList::iterator jt = zSolutions.begin();
+ jt != zSolutions.end(); jt++) {
+ Problem::Solution *solution = new Problem::Solution();
+ solution->description = (*jt)->description();
+ solution->details = (*jt)->details();
+ solution->apply = false;
+ solution->impl = (void *) get_pointer (*jt);
+ solutions = g_slist_append (solutions, solution);
+ }
+ problem->impl = (void *) solutions;
+ problems.push_back (problem);
+ }
+
+ resolved = interface->resolveProblems (problems);
+
+ zypp::ProblemSolutionList choices;
+ for (std::list ::iterator it = problems.begin();
+ it != problems.end(); it++) {
+ for (int i = 0; (*it)->getSolution (i); i++) {
+ Problem::Solution *solution = (*it)->getSolution (i);
+ if (resolved && solution->apply)
+ choices.push_back ((zypp::ProblemSolution *) solution->impl);
+ delete solution;
+ }
+ delete *it;
+ }
+
+ if (resolved)
+ zResolver->applySolutions (choices);
+ else
+ break;
+ }
+
+ if (!resolved)
+ zResolver->undo();
+ return resolved;
+}
+
+void Ypp::Impl::packageModified (Ypp::Package *package)
+{
+ // notify listeners of package change
+ for (GSList *i = pools; i; i = i->next) {
+fprintf (stderr, "ypp: informing pool of package modified\n");
+ ((Pool::Impl *) i->data)->packageModified (package);
+ }
+ if (disk)
+ disk->impl->packageModified (package);
+ if (interface)
+ interface->packageModified (package);
+
+ transactions = g_slist_append (transactions, package);
+ if (!inTransaction)
+ finishTransactions();
+}
+
+void Ypp::Impl::startTransactions()
+{
+ inTransaction = true;
+}
+
+void Ypp::Impl::finishTransactions()
+{
+ inTransaction = true;
+ bool resolved = resolveProblems();
+ if (resolved) {
+ // resolver won't tell us what changed -- tell pools about Auto packages
+ for (GSList *p = packages [Ypp::Package::PACKAGE_TYPE]; p; p = p->next) {
+ Ypp::Package *pkg = (Ypp::Package *) p->data;
+ if (pkg->impl->isModified()) {
+ for (GSList *i = pools; i; i = i->next)
+ ((Pool::Impl *) i->data)->packageModified (pkg);
+ pkg->impl->setUnmodified();
+ }
+ }
+ }
+ else {
+ // user canceled resolver -- undo all
+ for (GSList *i = transactions; i; i = i->next)
+ ((Ypp::Package *) i->data)->undo();
+ }
+ g_slist_free (transactions);
+ transactions = NULL;
+ inTransaction = false;
+}
+
+void Ypp::Impl::addPool (Pool::Impl *pool)
+{ fprintf (stderr, "ypp: adding pool\n"); pools = g_slist_append (pools, pool); }
+void Ypp::Impl::removePool (Pool::Impl *pool)
+{ fprintf (stderr, "ypp: removing pool\n"); pools = g_slist_remove (pools, pool); }
+
+#if 0
+// using auxiliary GSequence tree -- not yet shiped by Glib :X
+// in any case, a sort merge is very fast, as packages are more or less
+// sorted anyway...
+GSList *Ypp::Impl::getPackages (Ypp::Package::Type type)
+{
+ if (!packages[type]) {
+ // auxiliary for efficient alphabetic sorting
+ GSequence *pool = g_sequence_new (NULL);
+ struct inner {
+ static gint compare (gconstpointer _a, gconstpointer _b, gpointer _data)
+ {
+ Package *a = (Package *) _a;
+ Package *b = (Package *) _b;
+ return YGUtils::strcmp (a->name().c_str(), b->name().c_str());
+ }
+/* static void pool_foreach (gpointer data, gpointer _list)
+ {
+ GSList **list = (GSList **) _list;
+ *list = g_slist_append (*list, data);
+ }*/
+ };
+
+ ZyppPool::const_iterator it, end;
+ switch (type)
+ {
+ case Package::PACKAGE_TYPE:
+ it = zyppPool().byKindBegin zypp::Package();
+ end = zyppPool().byKindEnd zypp::Package();
+ break;
+ case Package::PATTERN_TYPE:
+ it = zyppPool().byKindBegin zypp::Pattern();
+ end = zyppPool().byKindEnd zypp::Pattern();
+ break;
+ case Package::LANGUAGE_TYPE:
+ it = zyppPool().byKindBegin zypp::Language();
+ end = zyppPool().byKindEnd zypp::Language();
+ break;
+ default:
+ break;
+ }
+ for (; it != end; it++)
+ {
+ Package *package = new Package (new Package::Impl (*it));
+ g_sequence_insert_sorted (pool, package, inner::compare, NULL);
+ }
+
+ // add stuff to the actual pool now
+ int index = 0;
+ for (GSequenceIter *it = g_sequence_get_begin_iter (pool);
+ !g_sequence_iter_is_end (it); it = g_sequence_iter_next (it)) {
+ gpointer data = g_sequence_get (it);
+ Package *pkg = (Package *) data;
+ pkg->impl->index = index++;
+ pkg->impl->type = type;
+ packages[type] = g_slist_append (packages[type], data);
+ }
+
+// g_sequence_foreach (pool, inner::pool_foreach, &);
+ g_sequence_free (pool);
+ }
+ return packages[type];
+}
+#else
+GSList *Ypp::Impl::getPackages (Ypp::Package::Type type)
+{
+ if (!packages[type]) {
+long time1 = time(NULL);
+fprintf (stderr, "creating pool of %d...\n", type);
+ GSList *pool = NULL;
+ struct inner {
+ static gint compare (gconstpointer _a, gconstpointer _b)
+ {
+ Package *a = (Package *) _a;
+ Package *b = (Package *) _b;
+ return YGUtils::strcmp (a->name().c_str(), b->name().c_str());
+ }
+ };
+
+ ZyppPool::const_iterator it, end;
+ switch (type) {
+ case Package::PACKAGE_TYPE:
+ it = zyppPool().byKindBegin zypp::Package();
+ end = zyppPool().byKindEnd zypp::Package();
+ break;
+ case Package::PATTERN_TYPE:
+ it = zyppPool().byKindBegin zypp::Pattern();
+ end = zyppPool().byKindEnd zypp::Pattern();
+ break;
+ case Package::LANGUAGE_TYPE:
+ it = zyppPool().byKindBegin zypp::Language();
+ end = zyppPool().byKindEnd zypp::Language();
+ break;
+ default:
+ break;
+ }
+ for (; it != end; it++) {
+ Package *package = new Package (new Package::Impl (*it));
+ Ypp::Node *category = 0;
+ if (type == Package::PACKAGE_TYPE) {
+ ZyppObject object = (*it)->theObj();
+ ZyppPackage zpackage = tryCastToZyppPkg (object);
+ if (!zpackage)
+ continue;
+ category = addCategory (type, zpackage->group(), package);
+ }
+ else if (type == Package::PATTERN_TYPE) {
+ ZyppObject object = (*it)->theObj();
+ ZyppPattern pattern = tryCastToZyppPattern (object);
+ if (!pattern || !pattern->userVisible())
+ continue;
+ category = addCategory (type, pattern->category(), 0);
+ }
+
+ package->impl->type = type;
+ package->impl->category = category;
+ pool = g_slist_prepend (pool, package);
+ }
+ // its faster to prepend then reverse, as we avoid iterating for each append
+ // lets reverse before sorting, as they are somewhat sorted already
+ pool = g_slist_reverse (pool);
+ // a sort merge. Don't use g_slist_insert_sorted() -- its linear
+ pool = g_slist_sort (pool, inner::compare);
+ packages[type] = pool;
+
+ polishCategories (type);
+fprintf (stderr, "delta time: %ld\n", time(NULL)-time1);
+ }
+ return packages[type];
+}
+#endif
+
+Ypp::Ypp()
+{
+ impl = new Impl();
+
+ zyppPool().saveState();
+ zyppPool().saveState();
+ zyppPool().saveStatezypp::Selection();
+ zyppPool().saveState();
+ zyppPool().saveState();
+}
+
+Ypp::~Ypp()
+{
+ delete impl;
+}
+
+const Ypp::Repository *Ypp::getRepository (int nb)
+{ return impl->getRepository (nb); }
+
+Ypp::Disk *Ypp::getDisk()
+{ return impl->getDisk(); }
+
+void Ypp::setInterface (Ypp::Interface *interface)
+{ impl->interface = interface; }
+
+bool Ypp::isModified()
+{
+ return zyppPool().diffState() ||
+ zyppPool().diffState() ||
+ zyppPool().diffStatezypp::Selection() ||
+ zyppPool().diffState() ||
+ zyppPool().diffState();
+}
+
+void Ypp::startTransactions()
+{ impl->startTransactions(); }
+
+void Ypp::finishTransactions()
+{ impl->finishTransactions(); }
+
Added: trunk/gtk/src/yzyppwrapper.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/yzyppwrapper.h?rev=43214&view=auto
==============================================================================
--- trunk/gtk/src/yzyppwrapper.h (added)
+++ trunk/gtk/src/yzyppwrapper.h Thu Dec 20 21:38:55 2007
@@ -0,0 +1,196 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* A simplification of libzypp's API.
+
+ To get a list of packages, setup a Query object and create a Pool with
+ it. Package has a set of manipulation methods, the results of which are
+ then reported to Pool listeners, which you can choose to act on your
+ interface, if you want them reflected on the viewer.
+ Iterate the pool using Pool::Iter. Don't keep it around though, instead use
+ getIndex() and getIter(index).
+
+ You must register an object that implements Interface, as some transactions
+ are bound by user decisions. Ypp is a singleton; first call to get() will
+ initialize it; you should call finish() when you're done to de-allocate
+ caches.
+ The only thing you should free is Pool objects. A Query will be freed by
+ the Pool object you pass it to.
+*/
+
+#ifndef ZYPP_WRAPPER_H
+#define ZYPP_WRAPPER_H
+
+#include <string>
+#include <list>
+
+struct Ypp
+{
+ // Utilities
+ struct Node {
+ std::string name;
+ Node *next();
+ Node *child();
+ void *impl;
+ };
+
+ // Entries
+ struct Package {
+ enum Type {
+ PACKAGE_TYPE, PATTERN_TYPE, LANGUAGE_TYPE, TOTAL_TYPES
+ };
+
+ Type type();
+ const std::string &name();
+ const std::string &summary();
+ Node *category();
+ bool is3D();
+
+ std::string description();
+ std::string filelist();
+ std::string changelog();
+ std::string authors();
+
+ std::string provides();
+ std::string requires();
+
+ bool isInstalled();
+ bool hasUpgrade();
+ bool isLocked();
+
+ bool toInstall (int *nb = 0);
+ bool toRemove();
+ bool isModified();
+ bool isAuto(); /* installing/removing cause of dependency */
+
+ void install (int nb); /* if installed, will replace it by that version */
+ void remove();
+ void undo();
+ void lock (bool lock);
+
+ struct Version {
+ std::string number;
+ int repo, cmp /*relatively to installed*/;
+ void *impl;
+ };
+ const Version *getInstalledVersion();
+ const Version *getAvailableVersion (int nb);
+
+ // convinience -- true if any available is from the given repo
+ bool isOnRepository (int repo);
+
+ struct Impl;
+ Impl *impl;
+ Package (Impl *impl);
+ ~Package();
+ };
+
+ // when installing/removing/... a few packages at a time, you should use this methods,
+ // so that problem resolver gets only kicked after they are all queued
+ void startTransactions();
+ void finishTransactions();
+
+ // Query
+ struct Query {
+ Query (Package::Type type);
+ void setName (std::string name);
+ void setCategory (Ypp::Node *category);
+ void setIsInstalled (bool installed);
+ void setHasUpgrade (bool upgradable);
+ void setIsModified (bool modified);
+ void setRepositories (std::list <int> repositories);
+
+ ~Query();
+ struct Impl;
+ Impl *impl;
+ };
+
+ // Pool
+ struct Pool {
+ Pool (Query *query);
+
+ typedef void * Iter;
+ Iter getFirst();
+ Iter getNext (Iter it);
+ Package *get (Iter it);
+ int getIndex (Iter it);
+ Iter getIter (int index);
+
+ struct Listener {
+ virtual void entryChanged (Iter iter, Package *package) = 0;
+ virtual void entryInserted (Iter iter, Package *package) = 0;
+ virtual void entryDeleted (Iter iter, Package *package) = 0;
+ };
+ void setListener (Listener *listener);
+
+ ~Pool();
+ struct Impl;
+ Impl *impl;
+ };
+
+ // Resolver
+ struct Problem {
+ std::string description, details;
+ struct Solution {
+ std::string description, details;
+ bool apply;
+ void *impl;
+ };
+ Solution *getSolution (int nb);
+ void *impl;
+ };
+
+ // Module
+ static Ypp *get();
+ static void finish();
+
+ struct Interface {
+ virtual bool acceptLicense (Package *package, const std::string &license) = 0;
+ // resolveProblems = false to cancel the action that had that effect
+ virtual bool resolveProblems (std::list problems) = 0;
+
+ // FIXME: this is mostly a hack; the thing is that GtkTreeSelection doesn't
+ // signal when a selected row changes values. Anyway, to be done differently.
+ virtual void packageModified (Package *package) = 0;
+ };
+ void setInterface (Interface *interface);
+
+ bool isModified(); // any change made?
+
+ // Misc
+ struct Repository {
+ std::string name, alias /*internal use*/;
+ };
+ const Repository *getRepository (int nb);
+
+ Node *getFirstCategory (Package::Type type);
+
+ struct Disk
+ {
+ struct Partition {
+ std::string path, used_str, total_str;
+ long long used, total;
+ };
+ const Partition *getPartition (int nb);
+
+ struct Listener {
+ virtual void update() = 0;
+ };
+ void setListener (Listener *listener);
+
+ Disk();
+ ~Disk();
+ struct Impl;
+ Impl *impl;
+ };
+ Disk *getDisk();
+
+ Ypp();
+ ~Ypp();
+ struct Impl;
+ Impl *impl;
+};
+
+#endif /*ZYPP_WRAPPER_H*/
+
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org