[yast-commit] r43212 - /trunk/gtk/src/
![](https://seccdn.libravatar.org/avatar/660f918b95fb16b6bf617ac05c9637e3.jpg?s=120&d=mm&r=g)
Author: rpmcruz Date: Thu Dec 20 21:36:55 2007 New Revision: 43212 URL: http://svn.opensuse.org/viewcvs/yast?rev=43212&view=rev Log: Moving unstable-libyui to main. Modified: trunk/gtk/src/Makefile.am trunk/gtk/src/YGComboBox.cc trunk/gtk/src/YGImage.cc trunk/gtk/src/YGLayout.cc trunk/gtk/src/YGMultiLineEdit.cc trunk/gtk/src/YGPackageSelector.cc trunk/gtk/src/YGProgressBar.cc trunk/gtk/src/YGPushButton.cc trunk/gtk/src/YGUI.cc trunk/gtk/src/YGUtils.cc trunk/gtk/src/YGUtils.h trunk/gtk/src/YGWizard.cc trunk/gtk/src/ygdkmngloader.c trunk/gtk/src/ygtkratiobox.h trunk/gtk/src/ygtkwizard.c trunk/gtk/src/ygtkwizard.h Modified: trunk/gtk/src/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/Makefile.am?rev=43212&r1=... ============================================================================== --- trunk/gtk/src/Makefile.am (original) +++ trunk/gtk/src/Makefile.am Thu Dec 20 21:36:55 2007 @@ -46,11 +46,13 @@ ygtkfieldentry.c \ ygtkmenubutton.c \ ygtkwizard.c \ - ygtkcellrendererarrow.c \ ygtkfindentry.c \ ygdkmngloader.c \ + ygtkimage.c \ ygtkhtmlwrap.c \ - ygtkrichtext.c + ygtkrichtext.c \ + yzyppwrapper.cc \ + ygtkzyppwrapper.cc # should only append ygtkrichtext.c if USE_GTKHTML is set dummy_SOURCES = dummy.cc Modified: trunk/gtk/src/YGComboBox.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGComboBox.cc?rev=43212&r... ============================================================================== --- trunk/gtk/src/YGComboBox.cc (original) +++ trunk/gtk/src/YGComboBox.cc Thu Dec 20 21:36:55 2007 @@ -26,8 +26,9 @@ gtk_combo_box_set_model (GTK_COMBO_BOX (getWidget()), GTK_TREE_MODEL (store)); g_object_unref (store); - if(opt.isEditable.value()) + if(opt.isEditable.value()) { gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (getWidget()), 0); + } else { GtkCellRenderer* cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (getWidget()), cell, TRUE); Modified: trunk/gtk/src/YGImage.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGImage.cc?rev=43212&r1=4... ============================================================================== --- trunk/gtk/src/YGImage.cc (original) +++ trunk/gtk/src/YGImage.cc Thu Dec 20 21:36:55 2007 @@ -5,266 +5,57 @@ #include "ygdkmngloader.h" #include <config.h> #include <ycp/y2log.h> -#include <YGUI.h> -#include "YEvent.h" +#include "YGUI.h" #include "YGWidget.h" #include "YImage.h" +#include "ygtkimage.h" class YGImage : public YImage, public YGWidget { - bool m_hasZeroWidth, m_hasZeroHeight, m_isScaled, m_isTiled, m_isAnimation; - bool m_imageLoaded; - - struct Animation { - GdkPixbufAnimation *pixbuf; - GdkPixbufAnimationIter *frame; - guint timeout_id; - }; - union { - GdkPixbuf *m_pixbuf; - Animation *m_animation; - }; - gchar *alt_text; - - void initOptions (const YWidgetOpt &opt) + void setProps (const YWidgetOpt &opt, const YCPString &alt_text) { - IMPL - m_imageLoaded = false; - m_hasZeroWidth = opt.zeroWidth.value(); - m_hasZeroHeight = opt.zeroHeight.value(); - m_isAnimation = opt.animated.value(); - m_isScaled = opt.scaleToFit.value(); - m_isTiled = opt.tiled.value(); + bool scale = opt.scaleToFit.value(), tile = opt.tiled.value(); + YGtkImageAlign align = CENTER_IMAGE_ALIGN; + if (tile) + align = TILE_IMAGE_ALIGN; + if (scale) + align = SCALE_IMAGE_ALIGN; + if (scale && tile) + y2warning ("YImage can't be scaled and tiled at the same time"); + ygtk_image_set_props (YGTK_IMAGE (getWidget()), align, alt_text->value_cstr()); - if (m_hasZeroWidth || m_isScaled || m_isTiled) + bool zeroWidth = opt.zeroWidth.value(), zeroHeight = opt.zeroHeight.value(); + if (zeroWidth || scale || tile) setStretchable (YD_HORIZ, true); - if (m_hasZeroHeight || m_isScaled || m_isTiled) + if (zeroHeight || scale || tile) setStretchable (YD_VERT, true); - - if (m_isScaled && m_isTiled) { - y2warning ("YImage can't be scaled and tiled at the same time"); - m_isTiled = false; - } - - if (m_isAnimation) - m_animation = NULL; - else - m_pixbuf = NULL; - - g_signal_connect (G_OBJECT (getWidget()), "expose-event", - G_CALLBACK (expose_event_cb), this); - gtk_widget_queue_draw (getWidget()); - } - - void loadImage (GdkPixbuf *pixbuf, const char *error_msg) - { - IMPL - if (pixbuf == NULL) { - g_warning ("Couldn't load image - %s", error_msg); - return; - } - - m_imageLoaded = true; - m_pixbuf = pixbuf; - gtk_widget_set_size_request (getWidget(), m_hasZeroWidth ? -1 : gdk_pixbuf_get_width (pixbuf), - m_hasZeroHeight ? -1 : gdk_pixbuf_get_height (pixbuf)); - } - - void loadAnimation (GdkPixbufAnimation *pixbuf, const char *error_msg) - { - IMPL - if (pixbuf == NULL) { - g_warning ("Couldn't load animation - %s", error_msg); - return; - } - - m_imageLoaded = true; - m_animation = new Animation; - m_animation->pixbuf = pixbuf; - - m_animation->frame = NULL; - advance_frame_cb (this); - - g_signal_connect (G_OBJECT (getWidget()), "expose-event", - G_CALLBACK (expose_event_cb), this); - gtk_widget_queue_draw (getWidget()); + gtk_widget_set_size_request (getWidget(), zeroWidth ? 1 : -1, zeroHeight ? 1 : -1); } public: YGImage (const YWidgetOpt &opt, YGWidget *parent, const YCPString &filename_str, const YCPString &text) : YImage (opt), - YGWidget (this, parent, true, GTK_TYPE_DRAWING_AREA, NULL) + YGWidget (this, parent, true, YGTK_TYPE_IMAGE, NULL) { IMPL - alt_text = g_strdup (text->value_cstr()); - initOptions (opt); - + setProps (opt, text); const char *filename = filename_str->value_cstr(); - GError *error = 0; - if (m_isAnimation) { - 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); - loadAnimation (pixbuf, error ? error->message : "(undefined)"); - } - else { - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error); - loadImage (pixbuf, error ? error->message : "(undefined)"); - } + bool animated = opt.animated.value(); + ygtk_image_set_from_file (YGTK_IMAGE (getWidget()), filename, animated); } YGImage (const YWidgetOpt &opt, YGWidget *parent, const YCPByteblock &byteblock, const YCPString &text) : YImage (opt), - YGWidget (this, parent, true, GTK_TYPE_DRAWING_AREA, NULL) - { - IMPL - alt_text = g_strdup (text->value_cstr()); - initOptions (opt); - - GError *error = 0; - if (m_isAnimation && ygdk_mng_pixbuf_is_data_mng (byteblock->value(), byteblock->size())) - { - GdkPixbufAnimation *pixbuf; - pixbuf = ygdk_mng_pixbuf_new_from_data (byteblock->value(), byteblock->size(), &error); - loadAnimation (pixbuf, error ? error->message : "(undefined)"); - } - else - { - GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); - g_signal_connect (G_OBJECT (loader), "area-prepared", - G_CALLBACK (image_loaded_cb), this); - - if (!gdk_pixbuf_loader_write (loader, - byteblock->value(), byteblock->size(), &error)) - g_warning ("Could not load image from data blocks: %s", error->message); - gdk_pixbuf_loader_close (loader, &error); - } - } - - virtual ~YGImage() - { - IMPL - if (m_imageLoaded) { - if (m_isAnimation) { - g_object_unref (G_OBJECT (m_animation->pixbuf)); - if (m_animation->timeout_id) - g_source_remove (m_animation->timeout_id); - delete m_animation; - } - else - g_object_unref (G_OBJECT (m_pixbuf)); - } - g_free (alt_text); - } - - // callback for image loading - static void image_loaded_cb (GdkPixbufLoader *loader, YGImage *pThis) - { - IMPL - if (pThis->m_isAnimation) { - if (pThis->m_animation) { - // a new frame loaded -- just redraw the widget - if (gdk_pixbuf_animation_iter_on_currently_loading_frame - (pThis->m_animation->frame)) - gtk_widget_queue_draw (pThis->getWidget()); - } - else { - GdkPixbufAnimation *pixbuf = gdk_pixbuf_loader_get_animation (loader); - g_object_ref (G_OBJECT (pixbuf)); - pThis->loadAnimation (pixbuf, " on block data reading callback"); - } - } - else { - GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); - g_object_ref (G_OBJECT (pixbuf)); - pThis->loadImage (pixbuf, " on block data reading callback"); - } - } - - // callback for image displaying - static gboolean advance_frame_cb (void *pData) - { - IMPL - YGImage *pThis = (YGImage *) pData; - Animation *animation = pThis->m_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 (pThis->getWidget()); - - // shedule next frame - int delay = gdk_pixbuf_animation_iter_get_delay_time (animation->frame); - if (delay != -1) - animation->timeout_id = g_timeout_add (delay, advance_frame_cb, pThis); - - GdkPixbuf *pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (pThis->m_animation->frame); - gtk_widget_set_size_request (pThis->getWidget(), gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - return FALSE; - } - - static gboolean expose_event_cb (GtkWidget *widget, GdkEventExpose *event, - YGImage *pThis) + YGWidget (this, parent, true, YGTK_TYPE_IMAGE, NULL) { IMPL - int x, y, width, height; - x = widget->allocation.x + 6; - y = widget->allocation.y + 6; - width = widget->allocation.width; - height = widget->allocation.height; - - cairo_t *cr = gdk_cairo_create (widget->window); - - if (!pThis->m_imageLoaded) { - // show default text if no image was loaded - PangoLayout *layout; - layout = gtk_widget_create_pango_layout (widget, pThis->alt_text); - - int text_width, text_height; - pango_layout_get_size (layout, &text_width, &text_height); - text_width /= PANGO_SCALE; - text_height /= PANGO_SCALE; - - x += (width - text_width) / 2; - y += (height - text_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 (pThis->m_isAnimation) - pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (pThis->m_animation->frame); - else - pixbuf = pThis->m_pixbuf; - gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); - - if (pThis->m_isTiled) - cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); - - if (pThis->m_isScaled) { - 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); - } - - cairo_rectangle (cr, 0, 0, width, height); - cairo_fill (cr); - - cairo_destroy (cr); - return TRUE; + setProps (opt, text); + const guint8 *data = byteblock->value(); + long data_size = byteblock->size(); + bool animated = opt.animated.value(); + ygtk_image_set_from_data (YGTK_IMAGE (getWidget()), data, data_size, animated); } YGWIDGET_IMPL_COMMON Modified: trunk/gtk/src/YGLayout.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGLayout.cc?rev=43212&r1=... ============================================================================== --- trunk/gtk/src/YGLayout.cc (original) +++ trunk/gtk/src/YGLayout.cc Thu Dec 20 21:36:55 2007 @@ -96,7 +96,7 @@ YGWidget::sync_stretchable(); } - virtual void moveChild (YWidget *, long, long) {}; // ignore + virtual void moveChild (YWidget *, long, long) {} // ignore }; YContainerWidget * Modified: trunk/gtk/src/YGMultiLineEdit.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGMultiLineEdit.cc?rev=43... ============================================================================== --- trunk/gtk/src/YGMultiLineEdit.cc (original) +++ trunk/gtk/src/YGMultiLineEdit.cc Thu Dec 20 21:36:55 2007 @@ -245,3 +245,146 @@ return new YGRichText (opt, YGWidget::get (parent), text); } +#if 0 +/* Wrote this code, in order to allow the user to print a package license. + But they are written in HTML, so that was too much for me. Anyway, might + be needed in the future -- it prints text okay. Maybe we could adapt it to + YGtkRichText, so that it just iterates through its tags (its a GtkTextView + afterall), rather than doing html parsing. ugh. Maybe we could somehow re-use + GtkTextView GtkLayouts...*/ + +typedef struct { + gchar *title, *text; + PangoLayout *title_layout, *text_layout; + gint cur_line; +} PrintData; + + +static void free_print_data_cb (gpointer _data, GClosure *closure) +{ + PrintData *data = _data; +fprintf (stderr, "freeing print data '%s'\n", data->title); + g_free (data->title); + g_free (data->text); + if (data->title_layout) + g_object_unref (G_OBJECT (data->title_layout)); + if (data->text_layout) + g_object_unref (G_OBJECT (data->text_layout)); + g_free (data); +} + +static void print_begin_cb (GtkPrintOperation *print, GtkPrintContext *context, PrintData *data) +{ + int width = gtk_print_context_get_width (context); + int height = gtk_print_context_get_height (context); + + PangoFontDescription *desc; + desc = pango_font_description_from_string ("Sans 12"); + + data->text_layout = gtk_print_context_create_pango_layout (context); + pango_layout_set_font_description (data->text_layout, desc); + pango_layout_set_width (data->text_layout, width * PANGO_SCALE); + pango_layout_set_text (data->text_layout, data->text, -1); + + data->title_layout = gtk_print_context_create_pango_layout (context); + pango_layout_set_font_description (data->title_layout, desc); + pango_layout_set_width (data->title_layout, width * PANGO_SCALE); + pango_layout_set_text (data->title_layout, data->title, -1); + + pango_font_description_free (desc); + + int title_height, text_height; + pango_layout_get_pixel_size (data->title_layout, NULL, &title_height); + title_height += 10; + pango_layout_get_pixel_size (data->text_layout, NULL, &text_height); + + int pages_nb, page_height = height - title_height; + pages_nb = text_height / page_height; + if (text_height % page_height != 0) + pages_nb++; + data->cur_line = 0; +fprintf (stderr, "print begin: will use %d pages\n", pages_nb); + gtk_print_operation_set_n_pages (print, pages_nb); +} + +static void print_draw_page_cb (GtkPrintOperation *print, GtkPrintContext *context, + gint page_nb, PrintData *data) +{ + int title_height; + pango_layout_get_pixel_size (data->title_layout, NULL, &title_height); + title_height += 10; + + cairo_t *cr = gtk_print_context_get_cairo_context (context); + cairo_set_source_rgb (cr, 0, 0, 0); + + cairo_move_to (cr, 6, 3); + pango_cairo_show_layout (cr, data->title_layout); + + cairo_move_to (cr, 0, title_height-4); + cairo_line_to (cr, gtk_print_context_get_width (context), title_height-4); + cairo_stroke (cr); + + int y = title_height, page_height = 0; + for (;; data->cur_line++) { +fprintf (stderr, "printing line: %d\n", data->cur_line); + PangoLayoutLine *line = pango_layout_get_line_readonly (data->text_layout, + data->cur_line); + if (!line) +{ +fprintf (stderr, "no more lines\n"); + break; +} + PangoRectangle rect; + pango_layout_line_get_pixel_extents (line, NULL, &rect); +fprintf (stderr, "paragraph rect: %d x %d , %d x %d\n", rect.x, rect.y, rect.width, rect.height); + page_height += rect.height; + if (page_height >= gtk_print_context_get_height (context)) +{ +fprintf (stderr, "end of page: %f x %d\n", gtk_print_context_get_height (context), page_height); + break; +} + + cairo_move_to (cr, rect.x, y + rect.height); + pango_cairo_show_layout_line (cr, line); + y += rect.height; + } +} + +void ygtk_html_print_text (GtkWindow *parent_window, const gchar *title, const gchar *text) +{ + PrintData *data = g_new (PrintData, 1); + data->title = g_strdup (title); + data->text = g_strdup (text); + data->title_layout = data->text_layout = NULL; + + GtkPrintOperation *print = gtk_print_operation_new(); + + static GtkPrintSettings *print_settings = NULL; + if (print_settings) + gtk_print_operation_set_print_settings (print, print_settings); + + g_signal_connect (G_OBJECT (print), "begin-print", G_CALLBACK (print_begin_cb), data); + g_signal_connect_data (G_OBJECT (print), "draw-page", G_CALLBACK (print_draw_page_cb), + data, free_print_data_cb, 0); + + GError *error; + GtkPrintOperationResult res; + res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, + parent_window, &error); + if (res == GTK_PRINT_OPERATION_RESULT_ERROR) { + GtkWidget *dialog; + dialog = gtk_message_dialog_new (parent_window, GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "<b>Print error</b>\n%s", error->message); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + g_error_free (error); + } + if (res == GTK_PRINT_OPERATION_RESULT_APPLY) { + if (print_settings) + g_object_unref (print_settings); + print_settings = g_object_ref (gtk_print_operation_get_print_settings (print)); + } +} +#endif + Modified: trunk/gtk/src/YGPackageSelector.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGPackageSelector.cc?rev=... ============================================================================== --- trunk/gtk/src/YGPackageSelector.cc (original) +++ trunk/gtk/src/YGPackageSelector.cc Thu Dec 20 21:36:55 2007 @@ -2,2419 +2,1382 @@ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * ********************************************************************/ -/* - Textdomain "yast2-gtk" -*/ - #include <config.h> #include <ycp/y2log.h> -#include <YGUI.h> + +#include "YGUI.h" #include "YGUtils.h" #include "YGi18n.h" #include "YGDialog.h" -#include "YPackageSelector.h" -#include "ygtkhtmlwrap.h" + #include "ygtkwizard.h" -#include "ygtkcellrendererarrow.h" -#include "ygtkratiobox.h" #include "ygtkfindentry.h" +#include "ygtkhtmlwrap.h" +#include "ygtkzyppwrapper.h" -#include <map> - -//#define DISABLE_PACKAGE_SELECTOR - -#ifndef DISABLE_PACKAGE_SELECTOR -#include <zypp/ZYppFactory.h> -#include <zypp/ResObject.h> -#include <zypp/ResPoolProxy.h> -#include <zypp/ui/Selectable.h> -#include <zypp/Patch.h> -#include <zypp/Selection.h> -#include <zypp/Package.h> -#include <zypp/Pattern.h> -#include <zypp/Language.h> -#include <zypp/Product.h> -#ifdef PRE_ZYPP_3 -#include <zypp/Source.h> -#include <zypp/SourceManager.h> -#else -#include <zypp/Repository.h> -#include <zypp/RepoManager.h> -#endif +// utilities +static GtkWidget *createImageFromXPM (const char **xpm) +{ + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (xpm); + GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf); + gtk_widget_show (image); + g_object_unref (pixbuf); + return image; +} -/* We should consider linking to libgnome and use gnome_url_show(url) here, - or at least do some path finding. */ #define FILEMANAGER_EXEC "/usr/bin/nautilus" -inline bool FILEMANAGER_PRESENT() -{ return g_file_test (FILEMANAGER_EXEC, G_FILE_TEST_IS_EXECUTABLE); } inline void FILEMANAGER_LAUNCH (const char *path) -{ system ((string (FILEMANAGER_EXEC) + " " + path + " &").c_str()); } +{ system ((std::string (FILEMANAGER_EXEC) + " -n --no-desktop " + path + " &").c_str()); } -// some typedefs and functions to short Zypp names -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::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); } - -static zypp::Text -fastGetSummary (ZyppObject obj) +static void busyCursor() { - static std::map<std::string, zypp::Text> name_to_summary; - std::string &summary = name_to_summary[ obj->name() ]; - if (summary.length() <= 0) - summary = obj->summary(); - return summary; + YGUI::ui()->busyCursor(); + // so that the cursor is actually set... + while (g_main_context_iteration (NULL, FALSE)) ; } +static void normalCursor() +{ YGUI::ui()->normalCursor(); } -// Computer icon comes from Tango, but may not be installed, or not initialized. -#include "computer.xpm" +#include "icons/pkg-list-mode.xpm" +#include "icons/pkg-tiles-mode.xpm" -static bool acceptLicense (ZyppSelectablePtr sel) +class PackagesView { - if (sel->hasLicenceConfirmed()) - return true; - - ZyppObject object = sel->candidateObj(); - ZyppPackage package = tryCastToZyppPkg (object); - if (!package) - return true; - - const string &license = package->licenseToConfirm(); - if (license.empty()) { - sel->setLicenceConfirmed (true); - return true; - } - - GtkWidget *dialog = gtk_dialog_new_with_buttons (_("License Agreement"), - YGUI::ui()->currentWindow(), GTK_DIALOG_MODAL, - _("_Reject"), GTK_RESPONSE_REJECT, _("_Accept"), GTK_RESPONSE_ACCEPT, NULL); - - GtkWidget *license_view, *license_window; - - license_view = ygtk_html_wrap_new(); - ygtk_html_wrap_set_text (license_view, license.c_str()); - - license_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (license_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type - (GTK_SCROLLED_WINDOW (license_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (license_window), license_view); - - GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox); - gtk_box_pack_start (vbox, license_window, TRUE, TRUE, 6); - - const char *print_text = _("If you would like to print this license, check the EULA.txt file on the first media"); - GtkLabel *print_label = GTK_LABEL (gtk_label_new (print_text)); - gtk_box_pack_start (vbox, GTK_WIDGET (print_label), FALSE, TRUE, 2); - - gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400); - gtk_widget_show_all (dialog); - - bool confirmed = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT; - gtk_widget_destroy (dialog); - - sel->setLicenceConfirmed (confirmed); - return confirmed; -} +public: + struct Listener { + virtual void packagesSelected (const std::list <Ypp::Package *> &selection) = 0; + }; + void setListener (Listener *listener) + { m_listener = listener; } -// install / remove convinience wrapper. You only need to specify an object -// if you want that particular version to be installed. -// returns true on sucess -static bool mark_selectable (ZyppSelectablePtr selectable, bool install /*or remove*/) -{ - zypp::ui::Status status = selectable->status(); +private: +Listener *m_listener; - if (install) { - if (!selectable->hasCandidateObj()) { - y2warning ("YGPackageSelector: no package on repository to install"); - return false; - } - if (!acceptLicense (selectable)) - return false; - if (status == zypp::ui::S_Del) - status = zypp::ui::S_KeepInstalled; - else { - if (status == zypp::ui::S_KeepInstalled) - status = zypp::ui::S_Update; - else - status = zypp::ui::S_Install; + void packagesSelected (const std::list <Ypp::Package *> &selection) + { + if (m_listener) { + busyCursor(); + m_listener->packagesSelected (selection); + normalCursor(); } } - else /*remove*/ { - if (status == zypp::ui::S_NoInst) - ; // do nothing - else if (status == zypp::ui::S_Install) - status = zypp::ui::S_NoInst; - else if (status == zypp::ui::S_Update) - status = zypp::ui::S_KeepInstalled; - else - status = zypp::ui::S_Del; - } - -#if 0 // debug - const char *name = selectable->name().c_str(); - switch (status) { - case zypp::ui::S_KeepInstalled: - y2milestone ("keep %s installed\n", name); - break; - case zypp::ui::S_Update: - y2milestone ("update %s\n", name); - break; - case zypp::ui::S_Install: - y2milestone ("install %s\n", name); - break; - case zypp::ui::S_Del: - y2milestone ("remove %s\n", name); - break; - case zypp::ui::S_NoInst: - y2milestone ("don't install %s\n", name); - break; - default: - y2milestone ("error: unknown action: should not happen\n"); - break; - } -#endif - - return selectable->set_status (status); -} -// tries to solve possible dependencies problems and asks the user for -// manual resolution if needed (there is not much space for interface -// design here) -static bool solveProblems() -{ - IMPL - zypp::Resolver_Ptr resolver = zypp::getZYpp()->resolver(); - if (resolver->resolvePool()) - return true; - zypp::ResolverProblemList problems = resolver->problems(); - if (problems.empty()) - return true; - - GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Resolve Problems"), - YGUI::ui()->currentWindow(), GTK_DIALOG_MODAL, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("C_onfirm"), GTK_RESPONSE_ACCEPT, NULL); - - GtkWidget *problems_view; - problems_view = gtk_tree_view_new(); - - GtkWidget *problems_window; - problems_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (problems_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type - (GTK_SCROLLED_WINDOW (problems_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (problems_window), problems_view); - - GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox); - gtk_box_pack_start (vbox, problems_window, TRUE, TRUE, 0); - - // create model - // the vairous columns are: radio button active (boolean), problem - // or solution description (string), is radio button (boolean: always - // true), show radio button (boolean; false for problems) - GtkTreeStore *problems_store = gtk_tree_store_new (4, - G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN); - // install view - GtkTreeViewColumn *column; - GtkCellRenderer *radio_renderer = gtk_cell_renderer_toggle_new(); - column = gtk_tree_view_column_new_with_attributes ("", - radio_renderer, "active", 0, "radio", 2, "visible", 3, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (problems_view), column); - g_signal_connect (G_OBJECT (radio_renderer), "toggled", - G_CALLBACK (YGUtils::tree_view_radio_toggle_cb), - GTK_TREE_MODEL (problems_store)); - - column = gtk_tree_view_column_new_with_attributes (_("Problems"), - gtk_cell_renderer_text_new(), "text", 1, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (problems_view), column); - - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (problems_view), FALSE); - gtk_tree_view_set_model (GTK_TREE_VIEW (problems_view), - GTK_TREE_MODEL (problems_store)); - g_object_unref (G_OBJECT (problems_store)); - - // construct model - GtkTreeIter piter, siter; - map <GtkTreePath *, zypp::ProblemSolution *> users_actions; - for (zypp::ResolverProblemList::iterator it = problems.begin(); - it != problems.end(); it++) { - zypp::ProblemSolutionList solutions = (*it)->solutions(); - - gtk_tree_store_append (problems_store, &piter, NULL); - gtk_tree_store_set (problems_store, &piter, 0, FALSE, - 1, (*it)->description().c_str(), 2, TRUE, 3, FALSE, -1); - - for (zypp::ProblemSolutionList::iterator jt = solutions.begin(); - jt != solutions.end(); jt++) { - gtk_tree_store_append (problems_store, &siter, &piter); - gtk_tree_store_set (problems_store, &siter, 0, FALSE, - 1, (*jt)->description().c_str(), 2, TRUE, 3, TRUE, -1); - users_actions [gtk_tree_model_get_path (GTK_TREE_MODEL ( - problems_store), &siter)] = get_pointer (*jt); - } - } - - // set tree properties - gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (problems_view)), GTK_SELECTION_NONE); - gtk_tree_view_expand_all (GTK_TREE_VIEW (problems_view)); - - gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400); - gtk_widget_show_all (dialog); - - bool confirmed = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT; - - if (confirmed) { - // apply user solutions - zypp::ProblemSolutionList userChoices; + struct View { + PackagesView *m_parent; + GtkWidget *m_widget; + View (PackagesView *parent) : m_parent (parent) + {} + virtual void setModel (GtkTreeModel *model) = 0; - GtkTreeIter iter; - for (map <GtkTreePath *, zypp::ProblemSolution *>::iterator it - = users_actions.begin(); it != users_actions.end(); it++) { - gtk_tree_model_get_iter (GTK_TREE_MODEL (problems_store), - &iter, it->first); - gboolean state = FALSE; - gtk_tree_model_get (GTK_TREE_MODEL (problems_store), &iter, - 0, &state, -1); - if (state) - userChoices.push_back (it->second); - - gtk_tree_path_free (it->first); - } - resolver->applySolutions (userChoices); - } - - gtk_widget_destroy (dialog); - if (confirmed) - // repeate the all process as things may not yet be solved - return solveProblems(); - return false; -} + void selectedPaths (GtkTreeModel *model, GList *paths) + { + std::list <Ypp::Package *> packages; + for (GList *i = paths; i; i = i->next) { + Ypp::Package *package; + GtkTreePath *path = (GtkTreePath *) i->data; + GtkTreeIter iter; + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, YGtkZyppModel::PTR_COLUMN, &package, -1); + gtk_tree_path_free (path); -#ifdef PRE_ZYPP_3 -static string getSourceName (zypp::Source_Ref source) -{ // based on yast-qt's singleProduct() - if (!source.enabled()) - // can't get name if disabled; strangely, source.resolvables().begin() - // hangs - return ""; - string ret; - bool found = false; - for (zypp::ResStore::iterator it = source.resolvables().begin(); - it != source.resolvables().end(); it++) { - zypp::Product::Ptr product; - product = zypp::dynamic_pointer_cast <zypp::Product> (*it); - if (product) { - if (found) { - y2milestone ("Multiple products on installation source %s", - source.alias().c_str()); - return ""; - } - found = true; - ret = fastGetSummary (product); + packages.push_back (package); + } + g_list_free (paths); + m_parent->packagesSelected (packages); } - } - - if (!found) - y2milestone ("No product on installation source %s", - source.alias().c_str()); - return ret; -} -#endif - -#define PACKAGE_INFO_HEIGHT 140 -#define ADVANCED_INFO_HEIGHT 80 - -// Expander widget with the package information -class PackageInformation -{ - GtkWidget *m_widget, *m_notebook; - // Information text - GtkWidget *m_about_text, *m_authors_text, *m_filelist_text, *m_changelog_text; - bool m_use_filemanager; - -public: - PackageInformation (const char *expander_text, bool only_description) + }; + struct ListView : public View { - m_widget = gtk_expander_new (expander_text); - gtk_widget_set_sensitive (m_widget, FALSE); - - if (only_description) { - GtkWidget *about_win = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (about_win), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - m_about_text = ygtk_html_wrap_new(); - gtk_container_add (GTK_CONTAINER (about_win), m_about_text); - gtk_container_add (GTK_CONTAINER (m_widget), about_win); - m_authors_text = m_filelist_text = m_changelog_text = NULL; - m_notebook = NULL; - } - else { - m_notebook = gtk_notebook_new(); - gtk_notebook_set_tab_pos (GTK_NOTEBOOK (m_notebook), GTK_POS_BOTTOM); - gtk_container_add (GTK_CONTAINER (m_widget), m_notebook); - - m_about_text = add_text_tab (m_notebook, _("Description")); - m_filelist_text = add_text_tab (m_notebook, _("File List")); - if ((m_use_filemanager = FILEMANAGER_PRESENT())) - ygtk_html_wrap_connect_link_clicked (m_filelist_text, - G_CALLBACK (dir_pressed_cb), NULL); - m_changelog_text = add_text_tab (m_notebook, _("Change Log")); - m_authors_text = add_text_tab (m_notebook, _("Authors")); + ListView (PackagesView *parent) + : View (parent) + { + GtkTreeView *view = GTK_TREE_VIEW (m_widget = gtk_tree_view_new()); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); + gtk_tree_view_set_search_column (GTK_TREE_VIEW (view), 1); + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + renderer = gtk_cell_renderer_pixbuf_new(); + column = gtk_tree_view_column_new_with_attributes ("", renderer, + "pixbuf", YGtkZyppModel::ICON_COLUMN, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + renderer = gtk_cell_renderer_text_new(); + g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); + column = gtk_tree_view_column_new_with_attributes ("", renderer, + "markup", YGtkZyppModel::NAME_DESCRIPTION_COLUMN, NULL); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + renderer = gtk_cell_renderer_pixbuf_new(); + column = gtk_tree_view_column_new_with_attributes ("", renderer, + "pixbuf", YGtkZyppModel::SPECIAL_ICON_COLUMN, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + + GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); + g_signal_connect (G_OBJECT (selection), "changed", + G_CALLBACK (packages_selected_cb), this); + gtk_widget_show (m_widget); } - gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (m_widget)), - -1, PACKAGE_INFO_HEIGHT); - } - GtkWidget *getWidget() - { return m_widget; } + virtual void setModel (GtkTreeModel *model) + { + gtk_tree_view_set_model (GTK_TREE_VIEW (m_widget), model); + if (GTK_WIDGET_REALIZED (m_widget)) + gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (m_widget), 0, 0); + } - void setPackage (ZyppSelectablePtr selectable, ZyppObject object) + static void packages_selected_cb (GtkTreeSelection *selection, View *pThis) + { + GtkTreeModel *model; + GList *paths = gtk_tree_selection_get_selected_rows (selection, &model); + pThis->selectedPaths (model, paths); + } + }; + struct IconView : public View { - if (!selectable || !object) { - if (m_about_text) - set_text (m_about_text, ""); - if (m_filelist_text) - set_text (m_filelist_text, ""); - if (m_changelog_text) - set_text (m_changelog_text, ""); - if (m_authors_text) - set_text (m_authors_text, ""); - gtk_expander_set_expanded (GTK_EXPANDER (m_widget), FALSE); - gtk_widget_set_sensitive (m_widget, FALSE); - return; + IconView (PackagesView *parent) + : View (parent) + { + GtkIconView *view = GTK_ICON_VIEW (m_widget = gtk_icon_view_new()); + gtk_icon_view_set_text_column (view, YGtkZyppModel::NAME_COLUMN); + gtk_icon_view_set_pixbuf_column (view, YGtkZyppModel::ICON_COLUMN); + gtk_icon_view_set_selection_mode (view, GTK_SELECTION_MULTIPLE); + g_signal_connect (G_OBJECT (m_widget), "selection-changed", + G_CALLBACK (packages_selected_cb), this); + gtk_widget_show (m_widget); } - /* Keep notebook on first page; but only when not visible to not - annoy the user. */ - if (m_notebook && !gtk_expander_get_expanded (GTK_EXPANDER (m_widget))) - gtk_notebook_set_current_page (GTK_NOTEBOOK (m_notebook), 0); - gtk_widget_set_sensitive (m_widget, TRUE); - - ZyppPackage package = tryCastToZyppPkg (object); - if (m_about_text) { - string description = YGUtils::escape_markup (object->description(), true); - - // cut authors, since they have their own section - string::size_type pos = description.find ("Authors:"); - if (pos != string::npos) - description.erase (pos, string::npos); - - string str; - if (package) { - description += "<br>"; - str = package->url(); - if (!str.empty()) - description += _("Website: ") + str + "<br>"; - str = package->license(); - if (!str.empty()) - description += _("License: ") + str + "<br>"; - description += _("Size: ") + object->size().asString() + "b<br>"; - } - -#ifdef PRE_ZYPP_3 - zypp::Source_Ref source = object->source(); - str = getSourceName (source); - if (str.empty()) - str = source.url().asString(); - else - str = str + " (" + source.url().asString() + ")"; -#else - zypp::Repository repo = object->repository(); - str = repo.info().name(); -#endif - if (!str.empty()) - description += _("Repository: ") + str; + virtual void setModel (GtkTreeModel *model) + { + gtk_icon_view_set_model (GTK_ICON_VIEW (m_widget), model); + if (GTK_WIDGET_REALIZED (m_widget)) { + GtkTreePath *path = gtk_tree_path_new_first(); + gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (m_widget), + path, FALSE, 0, 0); + gtk_tree_path_free (path); + } + } - set_text (m_about_text, description); + static void packages_selected_cb (GtkIconView *view, View *pThis) + { + GtkTreeModel *model = gtk_icon_view_get_model (view); + GList *paths = gtk_icon_view_get_selected_items (view); + pThis->selectedPaths (model, paths); } - if (package) { - if (m_filelist_text) { - string filelist; - const std::list <string> &filenames = package->filenames(); - for (std::list <string>::const_iterator it = filenames.begin(); - it != filenames.end(); it++) { - string file (*it); - // don't show created dirs - if (g_file_test (file.c_str(), G_FILE_TEST_IS_DIR)) - continue; - // set the path as a link - if (m_use_filemanager) { - string::size_type pos = file.find_last_of ('/'); - if (pos != string::npos) { // should be always true - string dirname (file, 0, pos+1); - string basename (file, pos+1, string::npos); - file = "<a href=" + dirname + ">" + dirname + "</a>" + basename; - } - } - filelist += file + "<br>"; - } - set_text (m_filelist_text, filelist); - } - if (m_changelog_text) { - string text; - const std::list <zypp::ChangelogEntry> &changelog = package->changelog(); - for (std::list <zypp::ChangelogEntry>::const_iterator it = changelog.begin(); - it != changelog.end(); it++) { - string t = "<blockquote>" + YGUtils::escape_markup (it->text(), true) + - "</blockquote>"; - text += "<p>" + it->date().asString() + "" - + YGUtils::escape_markup (it->author()) + ":<br>" - + t + "</p>"; - } - set_text (m_changelog_text, text); - } - if (m_authors_text) { - string packager (YGUtils::escape_markup (package->packager())), authors; + }; - const std::list <string> &authors_list = package->authors(); - if (!authors_list.empty()) { - for (std::list <string>::const_iterator it = authors_list.begin(); - it != authors_list.end(); it++) - authors += *it; - } - else { -// TODO: stuff changed on YGUtils, descript. and this needs to be reviewd - /* authors() should be the proper way to get authors, but it seems to - be rarely used, instead packagers list them on the description. */ - string description (object->description()); -//std::cerr << "description: " << description << std::endl; - string::size_type pos = description.find ("Authors:"); - if (pos != string::npos) { - pos = description.find_first_not_of ( - '-', pos + sizeof ("Authors:") + 1); -//std::cerr << "copy string from " << pos << std::endl; - authors = string (description, pos, string::npos); - authors = YGUtils::escape_markup (authors, true); -//std::cerr << "authors: " << authors << std::endl; - } - } +GtkWidget *m_box, *m_bin, *m_list_button, *m_icon_button; +GtkTreeModel *m_model; +View *m_view; - string text; - if (!packager.empty()) - text = _("Packaged by:") + ("<blockquote>" + packager) + - "</blockquote>"; - if (!authors.empty()) { - if (!packager.empty()) - text += "<br><br>"; - text += _("Developed by:") + ("<blockquote>" + authors) + - "</blockquote>"; - } - set_text (m_authors_text, text); - } - } - else { - if (m_filelist_text) - set_text (m_filelist_text, ""); - if (m_changelog_text) - set_text (m_changelog_text, ""); - if (m_authors_text) - set_text (m_authors_text, ""); - } - } +public: + GtkWidget *getWidget() + { return m_box; } -private: - // auxiliaries to cut down on code - static GtkWidget *add_text_tab (GtkWidget *notebook, const char *label) + PackagesView() : m_listener (NULL), m_model (NULL), m_view (NULL) { - GtkWidget *widget, *scroll_win; - scroll_win = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_win), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - widget = ygtk_html_wrap_new(); - gtk_container_add (GTK_CONTAINER (scroll_win), widget); + m_bin = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (m_bin), + GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_bin), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scroll_win, - gtk_label_new (label)); - return widget; + GtkWidget *buttons = gtk_vbox_new (FALSE, 0), *image; + image = createImageFromXPM (pkg_list_mode_xpm); + m_list_button = gtk_toggle_button_new(); + gtk_button_set_image (GTK_BUTTON (m_list_button), image); + image = createImageFromXPM (pkg_tiles_mode_xpm); + m_icon_button = gtk_toggle_button_new(); + gtk_button_set_image (GTK_BUTTON (m_icon_button), image); + gtk_box_pack_start (GTK_BOX (buttons), gtk_label_new(""), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (buttons), m_list_button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (buttons), m_icon_button, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (m_list_button), "toggled", + G_CALLBACK (mode_toggled_cb), this); + g_signal_connect (G_OBJECT (m_icon_button), "toggled", + G_CALLBACK (mode_toggled_cb), this); + + m_box = gtk_hbox_new (FALSE, 2); + gtk_box_pack_start (GTK_BOX (m_box), m_bin, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_box), buttons, FALSE, TRUE, 0); + + setMode (LIST_MODE); + } + + ~PackagesView() + { + if (m_model) + g_object_unref (G_OBJECT (m_model)); + delete m_view; } - static void set_text (GtkWidget *widget, const string &text) + enum ViewMode { + LIST_MODE, ICON_MODE + }; + void setMode (ViewMode mode) { - const char *str = _("<i>(not available)</i>"); - if (!text.empty()) - str = text.c_str(); - ygtk_html_wrap_set_text (widget, str); - ygtk_html_wrap_scroll (widget, TRUE); // scroll to the start + if (GTK_WIDGET_REALIZED (m_bin)) + busyCursor(); + g_signal_handlers_block_by_func (m_list_button, (gpointer) mode_toggled_cb, this); + g_signal_handlers_block_by_func (m_icon_button, (gpointer) mode_toggled_cb, this); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (m_list_button), mode == LIST_MODE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (m_icon_button), mode == ICON_MODE); + + g_signal_handlers_unblock_by_func (m_list_button, (gpointer) mode_toggled_cb, this); + g_signal_handlers_unblock_by_func (m_icon_button, (gpointer) mode_toggled_cb, this); + + if (m_view) + gtk_container_remove (GTK_CONTAINER (m_bin), m_view->m_widget); + delete m_view; + if (mode == LIST_MODE) + m_view = new ListView (this); + else + m_view = new IconView (this); +fprintf (stderr, "adding new view to container\n"); + gtk_container_add (GTK_CONTAINER (m_bin), m_view->m_widget); + if (m_model) + m_view->setModel (m_model); + packagesSelected (std::list <Ypp::Package *> ()); + normalCursor(); + } + + void query (Ypp::Query *query) + { + if (GTK_WIDGET_REALIZED (m_bin)) + busyCursor(); + + if (m_model) + g_object_unref (G_OBJECT (m_model)); + + YGtkZyppModel *zmodel = ygtk_zypp_model_new (query); + m_model = GTK_TREE_MODEL (zmodel); + if (m_view) { + m_view->setModel (m_model); + packagesSelected (std::list <Ypp::Package *> ()); + } + normalCursor(); } - /* When a directory is pressed on the file list. */ - static void dir_pressed_cb (GtkWidget *text, const gchar *link) - { FILEMANAGER_LAUNCH (link); } +private: + static void mode_toggled_cb (GtkToggleButton *toggle, PackagesView *pThis) + { + bool active = gtk_toggle_button_get_active (toggle); + if (!active) { + // don't let the button be un-pressed + g_signal_handlers_block_by_func (toggle, (gpointer) mode_toggled_cb, pThis); + gtk_toggle_button_set_active (toggle, TRUE); + g_signal_handlers_unblock_by_func (toggle, (gpointer) mode_toggled_cb, pThis); + return; + } + ViewMode mode = GTK_WIDGET (toggle) == pThis->m_list_button ? LIST_MODE : ICON_MODE; + pThis->setMode (mode); + } }; -// Table widget with package sources - /* I don't like this, since it differs from the rest of the code, but to - avoid declarations... */ - struct SourcesTableListener - { - virtual ~SourcesTableListener() {} - virtual void sources_changed_cb() = 0; - }; -class SourcesTable +// TEMP: a window of modified packages +class TrashWindow : PackagesView::Listener { - GtkWidget *m_widget; - GtkTreeModel *m_model; - SourcesTableListener *m_listener; +GtkWidget *m_window, *m_undo_button; +PackagesView *m_view; public: - SourcesTable (SourcesTableListener *listener) - : m_listener (listener) + TrashWindow() { - /* 0 - source enabled?, 1 - source name (estimation), 2 - source URL, - 3 - source id; what they call of alias. */ - GtkListStore *store = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING); - m_model = GTK_TREE_MODEL (store); - -#ifdef PRE_ZYPP_3 - zypp::SourceManager_Ptr manager = zypp::SourceManager::sourceManager(); - for (zypp::SourceManager::Source_const_iterator it = manager->Source_begin(); - it != manager->Source_end(); it++) { - zypp::Source_Ref src = *it; - if (src && src.enabled()) { - GtkTreeIter iter; - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, src.enabled(), - 1, getSourceName (src).c_str(), 2, src.url().asString().c_str(), - 3, src.alias().c_str(), -1); - } - } -#else - zypp::RepoManager manager; - std::list <zypp::RepoInfo> repos = manager.knownRepositories(); - for (std::list <zypp::RepoInfo>::iterator it = repos.begin(); - it != repos.end(); it++) { - if (it->enabled()) { - GtkTreeIter iter; - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, bool(it->enabled()), - 1, it->name().c_str(), 2, it->alias().c_str(), -1); - } - } -#endif - - GtkWidget *view = gtk_tree_view_new_with_model (m_model); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); - gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), - GTK_SELECTION_NONE); - g_object_unref (G_OBJECT (m_model)); // tree view will take care of it - - // prepare the view - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - - renderer = gtk_cell_renderer_toggle_new(); - column = gtk_tree_view_column_new_with_attributes ("", - renderer, "active", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - g_signal_connect (G_OBJECT (renderer), "toggled", - G_CALLBACK (source_toggled_cb), this); - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes ("", - renderer, "text", 1, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - -#ifdef PRE_ZYPP_3 - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes ("", - renderer, "text", 2, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); -#endif - - m_widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request (m_widget, -1, ADVANCED_INFO_HEIGHT); - gtk_container_add (GTK_CONTAINER (m_widget), view); + m_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (m_window), "Changes"); + gtk_window_set_default_size (GTK_WINDOW (m_window), 200, 250); + + m_view = new PackagesView(); + Ypp::Query *query = new Ypp::Query (Ypp::Package::PACKAGE_TYPE); + query->setIsModified (true); + m_view->query (query); + m_view->setListener (this); + + GtkWidget *vbox = gtk_vbox_new (FALSE, 6), *undo_align; + m_undo_button = gtk_button_new_from_stock (GTK_STOCK_UNDO); + gtk_widget_set_sensitive (m_undo_button, FALSE); + g_signal_connect (G_OBJECT (m_undo_button), "clicked", + G_CALLBACK (undo_clicked_cb), this); + undo_align = gtk_alignment_new (1, 0, 0, 0); + gtk_container_add (GTK_CONTAINER (undo_align), m_undo_button); + + gtk_box_pack_start (GTK_BOX (vbox), m_view->getWidget(), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), undo_align, FALSE, FALSE, 0); + gtk_container_add (GTK_CONTAINER (m_window), vbox); + gtk_widget_show_all (m_window); } - GtkWidget *getWidget() - { return m_widget; } - -private: - static void source_toggled_cb (GtkCellRendererToggle *renderer, - gchar *path_str, SourcesTable *pThis) + ~TrashWindow() { - IMPL - GtkTreeModel *model = pThis->m_model; - GtkTreePath *path = gtk_tree_path_new_from_string (path_str); - GtkTreeIter iter; - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - -#ifdef PRE_ZYPP_3 - gchar *alias; - gtk_tree_model_get (model, &iter, 3, &alias, -1); - - zypp::SourceManager_Ptr manager = zypp::SourceManager::sourceManager(); - zypp::Source_Ref source = manager->findSource (alias); - g_free (alias); - - if (gtk_cell_renderer_toggle_get_active (renderer)) - source.disable(); - else - source.enable(); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - 0, source.enabled(), -1); -#else - gchar *alias; - gtk_tree_model_get (model, &iter, 2, &alias, -1); - - zypp::RepoManager manager; - zypp::RepoInfo repo = manager.getRepositoryInfo (alias); - g_free (alias); + delete m_view; + gtk_widget_destroy (m_window); + } - bool enable = !gtk_cell_renderer_toggle_get_active (renderer); - repo.setEnabled (enable); +private: +std::list <Ypp::Package *> m_selection; - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - 0, bool (repo.enabled()), -1); -#endif + virtual void packagesSelected (const std::list <Ypp::Package *> &selection) + { + gtk_widget_set_sensitive (m_undo_button, !selection.empty()); + m_selection = selection; + } - pThis->m_listener->sources_changed_cb(); + static void undo_clicked_cb (GtkButton *button, TrashWindow *pThis) + { + for (std::list <Ypp::Package *>::iterator it = pThis->m_selection.begin(); + it != pThis->m_selection.end(); it++) + (*it)->undo(); } }; -// Table widget to monitor disk partitions space-usage -#define MIN_FREE_MB_WARN (80*1024) +#include "icons/cat-development.xpm" +#include "icons/cat-documentation.xpm" +#include "icons/cat-emulators.xpm" +#include "icons/cat-games.xpm" +#include "icons/cat-hardware.xpm" +#include "icons/cat-network.xpm" +#include "icons/cat-multimedia.xpm" +#include "icons/cat-office.xpm" +#include "icons/cat-system.xpm" +#include "icons/cat-utilities.xpm" -class DiskTable +class Filters { - GtkWidget *m_widget; - GtkTreeModel *m_model; - bool m_has_warned; // only warn once - - // evil long names - typedef zypp::DiskUsageCounter::MountPoint ZyppDu; - typedef zypp::DiskUsageCounter::MountPointSet ZyppDuSet; - typedef zypp::DiskUsageCounter::MountPointSet::iterator ZyppDuSetIterator; - public: - DiskTable() - { - m_has_warned = false; - if (zypp::getZYpp()->diskUsage().empty()) - zypp::getZYpp()->setPartitions ( - zypp::DiskUsageCounter::detectMountPoints()); - - /* 0 - mount point (also used as id), 1 - percentage of disk usage - ([0, 100]), 2 - disk usage detail (i.e. "200Mb of 1Gb") */ - GtkListStore *store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_INT, - G_TYPE_STRING); - m_model = GTK_TREE_MODEL (store); - update(); - - GtkWidget *view = gtk_tree_view_new_with_model (m_model); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); - gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), - GTK_SELECTION_NONE); - g_object_unref (G_OBJECT (m_model)); // tree view will take care of it - - // prepare the view - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes (_("Mount Point"), - renderer, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - - renderer = gtk_cell_renderer_progress_new(); - column = gtk_tree_view_column_new_with_attributes (_("Usage"), - renderer, "value", 1, "text", 2, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + struct Listener { + virtual void doQuery (Ypp::Query *query) = 0; + }; + void setListener (Listener *listener) + { m_listener = listener; signalChanged(); } - m_widget = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request (m_widget, -1, ADVANCED_INFO_HEIGHT); - gtk_container_add (GTK_CONTAINER (m_widget), view); - } +private: + GtkWidget *m_widget, *m_name, *m_status, *m_categories, *m_repos, *m_type, + *m_categories_expander, *m_repos_expander; + Listener *m_listener; + guint timeout_id; + int repoToggled; // how many repos are toggled? if 0, it can speed up query + int packageType; +public: GtkWidget *getWidget() { return m_widget; } - static string sizeToString (long long size) + Filters() + : m_listener (NULL), timeout_id (0), repoToggled (0), packageType (-1) { - zypp::ByteCount count (size, zypp::ByteCount::K); - return count.asString(); + GtkWidget *vbox = gtk_vbox_new (FALSE, 4); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 6); + GtkSizeGroup *size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + m_name = ygtk_find_entry_new(); + g_signal_connect_after (G_OBJECT (m_name), "changed", + G_CALLBACK (entry_changed_cb), this); + gtk_box_pack_start (GTK_BOX (vbox), + labelWidget (_("Name: "), m_name, size_group), FALSE, TRUE, 0); + + m_status = gtk_combo_box_new_text(); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_status), _("All")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_status), _("Installed")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_status), _("Upgradable")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_status), _("Available")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_status), _("Modified")); + gtk_combo_box_set_active (GTK_COMBO_BOX (m_status), 0); + g_signal_connect_after (G_OBJECT (m_status), "changed", + G_CALLBACK (combo_changed_cb), this); + gtk_box_pack_start (GTK_BOX (vbox), + labelWidget (_("Status: "), m_status, size_group), FALSE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (vbox), buildCategories(), FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), buildRepos(), FALSE, TRUE, 0); + + m_type = gtk_combo_box_new_text(); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_type), _("Packages")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_type), _("Patterns")); + gtk_combo_box_append_text (GTK_COMBO_BOX (m_type), _("Languages")); + gtk_combo_box_set_active (GTK_COMBO_BOX (m_type), 0); + g_signal_connect_after (G_OBJECT (m_type), "changed", + G_CALLBACK (combo_changed_cb), this); + gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (""), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), + labelWidget (_("Type: "), m_type, size_group), FALSE, TRUE, 0); + + m_widget = gtk_notebook_new(); + gtk_notebook_append_page (GTK_NOTEBOOK (m_widget), vbox, + gtk_label_new (_("Filters"))); + g_object_unref (G_OBJECT (size_group)); } - void update() + ~Filters() { - GtkListStore *store = GTK_LIST_STORE (m_model); - gtk_list_store_clear (store); - - bool warning = false; - ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage(); - for (ZyppDuSetIterator it = diskUsage.begin(); it != diskUsage.end(); it++) { - const ZyppDu &partition = *it; - if (!partition.readonly) { - // partition fields: dir, used_size, total_size (size on Kb) - GtkTreeIter iter; - gtk_list_store_append (store, &iter); - - long usage = (partition.pkg_size * 100) / (partition.total_size + 1); - string usage_str = sizeToString (partition.pkg_size) + " (of " + - sizeToString (partition.total_size) + ")"; - gtk_list_store_set (store, &iter, 0, partition.dir.c_str(), - 1, usage, 2, usage_str.c_str(), -1); - - warning = warning || - (partition.total_size > 1024 && - partition.total_size - partition.pkg_size < MIN_FREE_MB_WARN); - } - } - if (warning) - warn(); + if (timeout_id) g_source_remove (timeout_id); } - void warn() +private: + static void entry_changed_cb (GtkEditable *editable, Filters *pThis) + { pThis->signalChangedDelay(); } + static void combo_changed_cb (GtkComboBox *combo, Filters *pThis) + { pThis->signalChanged(); } + + void signalChanged() { - if (m_has_warned) - return; - m_has_warned = true; + if (!m_listener) return; - GtkWidget *dialog, *view, *scroll_view; - dialog = gtk_message_dialog_new_with_markup (YGUI::ui()->currentWindow(), - GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, _("<b>Disk Almost Full !</b>\n\n" - "One of the partitions is reaching its limit of capacity. You may " - "have to remove packages if you wish to install some.")); + Ypp::Package::Type type; + switch (gtk_combo_box_get_active (GTK_COMBO_BOX (m_type))) + { + case 0: default: type = Ypp::Package::PACKAGE_TYPE; break; + case 1: type = Ypp::Package::PATTERN_TYPE; break; + case 2: type = Ypp::Package::LANGUAGE_TYPE; break; + + } - view = gtk_tree_view_new_with_model (m_model); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); - gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), - GTK_SELECTION_NONE); + Ypp::Query *query = new Ypp::Query (type); - GtkTreeViewColumn *column; - column = gtk_tree_view_column_new_with_attributes (_("Mount Point"), - gtk_cell_renderer_text_new(), "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - column = gtk_tree_view_column_new_with_attributes (_("Usage"), - gtk_cell_renderer_progress_new(), - "value", 1, "text", 2, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + const char *name = gtk_entry_get_text (GTK_ENTRY (m_name)); + if (*name) + query->setName (std::string (name)); + switch (gtk_combo_box_get_active (GTK_COMBO_BOX (m_status))) + { + case 1: query->setIsInstalled (true); break; + case 2: query->setHasUpgrade (true); break; + case 3: query->setIsInstalled (false); break; + case 4: query->setIsModified (true); break; + case 0: default: break; + + } - scroll_view = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_view), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request (scroll_view, -1, 80); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll_view), - GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (scroll_view), view); - gtk_widget_show_all (scroll_view); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scroll_view); + { + GtkTreeSelection *selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (m_categories)); + GtkTreeModel *model; + GtkTreeIter iter; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + Ypp::Node *category; + gtk_tree_model_get (model, &iter, 1, &category, -1); + if (category) + query->setCategory (category); + } + } - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - } -}; + if (repoToggled) { + std::list <int> reposQuery; + GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_repos)); + GtkTreeIter iter; + if (gtk_tree_model_get_iter_first (model, &iter)) { + do { + gboolean enabled; + gint repo; + gtk_tree_model_get (model, &iter, 0, &enabled, 2, &repo, -1); + if (enabled) + reposQuery.push_back (repo); + } while (gtk_tree_model_iter_next (model, &iter)); + } + query->setRepositories (reposQuery); + } -// YOU patch selector -class YGPatchSelector : public YPackageSelector, public YGWidget -{ - GtkWidget *m_patches_view; - GtkTreeModel *m_patches_model; // GtkListStore type + m_listener->doQuery (query); + updateCategories (type); + } - // Package information widget - PackageInformation *m_information_widget; + void signalChangedDelay() + { + struct inner { + static gboolean timeout_cb (gpointer data) + { + Filters *pThis = (Filters *) data; + pThis->timeout_id = 0; + pThis->signalChanged(); + return FALSE; + } + }; + if (timeout_id) g_source_remove (timeout_id); + timeout_id = g_timeout_add (500, inner::timeout_cb, this); + } -public: - YGPatchSelector (const YWidgetOpt &opt, YGWidget *parent) - : YPackageSelector (opt), - YGWidget (this, parent, true, YGTK_TYPE_WIZARD, NULL) + void updateCategories (Ypp::Package::Type type) { - setBorder (0); - GtkWidget *main_vbox = gtk_vbox_new (FALSE, 0); + if (packageType == type) + return; + packageType = type; - YGtkWizard *wizard = YGTK_WIZARD (getWidget()); - ygtk_wizard_set_child (YGTK_WIZARD (getWidget()), main_vbox); - GtkWindow *window = YGUI::ui()->currentWindow(); - ygtk_wizard_set_header_text (wizard, window, _("Patch Selector")); - ygtk_wizard_set_header_icon (wizard, window, - THEMEDIR "/icons/32x32/apps/yast-software.png"); - ygtk_wizard_set_help_text (wizard, - _("For information on a given patch, just press it and as well as the " - "Package Information expander to make those informations visible.<br>" - "To install a patch you just need to press the check button next to it " - "and then the button Install when you are done.") - ); - ygtk_wizard_set_next_button_label (wizard, _("_Install")); - ygtk_wizard_set_next_button_id (wizard, g_strdup ("install"), g_free); - ygtk_wizard_set_abort_button_label (wizard, _("_Cancel")); - ygtk_wizard_set_abort_button_id (wizard, g_strdup ("cancel"), g_free); - g_signal_connect (G_OBJECT (getWidget()), "action-triggered", - G_CALLBACK (wizard_action_cb), this); + GtkTreeModel *model = NULL; - m_patches_view = gtk_tree_view_new(); - GtkWidget *patches_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type - (GTK_SCROLLED_WINDOW (patches_window), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (patches_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add (GTK_CONTAINER (patches_window), m_patches_view); - - m_information_widget = new PackageInformation (_("Patch Information"), true); - GtkWidget *pkg_info_widget = m_information_widget->getWidget(); - - gtk_box_pack_start (GTK_BOX (main_vbox), patches_window, TRUE, TRUE, 6); - gtk_box_pack_start (GTK_BOX (main_vbox), pkg_info_widget, FALSE, FALSE, 6); - gtk_widget_show_all (main_vbox); - - // Create a model for the patches lists - // models' columns: selected radio button state (boolean), - // package name (string), patch priority (string), selectable object (pointer) - m_patches_model = GTK_TREE_MODEL (gtk_list_store_new - (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER)); + if (type == Ypp::Package::PACKAGE_TYPE) { + struct inner { + static void populate (GtkTreeStore *store, GtkTreeIter *parent, + Ypp::Node *category) + { + if (!category) + return; + GtkTreeIter iter; + gtk_tree_store_append (store, &iter, parent); + const std::string &name = category->name; + gtk_tree_store_set (store, &iter, 0, name.c_str(), 1, category, -1); + if (!parent) { + const char **icon = 0; + if (name == "Development") + icon = cat_development_xpm; + else if (name == "Documentation") + icon = cat_documentation_xpm; + else if (name == "Emulators") + icon = cat_emulators_xpm; + else if (name == "Games") + icon = cat_games_xpm; + else if (name == "Hardware") + icon = cat_hardware_xpm; + else if (name == "Multimedia") + icon = cat_multimedia_xpm; + else if (name == "Network") + icon = cat_network_xpm; + else if (name == "Office") + icon = cat_office_xpm; + else if (name == "System") + icon = cat_system_xpm; + else if (name == "Utilities") + icon = cat_utilities_xpm; + if (icon) { + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (icon); + gtk_tree_store_set (store, &iter, 2, pixbuf, -1); + } + } + populate (store, &iter, category->child()); + populate (store, parent, category->next()); + } + }; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new(); - column = gtk_tree_view_column_new_with_attributes ("", renderer, - "active", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (m_patches_view), column); - g_signal_connect (G_OBJECT (renderer), "toggled", - G_CALLBACK (patch_toggled_cb), this); + GtkTreeStore *store = gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_POINTER, + GDK_TYPE_PIXBUF); + model = GTK_TREE_MODEL (store); - column = gtk_tree_view_column_new_with_attributes (_("Priority"), - gtk_cell_renderer_text_new(), "text", 1, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (m_patches_view), column); - - column = gtk_tree_view_column_new_with_attributes (_("Name"), - gtk_cell_renderer_text_new(), "text", 2, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (m_patches_view), column); - - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Patch>(); - it != zyppPool().byKindEnd <zypp::Patch>(); it++) { - ZyppSelectable selectable = *it; - ZyppPatch patch = tryCastToZyppPatch (selectable->theObj()); - if (!patch) - continue; - bool displayPatch = false; - - // These rules are taken from YQPkgPatchList::fillList() in the RelevantPatches case - if (selectable->hasInstalledObj()) { // installed? - if (selectable->installedPoolItem().status().isIncomplete()) { // patch broken? - // The patch is broken: It had been installed, but the user somehow - // downgraded individual packages belonging to the patch to older versions. - displayPatch = true; - - y2warning( "Installed patch is broken: %s - %s", - patch->name().c_str(), - patch->summary().c_str() ); - } - } else { // not installed - if (selectable->hasCandidateObj() && selectable->candidatePoolItem().status().isSatisfied()) { - // This is a pretty exotic case, but still it might happen: - // - // The patch itelf is not installed, but it is satisfied because the - // user updated all the packages belonging to the patch to the versions - // the patch requires. All that is missing now is to get the patch meta - // data onto the system. So let's display the patch to give the user - // a chance to install it (if he so chooses). - - displayPatch = true; - - y2milestone( "Patch satisfied, but not installed yet: %s - %s", - patch->name().c_str(), - patch->summary().c_str() ); - } - } + GtkTreeIter iter; + gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_set (store, &iter, 0, _("All"), 1, NULL, -1); - if (selectable->hasCandidateObj()) { // candidate available? - // The most common case: There is a candidate patch, i.e. one that could be - // installed, but either no version of that patch is installed or there is a - // newer one to which the patch could be updated. - - if (selectable->candidatePoolItem().status().isNeeded()) { // patch really needed? - // Patches are needed if any of the packages that belong to the patch - // are installed on the system. - - displayPatch = true; - } else { - // None of the packages that belong to the patch is installed on the system. - - y2debug( "Patch not needed: %s - %s", - patch->name().c_str(), - patch->summary().c_str() ); - } - } + inner::populate (store, NULL, Ypp::get()->getFirstCategory (type)); - if (displayPatch) { - // select them all - selectable->set_status (zypp::ui::S_Install); + } + else if (type == Ypp::Package::PATTERN_TYPE) { + GtkListStore *store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_POINTER, + GDK_TYPE_PIXBUF); + model = GTK_TREE_MODEL (store); - GtkTreeIter iter; - GtkListStore *store = GTK_LIST_STORE (m_patches_model); + GtkTreeIter iter; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, _("All"), 1, NULL, -1); + + for (Ypp::Node *i = Ypp::get()->getFirstCategory (type); i; i = i->next()) { gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, selectable->toInstall(), - 1, patch->category().c_str(), 2, selectable->name().c_str(), - 3, get_pointer (selectable), -1); + gtk_list_store_set (store, &iter, 0, i->name.c_str(), 1, i, -1); } } - gtk_tree_view_set_model (GTK_TREE_VIEW (m_patches_view), m_patches_model); + GtkTreeSelection *selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (m_categories)); + g_signal_handlers_block_by_func (selection, + (gpointer) categories_selection_cb, this); - // TODO: severity should be sort by severity, not alphabetically - YGUtils::tree_view_set_sortable (GTK_TREE_VIEW (m_patches_view), 1); + gtk_tree_view_set_model (GTK_TREE_VIEW (m_categories), model); + if (model) { + g_object_unref (G_OBJECT (model)); + gtk_widget_show (m_categories_expander); - gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_patches_view), 2); + /* we use gtk_tree_view_set_cursor(), rather than gtk_tree_selection_select_iter() + because that one is buggy in that when the user first interacts with the treeview, + a change signal is sent, even if he was just expanding one node... */ + GtkTreePath *path = gtk_tree_path_new_first(); + gtk_tree_view_set_cursor (GTK_TREE_VIEW (m_categories), path, NULL, FALSE); + gtk_tree_path_free (path); + } + else + gtk_widget_hide (m_categories_expander); - g_signal_connect (G_OBJECT (m_patches_view), "cursor-changed", - G_CALLBACK (patch_clicked_cb), this); + g_signal_handlers_unblock_by_func (selection, + (gpointer) categories_selection_cb, this); } - virtual ~YGPatchSelector() + GtkWidget *buildCategories() { - IMPL - g_object_unref (m_patches_model); - delete m_information_widget; + GtkWidget *scroll; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + m_categories = gtk_tree_view_new(); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (m_categories), FALSE); + gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_categories), 0); + renderer = gtk_cell_renderer_pixbuf_new(); + column = gtk_tree_view_column_new_with_attributes ("", + renderer, "pixbuf", 2, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (m_categories), column); + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes ("", + renderer, "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (m_categories), column); + + GtkTreeSelection *selection = gtk_tree_view_get_selection ( + GTK_TREE_VIEW (m_categories)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + g_signal_connect (G_OBJECT (selection), "changed", + G_CALLBACK (categories_selection_cb), this); + + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), + GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_widget_set_size_request (scroll, -1, 200); + gtk_container_add (GTK_CONTAINER (scroll), m_categories); + + m_categories_expander = gtk_expander_new (_("Categories")); + gtk_container_add (GTK_CONTAINER (m_categories_expander), scroll); + gtk_expander_set_expanded (GTK_EXPANDER (m_categories_expander), TRUE); + return m_categories_expander; } - static ZyppSelectablePtr selectedPatch (GtkTreeView *tree_view) + GtkWidget *buildRepos() { - IMPL - GtkTreePath *path; + GtkWidget *scroll; + GtkListStore *store; GtkTreeViewColumn *column; - gtk_tree_view_get_cursor (tree_view, &path, &column); - if (path) { - GtkTreeModel *model = gtk_tree_view_get_model (tree_view); + GtkCellRenderer *renderer; - ZyppSelectablePtr selectable = 0; + // 0 - enabled, 1 - name, 2 - ptr + store = gtk_list_store_new (3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_INT); + for (int i = 0; Ypp::get()->getRepository (i); i++) { + const Ypp::Repository *repo = Ypp::get()->getRepository (i); GtkTreeIter iter; - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, 3, &selectable, -1); - - gtk_tree_path_free (path); - return selectable; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, TRUE, 1, repo->name.c_str(), 2, i, -1); } - return NULL; - } + m_repos = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (m_repos), FALSE); + gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_repos), 1); + gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (m_repos)), + GTK_SELECTION_NONE); + g_object_unref (G_OBJECT (store)); + renderer = gtk_cell_renderer_toggle_new(); + column = gtk_tree_view_column_new_with_attributes ("", renderer, "active", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (m_repos), column); + g_signal_connect (G_OBJECT (renderer), "toggled", + G_CALLBACK (repo_toggled_cb), this); + g_signal_connect (G_OBJECT (m_repos), "row-activated", + G_CALLBACK (repo_clicked_cb), this); + renderer = gtk_cell_renderer_text_new(); + g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); + column = gtk_tree_view_column_new_with_attributes ("", + renderer, "text", 1, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (m_repos), column); - // callbacks - static void patch_clicked_cb (GtkTreeView *tree_view, YGPatchSelector *pThis) - { - IMPL - ZyppSelectablePtr sel = selectedPatch (tree_view); - pThis->m_information_widget->setPackage (sel, sel->theObj()); + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), + GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_widget_set_size_request (scroll, -1, 80); + gtk_container_add (GTK_CONTAINER (scroll), m_repos); + + m_repos_expander = gtk_expander_new (_("Repositories")); + gtk_container_add (GTK_CONTAINER (m_repos_expander), scroll); + return m_repos_expander; } - static void wizard_action_cb (YGtkWizard *wizard, gpointer id, - gint id_type, YGPatchSelector *pThis) + static void categories_selection_cb (GtkTreeSelection *selection, Filters *pThis) { - const gchar *action = (gchar *) id; - if (!strcmp (action, "install")) { - y2milestone ("Closing PackageSelector with 'accept'"); - if (solveProblems()) - YGUI::ui()->sendEvent (new YMenuEvent (YCPSymbol ("accept"))); - } - else if (!strcmp (action, "cancel")) { - y2milestone ("Closing PackageSelector with 'cancel'"); - YGUI::ui()->sendEvent (new YCancelEvent()); - } +fprintf (stderr, "CATEGORIES SELECTED\n"); + pThis->signalChanged(); } - static void patch_toggled_cb (GtkCellRendererToggle *renderer, - gchar *path_str, YGPatchSelector *pThis) + void toggle_repo (GtkTreePath *path) { IMPL - GtkTreeModel *model = pThis->m_patches_model; - - // Toggle the box - GtkTreePath *path = gtk_tree_path_new_from_string (path_str); - gint *column = (gint*) g_object_get_data (G_OBJECT (renderer), "column"); + GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_repos)); + GtkListStore *store = GTK_LIST_STORE (model); GtkTreeIter iter; gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - gboolean state; - ZyppSelectablePtr selectable = 0; - gtk_tree_model_get (model, &iter, 0, &state, 3, &selectable, -1); - - state = !state; - if (mark_selectable (selectable, state)) - gtk_list_store_set (GTK_LIST_STORE (model), &iter, column, state, -1); + gboolean enabled; + gtk_tree_model_get (model, &iter, 0, &enabled, -1); + gtk_list_store_set (store, &iter, 0, !enabled, -1); + if (enabled) repoToggled--; else repoToggled++; +fprintf (stderr, "repoToggled count: %d\n", repoToggled); + signalChanged(); } - YGWIDGET_IMPL_COMMON -}; - -// Package selector's widget -class PackageSelector : public SourcesTableListener -{ - -enum package_columns -{ - COL_SELECTABLE = 0, // selectable object (pointer) - COL_INSTALLED_NAME, // installed name (string) - COL_AVAILABLE_NAME, // available_name (string) - COL_IS_INSTALLED, // is installed (boolean) - COL_IS_AVAILABLE, // is available (boolean) - COL_CAN_BE_UPGRADED, // can be upgraded (boolean) - COL_CAN_BE_DOWNGRADED, // can be downgraded (boolean) - COL_SHOW_UPGRADABLE_CONTROL, // show up/downgrade control (boolean) - COL_HAS_CHILDREN, // has children - COL_FONT_STYLE // font style; italic for modified (integer) = 10 -}; - -friend class YGPackageSelector; - - GtkWidget *m_widget; - - // The GtkTreeView widgets - GtkWidget *m_installed_view, *m_available_view; - // Packages backend model - GtkTreeModel *m_packages_model; - - // Package information widget - PackageInformation *m_information_widget; - SourcesTable *m_sources_table; - DiskTable *m_disk_table; - - // Search gizmos - GtkWidget *m_search_entry, *m_plain_view; - guint search_timeout_id; - bool name_opt, summary_opt, descr_opt, provides_opt, requires_opt; - list <string> m_search_queries; - - // Interface tweak - GtkWidget *m_install_label, *m_remove_label; - -public: - PackageSelector (bool patterns_mode) + static void repo_toggled_cb (GtkCellRendererToggle *renderer, + gchar *path_str, Filters *pThis) { IMPL - m_widget = gtk_vbox_new (FALSE, 0); - - GtkWidget *packages_hbox = gtk_hbox_new (FALSE, 0); - - GtkWidget *available_box, *installed_box; - /* All views share a similar model structure. There is a common model for - all packages, where filters are installed upon to split it on two, each - installed on the tree view. The common model follows the following spec: - 0 - selectable object (pointer), 1 - installed name (string), 2 - available - name (string), 3 - is installed (boolean), 4 - is available (boolean), - 5 - can be upgraded (boolean), 6 - can be downgraded (boolean), - 7 - show up/downgrade control (boolean), 8 - has children, - 9 - font style; italic for modified (integer) = 10 - - Models are created at each view mode change (and the other freed). This - allows for more than one model type be used and is also better for speed, - since the filter and tree view then installed upon don't have to keep - syncing at every item change. */ - installed_box = createListWidget (_("<b>Installed Software:</b>"), - "computer", computer_xpm, m_installed_view, - 1, false); - available_box = createListWidget (_("<b>Available Software:</b>"), - "gtk-cdrom", NULL, m_available_view, - 2, true); - - /* FIXME: it seems (due to markup or something) search, this won't work. - Not really a issue as we provide searching, but... - gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_installed_view), 0); - gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_available_view), 0); */ - gtk_tree_view_set_enable_search (GTK_TREE_VIEW (m_installed_view), FALSE); - gtk_tree_view_set_enable_search (GTK_TREE_VIEW (m_available_view), FALSE); - - gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (m_installed_view)), GTK_SELECTION_MULTIPLE); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (m_available_view)), GTK_SELECTION_MULTIPLE); - - GtkWidget *buttons_minsize, *selection_buttons_vbox, *install_button, - *remove_button; - selection_buttons_vbox = gtk_vbox_new (TRUE, 80); - // to avoid re-labeling glitches, let it only grow - buttons_minsize = ygtk_adj_size_new(); - gtk_container_add (GTK_CONTAINER (buttons_minsize), selection_buttons_vbox); - ygtk_adj_size_set_only_expand (YGTK_ADJ_SIZE (buttons_minsize), TRUE); - - install_button = createArrowButton (_("_install"), GTK_ARROW_RIGHT, &m_install_label); - remove_button = createArrowButton (_("_remove"), GTK_ARROW_LEFT, &m_remove_label); - - GtkWidget *install_align = gtk_alignment_new (0, 1, 1, 0); - gtk_container_add (GTK_CONTAINER (install_align), install_button); - GtkWidget *remove_align = gtk_alignment_new (0, 0, 1, 0); - gtk_container_add (GTK_CONTAINER (remove_align), remove_button); - - gtk_box_pack_start (GTK_BOX (selection_buttons_vbox), install_align, - TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (selection_buttons_vbox), remove_align, - TRUE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER (selection_buttons_vbox), 6); - - gtk_box_pack_start (GTK_BOX (packages_hbox), available_box, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (packages_hbox), buttons_minsize, - FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (packages_hbox), installed_box, TRUE, TRUE, 0); - - GtkWidget *view_box, *view_label, *view_categories, *view_patterns, - *view_languages; - view_label = gtk_label_new (_("View Packages:")); - gtk_label_set_use_markup (GTK_LABEL (view_label), TRUE); - gtk_misc_set_alignment (GTK_MISC (view_label), 0, 0.5); - m_plain_view = gtk_radio_button_new_with_mnemonic (NULL, _("as _plain list")); - view_categories = gtk_radio_button_new_with_mnemonic_from_widget - (GTK_RADIO_BUTTON (m_plain_view), _("in _categories")); - view_patterns = gtk_radio_button_new_with_mnemonic_from_widget - (GTK_RADIO_BUTTON (m_plain_view), _("in _patterns")); - view_languages = gtk_radio_button_new_with_mnemonic_from_widget - (GTK_RADIO_BUTTON (m_plain_view), _("in _languages")); - view_box = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (view_box), view_label, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (view_box), m_plain_view, FALSE, TRUE, 4); - gtk_box_pack_start (GTK_BOX (view_box), view_categories, FALSE, TRUE, 4); - gtk_box_pack_start (GTK_BOX (view_box), view_patterns, FALSE, TRUE, 4); - gtk_box_pack_start (GTK_BOX (view_box), view_languages, FALSE, TRUE, 4); - g_signal_connect (G_OBJECT (m_plain_view), "toggled", - G_CALLBACK (view_plain_mode_cb), this); - g_signal_connect (G_OBJECT (view_categories), "toggled", - G_CALLBACK (view_categories_mode_cb), this); - g_signal_connect (G_OBJECT (view_patterns), "toggled", - G_CALLBACK (view_patterns_mode_cb), this); - g_signal_connect (G_OBJECT (view_languages), "toggled", - G_CALLBACK (view_languages_mode_cb), this); - - // default search fields - name_opt = summary_opt = provides_opt = true; - requires_opt = descr_opt = false; - - GtkWidget *search_hbox, *search_label; - search_hbox = gtk_hbox_new (FALSE, 0); - search_label = gtk_label_new_with_mnemonic (_("_Search:")); - gtk_label_set_use_markup (GTK_LABEL (search_label), TRUE); - gtk_misc_set_alignment (GTK_MISC (search_label), 0, 0.5); - m_search_entry = ygtk_find_entry_new(); - gtk_label_set_mnemonic_widget (GTK_LABEL (search_label), m_search_entry); - gtk_box_pack_start (GTK_BOX (search_hbox), search_label, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (search_hbox), m_search_entry, TRUE, TRUE, 4); - search_timeout_id = 0; - g_signal_connect (G_OBJECT (m_search_entry), "activate", // when Enter - G_CALLBACK (search_activate_cb), this); // is pressed - g_signal_connect_after (G_OBJECT (m_search_entry), "changed", - G_CALLBACK (search_request_cb), this); - ygtk_find_entry_attach_menu (YGTK_FIND_ENTRY (m_search_entry), - create_search_menu()); - - /* we want "View Packages" to be aligned to "Search"; we could use a - GtkTable for that, but a GtkSizeGroup does the job with less hassle. */ - GtkSizeGroup *align_labels = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); - gtk_size_group_add_widget (align_labels, view_label); - gtk_size_group_add_widget (align_labels, search_label); - g_object_unref (G_OBJECT (align_labels)); - - m_information_widget = new PackageInformation (_("Package Information"), false); - GtkWidget *pkg_info_widget = m_information_widget->getWidget(); - - m_sources_table = new SourcesTable (this); - m_disk_table = new DiskTable(); - - GtkWidget *advanced_expander = gtk_expander_new (_("Advanced")); - GtkWidget *advanced_notebook = gtk_notebook_new(); - GtkWidget *sources_vbox = gtk_vbox_new (FALSE, 4); - GtkWidget *sources_label = gtk_label_new ( - _("<i>Use the Software Repositories tool to manage the sources.</i>")); - gtk_misc_set_alignment (GTK_MISC (sources_label), 1, 0); - gtk_label_set_use_markup (GTK_LABEL (sources_label), TRUE); - gtk_box_pack_start (GTK_BOX (sources_vbox), m_sources_table->getWidget(), - TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (sources_vbox), sources_label, TRUE, TRUE, 0); - gtk_notebook_set_tab_pos (GTK_NOTEBOOK (advanced_notebook), GTK_POS_BOTTOM); - gtk_notebook_append_page (GTK_NOTEBOOK (advanced_notebook), - sources_vbox, gtk_label_new (_("Repositories"))); - gtk_notebook_append_page (GTK_NOTEBOOK (advanced_notebook), - m_disk_table->getWidget(), gtk_label_new (_("Disk Usage"))); - gtk_container_add (GTK_CONTAINER (advanced_expander), advanced_notebook); - - gtk_box_pack_start (GTK_BOX (m_widget), packages_hbox, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (m_widget), view_box, FALSE, FALSE, 12); - gtk_box_pack_start (GTK_BOX (m_widget), search_hbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (m_widget), pkg_info_widget, FALSE, FALSE, 12); - gtk_box_pack_start (GTK_BOX (m_widget), advanced_expander, FALSE, FALSE, 0); - gtk_widget_show_all (m_widget); - - g_object_ref (G_OBJECT (m_widget)); - gtk_object_sink (GTK_OBJECT (m_widget)); - - // interface sugar - g_signal_connect (G_OBJECT (install_button), "clicked", - G_CALLBACK (install_button_clicked_cb), this); - g_signal_connect (G_OBJECT (remove_button), "clicked", - G_CALLBACK (remove_button_clicked_cb), this); - - g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW ( - m_installed_view))), "changed", - G_CALLBACK (package_clicked_cb), this); - g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW ( - m_available_view))), "changed", - G_CALLBACK (package_clicked_cb), this); - - // signal for default view - if (patterns_mode) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view_patterns), TRUE); - else - g_signal_emit_by_name (G_OBJECT (m_plain_view), "toggled", this); + GtkTreePath *path = gtk_tree_path_new_from_string (path_str); + pThis->toggle_repo (path); + gtk_tree_path_free (path); } - // create widgets functions to cut down on code - GtkWidget *createListWidget (const char *header, const char *stock_icon, - const char **xpm_icon, GtkWidget *&list, int package_name_col, - bool has_version_col) + static void repo_clicked_cb (GtkTreeView *view, GtkTreePath *path, + GtkTreeViewColumn *column, Filters *pThis) { - GtkWidget *vbox, *header_hbox, *image, *label, *scrolled_window; - - vbox = gtk_vbox_new (FALSE, 0); - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type - (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - list = gtk_tree_view_new(); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (list), TRUE); - gtk_tree_selection_set_select_function (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (list)), dont_select_groups_cb, this, NULL); - gtk_container_add (GTK_CONTAINER (scrolled_window), list); - - header_hbox = gtk_hbox_new (FALSE, 0); - image = NULL; - if (stock_icon) - image = gtk_image_new_from_icon_name (stock_icon, GTK_ICON_SIZE_BUTTON); - if ((!stock_icon || gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY) - && xpm_icon) { - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (xpm_icon); - image = gtk_image_new_from_pixbuf (pixbuf); - g_object_unref (G_OBJECT (pixbuf)); - } - label = gtk_label_new_with_mnemonic (header); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), list); - if (image) - gtk_box_pack_start (GTK_BOX (header_hbox), image, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (header_hbox), label, FALSE, FALSE, 4); - - gtk_box_pack_start (GTK_BOX (vbox), header_hbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 4); - - // The treeview model will be built according to the view... Columns - // and renderers are common anyway... - GtkCellRenderer *text_renderer = gtk_cell_renderer_text_new(); - g_object_set (G_OBJECT (text_renderer), - "ellipsize", PANGO_ELLIPSIZE_END, NULL); - GtkTreeViewColumn *column; - column = gtk_tree_view_column_new_with_attributes (_("Packages"), - text_renderer, "markup", package_name_col, "style", 9, NULL); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); - // versions combo column - if (has_version_col) { - GtkCellRenderer *arrow_renderer = ygtk_cell_renderer_arrow_new(); - column = gtk_tree_view_column_new_with_attributes (NULL, - arrow_renderer, "can-go-up", 5, "can-go-down", 6, "visible", 7, NULL); - gtk_tree_view_column_set_expand (column, FALSE); - gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); - g_signal_connect (G_OBJECT (arrow_renderer), "pressed", - G_CALLBACK (change_available_version_cb), this); - } - return vbox; - } - - GtkWidget *createArrowButton (const char *label, GtkArrowType arrow_type, - GtkWidget **label_widget) - { - GtkWidget *button, *box = gtk_hbox_new (FALSE, 0); - GtkWidget *arrow = gtk_arrow_new (arrow_type, GTK_SHADOW_OUT); - gtk_container_add (GTK_CONTAINER (box), arrow); - *label_widget = gtk_label_new_with_mnemonic (label); - gtk_container_add (GTK_CONTAINER (box), *label_widget); - gtk_box_set_child_packing (GTK_BOX (box), arrow, FALSE, TRUE, 0, - arrow_type == GTK_ARROW_LEFT ? GTK_PACK_START : GTK_PACK_END); - - button = gtk_button_new(); - gtk_container_add (GTK_CONTAINER (button), box); - return button; + IMPL + pThis->toggle_repo (path); } - // Dynamic views support - void load_packages_view (GtkTreeModel *(* build_model) (GtkProgressBar *)) - { - GtkWidget *dialog, *label, *vbox, *progress = 0; - dialog = gtk_dialog_new(); - gtk_window_set_title (GTK_WINDOW (dialog), ""); - gtk_window_set_transient_for (GTK_WINDOW (dialog), - YGUI::ui()->currentWindow()); - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - gtk_window_set_default_size (GTK_WINDOW (dialog), 100, -1); - gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - vbox = GTK_DIALOG (dialog)->vbox; -// gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); - label = gtk_label_new (_("Loading packages list...")); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0); - gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 4); - progress = gtk_progress_bar_new(); - gtk_box_pack_start (GTK_BOX (vbox), progress, TRUE, FALSE, 4); - gtk_widget_show_all (dialog); - - gtk_tree_view_set_model (GTK_TREE_VIEW (m_installed_view), NULL); - gtk_tree_view_set_model (GTK_TREE_VIEW (m_available_view), NULL); - m_information_widget->setPackage (NULL, NULL); - - GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (progress); - // build it - GtkTreeModel *model = (m_packages_model = build_model (progress_bar)); - - GtkTreeModel *installed_model, *available_model; - installed_model = gtk_tree_model_filter_new (model, NULL); - available_model = gtk_tree_model_filter_new (model, NULL); - g_object_unref (G_OBJECT (model)); - - gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER ( - installed_model), is_package_installed, this, NULL); - gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER ( - available_model), is_package_available, this, NULL); - - gtk_tree_view_set_model (GTK_TREE_VIEW (m_installed_view), installed_model); - gtk_tree_view_set_model (GTK_TREE_VIEW (m_available_view), available_model); - g_object_unref (G_OBJECT (installed_model)); - g_object_unref (G_OBJECT (available_model)); - - // use the "available" name to do the sorting - GtkTreeSortable *sortable = GTK_TREE_SORTABLE (model); - gtk_tree_sortable_set_sort_func (sortable, COL_AVAILABLE_NAME, - YGUtils::sort_compare_cb, - GINT_TO_POINTER (COL_AVAILABLE_NAME), - NULL); - gtk_tree_sortable_set_sort_column_id (sortable, COL_AVAILABLE_NAME, - GTK_SORT_ASCENDING); - - gtk_widget_destroy (dialog); + // utility + static GtkWidget *labelWidget (const char *label_str, GtkWidget *widget, + GtkSizeGroup *group) + { + GtkWidget *hbox = gtk_hbox_new (FALSE, 0); + GtkWidget *label = gtk_label_new_with_mnemonic (label_str); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0); + gtk_size_group_add_widget (group, label); + return hbox; } +}; - // macros to handle progress bar - #define SET_PROGRESS(_steps, _jump) int steps = _steps, step = 0, jump = _jump; - #define PROGRESS() \ - if (progress && ((step++) % jump == 0)) { \ - gdouble fraction = steps > 0 ? ((gdouble) step) / steps : 0; \ - gtk_progress_bar_set_fraction (progress, fraction); \ - while (gtk_events_pending()) gtk_main_iteration(); } - - static GtkTreeModel *loadPackagesListAsPlain (GtkProgressBar *progress) - { - GtkListStore *store = gtk_list_store_new (10, G_TYPE_POINTER, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT); - GtkTreeModel *model = GTK_TREE_MODEL (store); - g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (1)); - - SET_PROGRESS (zyppPool().size <zypp::Package>(), 200) - GtkTreeIter iter; - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>(); - it != zyppPool().byKindEnd <zypp::Package>(); it++) - { - ZyppSelectable selectable = *it; - gtk_list_store_append (store, &iter); - loadPackageRow (model, &iter, selectable); - PROGRESS() - } - return model; - } +#include "icons/pkg-locked.xpm" +#include "icons/pkg-unlocked.xpm" - static GtkTreeModel *loadPackagesListByCategory (GtkProgressBar *progress) - { - GtkTreeStore *store = gtk_tree_store_new (10, G_TYPE_POINTER, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT); - GtkTreeModel *model = GTK_TREE_MODEL (store); - g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (1)); +class PackageControl +{ +GtkWidget *m_vbox, *m_status, *m_lock_button, *m_locked_image, *m_unlocked_image, + *m_installed_box, *m_available_box, *m_remove_button, *m_install_button, + *m_undo_button, *m_versions_combo, *m_version_repo; +GtkTreeModel *m_versions_model; - // we need to create the categories tree as we iterate packages - map <string, GtkTreePath *> tree; +public: +std::list <Ypp::Package *> m_packages; - SET_PROGRESS (zyppPool().size <zypp::Package>(), 80) - GtkTreeIter iter, parent_iter; - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>(); - it != zyppPool().byKindEnd <zypp::Package>(); it++) - { - ZyppSelectable selectable = *it; - ZyppObject object = selectable->theObj(); + GtkWidget *getWidget() + { return m_vbox; } - GtkTreePath *path = NULL; - ZyppPackage package = tryCastToZyppPkg (object); - if (package) { - // group is a string like "Productivity/Networking/Email/Utilities" - string group = package->group(); - - // We will now retrieve the hierarchy of the package's group and - // make sure a path has already been created on all nodes, as well - // as get last node's GtkTreePath - list <string> hierarchy = YGUtils::splitString (group, '/'); - while (!hierarchy.empty()) { - string node = hierarchy.front(); - hierarchy.pop_front(); - - map <string, GtkTreePath*>::iterator it = tree.find (node); - if (it == tree.end()) { - if (path) { - gtk_tree_model_get_iter (GTK_TREE_MODEL (store), - &parent_iter, path); - gtk_tree_store_append (store, &iter, &parent_iter); - } - else // create at root - gtk_tree_store_append (store, &iter, NULL); + PackageControl() + { + GtkSizeGroup *size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + m_vbox = gtk_vbox_new (FALSE, 6); + GtkWidget *hbox, *label; + + m_lock_button = gtk_toggle_button_new(); + g_signal_connect (G_OBJECT (m_lock_button), "toggled", + G_CALLBACK (locked_toggled_cb), this); + m_undo_button = gtk_button_new_from_stock (GTK_STOCK_UNDO); + g_signal_connect (G_OBJECT (m_undo_button), "clicked", + G_CALLBACK (undo_clicked_cb), this); + + hbox = gtk_hbox_new (FALSE, 6); + label = gtk_label_new (_("Status:")); + YGUtils::setWidgetFont (label, PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_size_group_add_widget (size_group, label); + m_status = gtk_label_new ("-"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), m_status, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), m_undo_button, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new(0), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), m_lock_button, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_vbox), hbox, TRUE, TRUE, 0); + + m_locked_image = createImageFromXPM (pkg_locked_xpm); + m_unlocked_image = createImageFromXPM (pkg_unlocked_xpm); + g_object_ref_sink (G_OBJECT (m_locked_image)); + g_object_ref_sink (G_OBJECT (m_unlocked_image)); + + m_remove_button = createButton (_("_Remove"), GTK_STOCK_DELETE); + g_signal_connect (G_OBJECT (m_remove_button), "clicked", + G_CALLBACK (remove_clicked_cb), this); + m_install_button = createButton ("", GTK_STOCK_SAVE); + g_signal_connect (G_OBJECT (m_install_button), "clicked", + G_CALLBACK (install_clicked_cb), this); + + m_installed_box = gtk_hbox_new (FALSE, 6); + label = gtk_label_new (_("Installed: ")); + YGUtils::setWidgetFont (label, PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_size_group_add_widget (size_group, label); + gtk_box_pack_start (GTK_BOX (m_installed_box), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_installed_box), m_remove_button, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_vbox), m_installed_box, TRUE, TRUE, 0); + + m_versions_model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT)); + m_versions_combo = gtk_combo_box_new_with_model (m_versions_model); + g_signal_connect (G_OBJECT (m_versions_combo), "changed", + G_CALLBACK (version_changed_cb), this); + + GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (m_versions_combo), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (m_versions_combo), + renderer, "text", 0, NULL); + + m_available_box = gtk_hbox_new (FALSE, 6); + label = gtk_label_new (_("Available: ")); + YGUtils::setWidgetFont (label, PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_size_group_add_widget (size_group, label); + gtk_box_pack_start (GTK_BOX (m_available_box), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_available_box), m_versions_combo, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_available_box), m_install_button, FALSE, TRUE, 0); + label = gtk_label_new (_("(Repository:")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + m_version_repo = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (m_version_repo), 0, 0.5); + gtk_label_set_ellipsize (GTK_LABEL (m_version_repo), PANGO_ELLIPSIZE_END); + gtk_box_pack_start (GTK_BOX (m_available_box), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_available_box), m_version_repo, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_vbox), m_available_box, TRUE, TRUE, 0); + + g_object_unref (G_OBJECT (size_group)); + } + + ~PackageControl() + { + gtk_widget_destroy (m_locked_image); + g_object_unref (G_OBJECT (m_locked_image)); + gtk_widget_destroy (m_unlocked_image); + g_object_unref (G_OBJECT (m_unlocked_image)); + } + + void setPackages (const std::list <Ypp::Package *> &packages) + { +fprintf (stderr, "packages selected (%d)\n", packages.size()); + // FIXME: we'll probably want to re-work the controls interface + // for now, let's just handle none-one-multiple selections separatadely + m_packages = packages; + if (packages.size() == 1) { + Ypp::Package *package = packages.front(); + // status label + std::string status; + if (package->isInstalled()) + status = _("Installed ") + package->getInstalledVersion()->number; + else + status = _("Not installed"); + if (package->toInstall()) { + int nb; + const Ypp::Package::Version *version; + package->toInstall (&nb); + version = package->getAvailableVersion (nb); + status += _(" (to install"); + if (version) + status += " " + version->number; + status += ")"; + } + else if (package->toRemove()) + status += _(" (to remove)"); + gtk_label_set_text (GTK_LABEL (m_status), status.c_str()); + if (package->isModified()) + gtk_widget_show (m_undo_button); + else + gtk_widget_hide (m_undo_button); - string name = "<big><b>" + node + "</b></big>"; - gtk_tree_store_set (store, &iter, - 0, NULL, 1, name.c_str(), 2, name.c_str(), 3, TRUE, - 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1); + // install version + if (package->isInstalled()) + gtk_widget_show (m_installed_box); + else + gtk_widget_hide (m_installed_box); - path = gtk_tree_model_get_path (model, &iter); - tree [node] = path; - } - else // exists - path = it->second; + // available versions + gtk_widget_show (m_versions_combo); + if (package->getAvailableVersion (0)) { + gtk_list_store_clear (GTK_LIST_STORE (m_versions_model)); + for (int i = 0; package->getAvailableVersion (i); i++) { + const char *version = package->getAvailableVersion (i)->number.c_str(); +fprintf (stderr, "adding version: %s\n", version); + GtkTreeIter iter; + gtk_list_store_append (GTK_LIST_STORE (m_versions_model), &iter); + gtk_list_store_set (GTK_LIST_STORE (m_versions_model), &iter, + 0, version, 1, i, -1); } + gtk_combo_box_set_active (GTK_COMBO_BOX (m_versions_combo), 0); + gtk_widget_show (m_available_box); } + else + gtk_widget_hide (m_available_box); - if (!path) // package has no group - continue; - - gtk_tree_model_get_iter (model, &parent_iter, path); - gtk_tree_store_append (store, &iter, &parent_iter); - loadPackageRow (model, &iter, selectable); - PROGRESS() - } - - // free GtkTreePaths - for (map <string, GtkTreePath*>::iterator it = tree.begin(); - it != tree.end(); it++) - gtk_tree_path_free (it->second); - return model; - } - - /* NOTE: Getting the packages under a pattern, language, etc is done - differently, so code re-use would be limited. Probably doesn't worth - the trouble and complexity of doing so. */ - - static GtkTreeModel *loadPackagesListByPattern (GtkProgressBar *progress) - { - GtkTreeStore *store = gtk_tree_store_new (10, G_TYPE_POINTER, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT); - GtkTreeModel *model = GTK_TREE_MODEL (store); - g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (0)); - - // we need to create a categories tree for the patterns - map <string, GtkTreeIter> tree; - - SET_PROGRESS (zyppPool().size <zypp::Pattern>(), 5) - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Pattern>(); - it != zyppPool().byKindEnd <zypp::Pattern>(); it++) { - ZyppSelectable selectable = *it; - ZyppObject object = selectable->theObj(); - ZyppPattern pattern = tryCastToZyppPattern (object); - if (pattern && pattern->userVisible()) { - GtkTreeIter category_iter, pattern_iter, package_iter; - string category = pattern->category(); - map <string, GtkTreeIter>::iterator cat_it = tree.find (category); - if (cat_it == tree.end()) { - string name = "<big><b>" + category + "</b></big>"; - gtk_tree_store_append (store, &category_iter, NULL); - gtk_tree_store_set (store, &category_iter, - 0, NULL, 1, name.c_str(), 2, name.c_str(), 3, TRUE, - 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1); - tree [category] = category_iter; - } + // is locked + gtk_widget_show (m_lock_button); + bool locked = package->isLocked(); + g_signal_handlers_block_by_func (m_lock_button, (gpointer) locked_toggled_cb, this); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (m_lock_button), locked); + g_signal_handlers_unblock_by_func (m_lock_button, (gpointer) locked_toggled_cb, this); + gtk_button_set_image (GTK_BUTTON (m_lock_button), + locked ? m_locked_image : m_unlocked_image); + gtk_widget_set_sensitive (m_install_button, !locked); + gtk_widget_set_sensitive (m_remove_button, !locked); + + gtk_widget_show (m_vbox); + } + else if (packages.size()) { + bool allInstalled = true, allNotInstalled = true, allUpgradable = true, + allModified = true, allLocked = true, allUnlocked = true; + for (std::list <Ypp::Package *>::const_iterator it = packages.begin(); + it != packages.end(); it++) { + if (!(*it)->isInstalled()) { + allInstalled = false; + allUpgradable = false; + } + else { + allNotInstalled = false; + const Ypp::Package::Version *version = (*it)->getAvailableVersion(0); + if (!version || version->cmp <= 0) + allUpgradable = false; + } + if (!(*it)->isModified()) + allModified = false; + if ((*it)->isLocked()) + allUnlocked = false; else - category_iter = cat_it->second; - - string name = "<b>" + fastGetSummary (object) + "</b>"; - gtk_tree_store_append (store, &pattern_iter, &category_iter); - loadPackageRow (model, &pattern_iter, selectable); - -/* gtk_tree_store_set (store, &pattern_iter, - 0, get_pointer (selectable), 1, name.c_str(), 2, name.c_str(), - 3, TRUE, 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1);*/ - - // adding children packages - const set <string> &packages = pattern->install_packages(); - for (ZyppPool::const_iterator pt2 = - zyppPool().byKindBegin <zypp::Package>(); - pt2 != zyppPool().byKindEnd <zypp::Package>(); pt2++) { - ZyppSelectable sel = *pt2; - for (set <string>::iterator pt1 = packages.begin(); - pt1 != packages.end(); pt1++) { - if (sel->name() == *pt1) { - gtk_tree_store_append (store, &package_iter, &pattern_iter); - loadPackageRow (model, &package_iter, sel); - } - } - } + allLocked = false; } - PROGRESS() - } - return model; - } - static GtkTreeModel *loadPackagesListByLanguage (GtkProgressBar *progress) - { - GtkTreeStore *store = gtk_tree_store_new (10, G_TYPE_POINTER, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT); - GtkTreeModel *model = GTK_TREE_MODEL (store); - g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (0)); - - SET_PROGRESS (zyppPool().size <zypp::Language>(), 20) - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Language>(); - it != zyppPool().byKindEnd <zypp::Language>(); it++) { - ZyppSelectable langsel = *it; - ZyppObject langobj = langsel->theObj(); - ZyppLanguage lang = tryCastToZyppLanguage (langobj); - if (lang) { - string langname = langsel->name(); - if (langname.empty() || langname == "C") - continue; - - string descrpt = "<b>" + langobj->description() + "</b>"; - GtkTreeIter parent_iter, iter; - gtk_tree_store_append (store, &parent_iter, NULL); - loadPackageRow (model, &parent_iter, langsel); -/* gtk_tree_store_set (store, &parent_iter, - 0, get_pointer (langsel), 1, descrpt.c_str(), 2, descrpt.c_str(), - 3, TRUE, 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1);*/ - - for (ZyppPool::const_iterator it = - zyppPool().byKindBegin <zypp::Package>(); - it != zyppPool().byKindEnd <zypp::Package>(); it++) { - ZyppSelectable pkgsel = *it; - ZyppObject pkgobj = pkgsel->theObj(); - - const zypp::CapSet &capSet = pkgobj->dep (zypp::Dep::FRESHENS); - for (zypp::CapSet::const_iterator it = capSet.begin(); - it != capSet.end(); it++) { - if (it->index() == lang->name()) { - gtk_tree_store_append (store, &iter, &parent_iter); - loadPackageRow (model, &iter, pkgsel); - } - } - } - } - PROGRESS() - } - return model; - } - #undef SET_PROGRESS - #undef PROGRESS - - static void induceObjects (ZyppSelectable selectable, ZyppObject &install_obj, - ZyppObject &available_obj, bool *has_upgrade, - bool *has_downgrade) - { - available_obj = (install_obj = NULL); - if (!selectable) - return; - switch (selectable->status()) { - case zypp::ui::S_Install: - case zypp::ui::S_Update: - install_obj = selectable->candidateObj(); - break; - case zypp::ui::S_Del: - available_obj = selectable->installedObj(); - break; - default: - available_obj = selectable->candidateObj(); - install_obj = selectable->installedObj(); - break; - } + std::string status; + if (allInstalled) + status = _("Installed"); + else if (allNotInstalled) + status = _("Not installed"); + else + status = _("--"); - // zypp keeps on the pool objects whose sources we disabled, so we may - // need to calculate the candidate object here. -#ifdef PRE_ZYPP_3 - if (available_obj != NULL && !available_obj->source().enabled()) { -#else - // beware lurking tribool requires bool cast here. - if (available_obj != NULL && !(bool)(available_obj->repository().info().enabled())) { -#endif - available_obj = NULL; - for (zypp::ui::Selectable::available_iterator it = selectable->availableBegin(); - it != selectable->availableEnd(); it++) { -#ifdef PRE_ZYPP_3 - if (!(*it)->source().enabled()) -#else - if (!(*it)->repository().info().enabled()) -#endif - ; - else if (!available_obj) - available_obj = *it; - else if (zypp::Edition::compare ((*it)->edition(), - available_obj->edition()) > 0) - available_obj = *it; + if (allModified) { + status += _(" (modified)"); + gtk_widget_show (m_undo_button); } - } - - bool has_up = false, has_down = false; - if (available_obj != NULL && install_obj != NULL) { - int res = zypp::Edition::compare (install_obj->edition(), - available_obj->edition()); - if (res < 0) - has_up = true; - else if (res > 0) - has_down = true; - } - - if (has_upgrade) - *has_upgrade = has_up; - if (has_downgrade) - *has_downgrade = has_down; - } - - /* Must be called for the main model. */ - static void loadPackageRow (GtkTreeModel *model, GtkTreeIter *iter, - ZyppSelectable selectable) - { - ZyppObject install_obj, available_obj; - bool has_upgrade, has_downgrade, has_children = FALSE; - induceObjects (selectable, install_obj, available_obj, - &has_upgrade, &has_downgrade); - - bool detailed = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), - "detail-package")); - string availableName, installedName, name (YGUtils::escape_markup (selectable->name())); - if (available_obj) { - if (detailed) - availableName = "<b>" + name + "</b> (" + available_obj->edition().version() + - ")\n<small>" + YGUtils::escape_markup (fastGetSummary (available_obj)) + - "</small>"; - else { - ZyppPattern pattern = tryCastToZyppPattern (available_obj); - ZyppLanguage lang = tryCastToZyppLanguage (available_obj); - if (pattern) { - availableName = "<b>" + fastGetSummary (available_obj) + "</b>"; - has_children = TRUE; - } else if (lang) { - availableName = "<b>" + available_obj->description() + "</b>"; - has_children = TRUE; - } else - availableName = name + " (" + available_obj->edition().version() + ")"; - } - } - if (install_obj) { - if (detailed) - installedName = "<b>" + name + "</b> (" + install_obj->edition().version() + - ")\n<small>" + YGUtils::escape_markup (fastGetSummary (install_obj)) + - "</small>"; - else { - ZyppPattern pattern = tryCastToZyppPattern (install_obj); - ZyppLanguage lang = tryCastToZyppLanguage (install_obj); - if (pattern) { - installedName = "<b>" + fastGetSummary (install_obj) + "</b>"; - has_children = TRUE; - } else if (lang) { - installedName = "<b>" + install_obj->description() + "</b>"; - has_children = TRUE; - } else - installedName = name + " (" + install_obj->edition().version() + ")"; - } - } - - // Make sure that both the availableName and installedName - // are filled. Occasionally, the names are empty, so the - // following checks make sure these variable are filled. - if (availableName.empty()) - availableName = installedName; - else if (installedName.empty()) - installedName = availableName; - - PangoStyle style = PANGO_STYLE_NORMAL; - if (selectable->toModify()) - style = PANGO_STYLE_ITALIC; - - // oh, would be nice to have a common set for tree models... - if (GTK_IS_LIST_STORE (model)) - gtk_list_store_set (GTK_LIST_STORE (model), iter, - COL_SELECTABLE, get_pointer (selectable), - COL_INSTALLED_NAME, installedName.c_str(), - COL_AVAILABLE_NAME, availableName.c_str(), - COL_IS_INSTALLED, install_obj != 0, - COL_IS_AVAILABLE, available_obj != 0, - COL_CAN_BE_UPGRADED, has_upgrade, - COL_CAN_BE_DOWNGRADED, has_downgrade, - COL_SHOW_UPGRADABLE_CONTROL, detailed, - COL_HAS_CHILDREN, has_children, - COL_FONT_STYLE, style, -1); - else /*if (GTK_IS_TREE_STORE (model))*/ - gtk_tree_store_set (GTK_TREE_STORE (model), iter, - COL_SELECTABLE, get_pointer (selectable), - COL_INSTALLED_NAME, installedName.c_str(), - COL_AVAILABLE_NAME, availableName.c_str(), - COL_IS_INSTALLED, install_obj != 0, - COL_IS_AVAILABLE, available_obj != 0, - COL_CAN_BE_UPGRADED, has_upgrade, - COL_CAN_BE_DOWNGRADED, has_downgrade, - COL_SHOW_UPGRADABLE_CONTROL, detailed, - COL_HAS_CHILDREN, has_children, - COL_FONT_STYLE, style, -1); -/* y2milestone ("set %s: %d - %d\n", selectable->name().c_str(), - available_obj != 0, install_obj != 0);*/ - } + else + gtk_widget_hide (m_undo_button); + gtk_label_set_text (GTK_LABEL (m_status), status.c_str()); - virtual ~PackageSelector() - { - IMPL - if (search_timeout_id) - g_source_remove (search_timeout_id); + // install version + if (allInstalled) + gtk_widget_show (m_installed_box); + else + gtk_widget_hide (m_installed_box); - delete m_information_widget; - delete m_sources_table; - delete m_disk_table; - gtk_widget_destroy (m_widget); - g_object_unref (G_OBJECT (m_widget)); - } + // available versions + gtk_widget_hide (m_versions_combo); + if (allNotInstalled || allUpgradable) { + gtk_widget_show (m_available_box); + const char *installLabel = _("Install"); + if (allUpgradable) + installLabel = _("Upgrade"); + gtk_button_set_label (GTK_BUTTON (m_install_button), installLabel); + } + else + gtk_widget_hide (m_available_box); - GtkWidget *getWidget() - { return m_widget; } + // is locked + if (allLocked || allUnlocked) { + gtk_widget_show (m_lock_button); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (m_lock_button), allLocked); + gtk_button_set_image (GTK_BUTTON (m_lock_button), + allLocked ? m_locked_image : m_unlocked_image); + gtk_widget_set_sensitive (m_install_button, !allLocked); + gtk_widget_set_sensitive (m_remove_button, !allLocked); + } + else { + gtk_widget_hide (m_lock_button); + gtk_widget_set_sensitive (m_install_button, TRUE); + gtk_widget_set_sensitive (m_remove_button, TRUE); + } + gtk_widget_show (m_vbox); + } + else + gtk_widget_hide (m_vbox); - static void view_plain_mode_cb (GtkToggleButton *button, - PackageSelector *pThis) - { - if (!gtk_toggle_button_get_active (button)) return; - pThis->load_packages_view (&loadPackagesListAsPlain); +#if 0 + m_package = package; + if (package) { + if (package->isInstalled()) { + gtk_widget_show (m_remove_button); + gtk_widget_hide (m_install_button); + } + else { + gtk_widget_show (m_install_button); + gtk_widget_hide (m_remove_button); + } + if (package && package->hasUpgrade()) + gtk_widget_show (m_upgrade_button); + else + gtk_widget_hide (m_upgrade_button); + } + else { + gtk_widget_hide (m_install_button); + gtk_widget_hide (m_remove_button); + gtk_widget_hide (m_upgrade_button); + } +#endif } - static void view_categories_mode_cb (GtkToggleButton *button, - PackageSelector *pThis) +private: + static void install_clicked_cb (GtkButton *button, PackageControl *pThis) { - if (!gtk_toggle_button_get_active (button)) return; - pThis->clear_search_entry (true); - pThis->load_packages_view (&loadPackagesListByCategory); + busyCursor(); + Ypp::get()->startTransactions(); + for (std::list <Ypp::Package *>::iterator it = pThis->m_packages.begin(); + it != pThis->m_packages.end(); it++) { + int version; + if (GTK_WIDGET_VISIBLE (pThis->m_versions_combo)) + version = gtk_combo_box_get_active (GTK_COMBO_BOX ( + pThis->m_versions_combo)); + else + version = 0; // i.e. most recent (on multi-packages) + (*it)->install (version); + } + Ypp::get()->finishTransactions(); + normalCursor(); } - static void view_patterns_mode_cb (GtkToggleButton *button, - PackageSelector *pThis) + static void remove_clicked_cb (GtkButton *button, PackageControl *pThis) { - if (!gtk_toggle_button_get_active (button)) return; - pThis->clear_search_entry (true); - pThis->load_packages_view (&loadPackagesListByPattern); + busyCursor(); + Ypp::get()->startTransactions(); + for (std::list <Ypp::Package *>::iterator it = pThis->m_packages.begin(); + it != pThis->m_packages.end(); it++) + (*it)->remove(); + Ypp::get()->finishTransactions(); + normalCursor(); } - static void view_languages_mode_cb (GtkToggleButton *button, - PackageSelector *pThis) + static void undo_clicked_cb (GtkButton *button, PackageControl *pThis) { - if (!gtk_toggle_button_get_active (button)) return; - pThis->clear_search_entry (true); - pThis->load_packages_view (&loadPackagesListByLanguage); + busyCursor(); + Ypp::get()->startTransactions(); + for (std::list <Ypp::Package *>::iterator it = pThis->m_packages.begin(); + it != pThis->m_packages.end(); it++) + (*it)->undo(); + Ypp::get()->finishTransactions(); + normalCursor(); } - void sources_changed_cb() + static void locked_toggled_cb (GtkToggleButton *button, PackageControl *pThis) { - // reload view; FIXME: re-load the current view, not necessarly - // the plain list; hacky anyway - if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m_plain_view))) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (m_plain_view), TRUE); - else - g_signal_emit_by_name (G_OBJECT (m_plain_view), "toggled", this); + busyCursor(); + Ypp::get()->startTransactions(); + for (std::list <Ypp::Package *>::iterator it = pThis->m_packages.begin(); + it != pThis->m_packages.end(); it++) + (*it)->lock (gtk_toggle_button_get_active (button)); + Ypp::get()->finishTransactions(); + normalCursor(); } - void clear_search_entry (bool dont_load) + static void version_changed_cb (GtkComboBox *combo, PackageControl *pThis) { - if (dont_load) - g_signal_handlers_block_by_func (m_search_entry, - (gpointer) search_request_cb, this); - gtk_entry_set_text (GTK_ENTRY (m_search_entry), ""); - if (dont_load) - g_signal_handlers_unblock_by_func (m_search_entry, - (gpointer) search_request_cb, this); - } + fprintf (stderr, "version changed\n"); + if (!pThis->m_packages.empty()) { + Ypp::Package *package = pThis->m_packages.front(); + int nb; + GtkTreeIter iter; + if (gtk_combo_box_get_active_iter (combo, &iter)) { + gtk_tree_model_get (pThis->m_versions_model, &iter, 1, &nb, -1); + const Ypp::Package::Version *version; + fprintf (stderr, "get available version %d\n", nb); + version = package->getAvailableVersion (nb); + g_assert (version != NULL); + + const Ypp::Repository *repo = Ypp::get()->getRepository (version->repo); + if (repo) { + std::string repo_str = repo->name + ")"; + gtk_label_set_text (GTK_LABEL (pThis->m_version_repo), repo_str.c_str()); + } + else + gtk_label_set_text (GTK_LABEL (pThis->m_version_repo), + "TODO: hide this for collections)"); - static void search_activate_cb (GtkEntry *entry, PackageSelector *pThis) - { - IMPL - if (pThis->search_timeout_id) - g_source_remove (pThis->search_timeout_id); - search_cb (pThis); + const char *installLabel = _("Install"); + if (package->isInstalled()) { + if (version->cmp > 0) + installLabel = _("Upgrade"); + else if (version->cmp == 0) + installLabel = _("Re-install"); + else //if (version->cmp < 0) + installLabel = _("Downgrade"); + } + gtk_button_set_label (GTK_BUTTON (pThis->m_install_button), installLabel); + } + } } - static void search_request_cb (GtkEditable *editable, PackageSelector *pThis) + // utility + static GtkWidget *createButton (const char *label_str, const gchar *stock_id) { - IMPL - // we'll make a delay for the actual search to wait for the user - // to finish writting - if (pThis->search_timeout_id) - g_source_remove (pThis->search_timeout_id); - pThis->search_timeout_id = g_timeout_add (500, search_cb, pThis); + GtkWidget *button, *image; + button = gtk_button_new_with_mnemonic (label_str); + if (stock_id) { + image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON); + gtk_button_set_image (GTK_BUTTON (button), image); + } + return button; } +}; - struct FindClosure { - bool found; - GtkTreeView *view; - PackageSelector *pThis; - }; - static gboolean find_exact_match (GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer data) - { - FindClosure *cl = (FindClosure *) data; - - ZyppSelectablePtr sel = NULL; - - gtk_tree_model_get (model, iter, COL_SELECTABLE, &sel, -1); - - if (!sel) - return FALSE; - - if (sel->name() == *cl->pThis->m_search_queries.begin()) { - cl->found = true; - gtk_tree_selection_select_iter - (gtk_tree_view_get_selection (cl->view), iter); - package_clicked_cb (gtk_tree_view_get_selection (cl->view), cl->pThis); - return TRUE; - } - return FALSE; - } - - void highlight_exact_matches () - { - if (m_search_queries.empty() || !name_opt) - return; +class PackageInfo +{ +GtkWidget *m_widget, *m_description, *m_filelist, *m_changelog, *m_authors; - FindClosure cl; - cl.found = false; - cl.pThis = this; - cl.view = GTK_TREE_VIEW (m_installed_view); - - gtk_tree_model_foreach (gtk_tree_view_get_model (cl.view), - find_exact_match, &cl); - - if (!cl.found) { - cl.view = GTK_TREE_VIEW (m_available_view); - gtk_tree_model_foreach (gtk_tree_view_get_model (cl.view), - find_exact_match, &cl); - } - } +public: + GtkWidget *getWidget() + { return m_widget; } - static gboolean search_cb (gpointer data) + PackageInfo() { - IMPL - - // This is potentially very slow ... -#ifdef IMPL_DEBUG - fprintf (stderr, "search start...\n"); -#endif - PackageSelector *pThis = (PackageSelector *) data; - pThis->search_timeout_id = 0; - - const gchar *query = gtk_entry_get_text (GTK_ENTRY (pThis->m_search_entry)); - bool plain_view = gtk_toggle_button_get_active ( - GTK_TOGGLE_BUTTON (pThis->m_plain_view)); - if (!plain_view) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pThis->m_plain_view), TRUE); - pThis->m_search_queries = YGUtils::splitString (query, ' '); - - // just re-filter - GtkTreeModel *available_model = - gtk_tree_view_get_model (GTK_TREE_VIEW (pThis->m_available_view)); - GtkTreeModel *installed_model = - gtk_tree_view_get_model (GTK_TREE_VIEW (pThis->m_installed_view)); - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (available_model)); - gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (installed_model)); - - pThis->highlight_exact_matches (); - -#ifdef IMPL_DEBUG - fprintf (stderr, "search done...\n"); -#endif - return FALSE; + m_widget = gtk_notebook_new(); + addPage (_("Description"), createHtmlWidget (&m_description)); + addPage (_("File List"), createHtmlWidget (&m_filelist)); + addPage (_("ChangeLog"), createHtmlWidget (&m_changelog)); + addPage (_("Authors"), createHtmlWidget (&m_authors)); + gtk_widget_set_size_request (m_widget, -1, 150); + ygtk_html_wrap_connect_link_clicked (m_filelist, + G_CALLBACK (path_pressed_cb), NULL); } - GtkMenu *create_search_menu() + void setPackage (Ypp::Package *package) { - GtkWidget *menu = gtk_menu_new(); - append_option_item (menu, _("Name"), &name_opt); - append_option_item (menu, _("Summary"), &summary_opt); - append_option_item (menu, _("Description"), &descr_opt); - append_option_item (menu, _("RPM Provides"), &provides_opt); - append_option_item (menu, _("RPM Requires"), &requires_opt); - gtk_widget_show_all (menu); - return GTK_MENU (menu); + if (package) { + setText (m_description, package->description()); + setText (m_filelist, package->filelist()); + setText (m_changelog, package->changelog()); + setText (m_authors, package->authors()); + if (!GTK_WIDGET_VISIBLE (m_widget)) { + gtk_notebook_set_current_page (GTK_NOTEBOOK (m_widget), 0); + gtk_widget_show (m_widget); + } + } + else + gtk_widget_hide (m_widget); } - static void append_option_item (GtkWidget *menu, const char *label, bool *option) +private: + static void path_pressed_cb (GtkWidget *text, const gchar *link) + { FILEMANAGER_LAUNCH (link); } + + // utilities: + static GtkWidget *createHtmlWidget (GtkWidget **html_widget) { - GtkWidget *item = gtk_check_menu_item_new_with_label (label); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), *option); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - g_signal_connect (G_OBJECT (item), "toggled", - G_CALLBACK (search_option_change_cb), option); + *html_widget = ygtk_html_wrap_new(); + GtkWidget *scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_container_add (GTK_CONTAINER (scroll), *html_widget); + return scroll; } - static void search_option_change_cb (GtkCheckMenuItem *item, bool *option) - { *option = item->active; } - - inline static gboolean is_package_visible (GtkTreeModel *model, GtkTreeIter *iter, - PackageSelector *pThis, int visible_col) + void addPage (const char *title, GtkWidget *content) { - gboolean visible, has_children; - ZyppSelectablePtr selectable; - - gtk_tree_model_get (model, iter, visible_col, &visible, - COL_HAS_CHILDREN, &has_children, - COL_SELECTABLE, &selectable, -1); - -// fprintf (stderr, "is visible '%s'\n", selectable ? selectable->name().c_str() : "<noname>"); - if (has_children) - visible = TRUE; - else if (visible && !pThis->m_search_queries.empty()) - visible = pThis->does_package_match (selectable); - - return visible; + gtk_notebook_append_page (GTK_NOTEBOOK (m_widget), content, gtk_label_new (title)); } - static gboolean is_package_installed (GtkTreeModel *model, GtkTreeIter *iter, - gpointer data) - { return is_package_visible (model, iter, (PackageSelector *) data, 3); } - - static gboolean is_package_available (GtkTreeModel *model, GtkTreeIter *iter, - gpointer data) + void setText (GtkWidget *rtext, const std::string &text) { - gboolean is_installed, is_available, has_upgrade, has_children; - gboolean visible = TRUE; - ZyppSelectablePtr selectable; - PackageSelector *pThis = (PackageSelector *) data; - - // only show the packages that aren't installed - // unless there's an upgrade available - gtk_tree_model_get (model, iter, COL_SELECTABLE, &selectable, - COL_IS_INSTALLED, &is_installed, - COL_IS_AVAILABLE, &is_available, - COL_CAN_BE_UPGRADED, &has_upgrade, - COL_HAS_CHILDREN, &has_children, -1); - if (!has_children) { - if (is_available && (!is_installed || has_upgrade)) { - if (!pThis->m_search_queries.empty()) - visible = pThis->does_package_match (selectable); - } else - visible = FALSE; + if (text.empty()) { + const char *empty = _("<i>(only available for installed packages)</i>"); + ygtk_html_wrap_set_text (rtext, empty); } - - return visible; + else + ygtk_html_wrap_set_text (rtext, text.c_str()); + ygtk_html_wrap_scroll (rtext, TRUE); } +}; - bool does_package_match_one (ZyppSelectablePtr sel, string key) - { - ZyppObject obj = NULL; +class DiskView : public Ypp::Disk::Listener +{ +GtkWidget *m_widget; +bool m_hasWarn; +GtkTreeModel *m_model; - if (name_opt && YGUtils::contains (sel->name(), key)) - return TRUE; - - if (summary_opt || descr_opt || provides_opt || requires_opt) - obj = sel->theObj(); - - if (summary_opt && YGUtils::contains (fastGetSummary (obj), key)) - return TRUE; - if (descr_opt && YGUtils::contains (obj->description(), key)) - return TRUE; - if (provides_opt) { - const zypp::CapSet &capSet = obj->dep (zypp::Dep::PROVIDES); - for (zypp::CapSet::const_iterator it = capSet.begin(); - it != capSet.end(); it++) - if (YGUtils::contains (it->asString(), key)) - return TRUE; - } - if (requires_opt) { - const zypp::CapSet &capSet = obj->dep (zypp::Dep::REQUIRES); - for (zypp::CapSet::const_iterator it = capSet.begin(); - it != capSet.end(); it++) - if (YGUtils::contains (it->asString(), key)) - return TRUE; - } - return FALSE; - } +public: + GtkWidget *getWidget() + { return m_widget; } - gboolean does_package_match (ZyppSelectablePtr sel) + DiskView() + : m_hasWarn (false) { - if (m_search_queries.empty()) - return true; + m_model = GTK_TREE_MODEL (gtk_list_store_new ( + // 0 - mount point, 1 - usage percent, 2 - usage string + 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING)); + m_widget = createCombo (m_model); + g_object_unref (G_OBJECT (m_model)); - bool and_results = true; // vs. or them ... + Ypp::get()->getDisk()->setListener (this); + update(); + } - bool result = and_results; - for (list <string>::iterator it = m_search_queries.begin(); - it != m_search_queries.end(); it++) { - - // TODO: googlify more ... - if (*it == "OR") { - and_results = false; - continue; - } - if (*it == "AND") { - and_results = true; - continue; - } - bool match = does_package_match_one (sel, *it); - result = and_results ? result && match : result || match; - } - return result; - } - - // callbacks - static bool getSelectedPackage (GtkTreeView *tree_view, - ZyppSelectablePtr *package_sel, GtkTreePath **_path = 0) +private: + #define MIN_FREE_MB_WARN (80*1024) + virtual void update() { - IMPL - GtkTreePath *path = 0; - gtk_tree_view_get_cursor (tree_view, &path, NULL); - if (path) { - GtkTreeModel *model = gtk_tree_view_get_model (tree_view); + GtkListStore *store = GTK_LIST_STORE (m_model); + gtk_list_store_clear (store); + + int warn_part = -1; + Ypp::Disk *disk = Ypp::get()->getDisk(); + for (int i = 0; disk->getPartition (i); i++) { + const Ypp::Disk::Partition *part = disk->getPartition (i); + long usage = (part->used * 100) / (part->total + 1); + std::string usage_str = part->used_str + " (of " + part->total_str + ")"; GtkTreeIter iter; - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, COL_SELECTABLE, package_sel, -1); - if (_path) - *_path = gtk_tree_model_filter_convert_path_to_child_path - (GTK_TREE_MODEL_FILTER (model), path); - gtk_tree_path_free (path); - return true; + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, part->path.c_str(), 1, usage, + 2, usage_str.c_str(), -1); + if (warn_part < 0 && (part->total > 1024 && part->total - part->used < MIN_FREE_MB_WARN)) + warn_part = i; } - return false; + if (warn_part >= 0) { + warn(); + gtk_combo_box_set_active (GTK_COMBO_BOX (m_widget), warn_part); + } + else + gtk_combo_box_set_active (GTK_COMBO_BOX (m_widget), 0); } - // For SLED10 / older gtk+'s ... - static bool compat_gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter, - GtkTreeIter *filter_iter, - GtkTreeIter *child_iter) - { -#if GTK_CHECK_VERSION(2,10,0) - return gtk_tree_model_filter_convert_child_iter_to_iter (filter, filter_iter, child_iter); -#else // cut/paste from gtk+ HEAD... - gboolean ret; - GtkTreePath *child_path, *path; - - memset (filter_iter, 0, sizeof (GtkTreeIter)); - - GtkTreeModel *child_model; - g_object_get (G_OBJECT (filter), "child-model", &child_model, NULL); - child_path = gtk_tree_model_get_path (child_model, child_iter); - g_return_val_if_fail (child_path != NULL, FALSE); - - path = gtk_tree_model_filter_convert_child_path_to_path (filter, - child_path); - gtk_tree_path_free (child_path); - - if (!path) - return FALSE; + void warn() + { + if (m_hasWarn) return; + m_hasWarn = true; - ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path); - gtk_tree_path_free (path); + GtkWidget *dialog, *view; + dialog = gtk_message_dialog_new (YGUI::ui()->currentWindow(), + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, _("Disk Almost Full !")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + "One of the partitions is reaching its limit of capacity. You may " + "have to remove packages if you wish to install some."); - return ret; -#endif - } + view = createView (m_model); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), view); - static bool sync_tree_views_scroll (GtkTreeView *current_view, GtkTreeView *other_view, - GtkTreePath *current_path, bool select_it) - { - /* What we do here is to scroll the other view to the correspondent - package position. If the package isn't present in that view, we - iterate it so we get the closest package (with respect to alphabetic - sorting). */ - - // converts the path from one model to the other - GtkTreePath *_path, *other_path; - _path = gtk_tree_model_filter_convert_path_to_child_path ( - GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (current_view)), - current_path); - if (!_path) - return false; - - GtkTreeModel *base_model = gtk_tree_model_filter_get_model ( - GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (current_view))); - - GtkTreeIter iter, other_iter; - gtk_tree_model_get_iter (base_model, &iter, _path); - gtk_tree_path_free (_path); - - int timeout = 0; - // Try to find a a similar item in the other view to synchronise with - while (!compat_gtk_tree_model_filter_convert_child_iter_to_iter ( - GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (other_view)), - &other_iter, &iter)) - { - if (!gtk_tree_model_iter_next (base_model, &iter)) - return false; - // This turns into N^3 very quickly if we search too hard - if (timeout++ > 10) - return false; - select_it = false; // not the same package -- dont select it then - } - - other_path = gtk_tree_model_get_path (gtk_tree_view_get_model (other_view), - &other_iter); - - GdkRectangle cell_rect, visible_rect; - gtk_tree_view_get_cell_area (other_view, other_path, NULL, &cell_rect); - gtk_tree_view_get_visible_rect (other_view, &visible_rect); - int y = visible_rect.y + cell_rect.y; - - gtk_tree_view_get_cell_area (current_view, current_path, NULL, &cell_rect); - y -= cell_rect.y; // offset - - gtk_tree_view_expand_to_path (other_view, other_path); - YGUtils::tree_view_smooth_scroll_to_point (other_view, 0, y); - if (select_it) - gtk_tree_selection_select_path (gtk_tree_view_get_selection (other_view), - other_path); - gtk_tree_path_free (other_path); - return true; + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); } - static void package_clicked_cb (GtkTreeSelection *selection, PackageSelector *pThis) + // utilities +#if 1 + static GtkWidget *createView (GtkTreeModel *model) { - IMPL - int selected_rows = gtk_tree_selection_count_selected_rows (selection); - if (selected_rows == 0) - return; - - static bool safeguard = false; - if (safeguard) - return; - safeguard = true; + GtkWidget *view = gtk_tree_view_new_with_model (model), *scroll; + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); + gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), + GTK_SELECTION_NONE); - GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection); - bool install_view = tree_view == GTK_TREE_VIEW (pThis->m_installed_view); - GtkTreeView *other_view = GTK_TREE_VIEW (install_view ? - pThis->m_available_view : pThis->m_installed_view); - - // unselect the other view - gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (other_view)); - - // select and scroll to the package in the other view (if it's listed there) - GtkTreePath *path = 0; - gtk_tree_view_get_cursor (tree_view, &path, NULL); - if (path) { - // function can be called to set some package visible - gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0, 0); + GtkTreeViewColumn *column; + column = gtk_tree_view_column_new_with_attributes (_("Mount Point"), + gtk_cell_renderer_text_new(), "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + column = gtk_tree_view_column_new_with_attributes (_("Usage"), + gtk_cell_renderer_progress_new(), "value", 1, "text", 2, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - sync_tree_views_scroll (tree_view, other_view, path, selected_rows == 1); - gtk_tree_path_free (path); - } + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), + GTK_SHADOW_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_NEVER, GTK_POLICY_NEVER); +// gtk_widget_set_size_request (scroll, -1, 50); + gtk_container_add (GTK_CONTAINER (scroll), view); + gtk_widget_show_all (scroll); + return scroll; + } +#endif + static GtkWidget *createCombo (GtkTreeModel *model) + { + GtkWidget *combo = gtk_combo_box_new_with_model (model); + GtkCellRenderer *renderer; + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), + renderer, "text", 0, NULL); + // let's put all columns to the same width, to make it look like a table + g_object_set (G_OBJECT (renderer), "width-chars", 14, NULL); + renderer = gtk_cell_renderer_progress_new(); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), + renderer, "value", 1, "text", 2, NULL); + return combo; + } +}; - // show package information - ZyppSelectablePtr sel = 0; - getSelectedPackage (tree_view, &sel); - - ZyppObject install_obj, available_obj; - induceObjects (sel, install_obj, available_obj, NULL, NULL); - - ZyppObject &obj = install_view ? install_obj : available_obj; - pThis->m_information_widget->setPackage (sel, obj); - - // change the install/remove button label to upgrade, or etc - GtkLabel *install_label = GTK_LABEL (pThis->m_install_label), - *remove_label = GTK_LABEL (pThis->m_remove_label); - if (selected_rows > 1) { - gtk_label_set_text (install_label, _("_install")); - gtk_label_set_text (remove_label, _("_remove")); - } - else { // personalize - // remove label - if (sel && sel->toInstall()) - gtk_label_set_text (remove_label, _("_undo")); - else - gtk_label_set_text (remove_label, _("_remove")); - // install label - if (sel && sel->toDelete()) - gtk_label_set_text (install_label, _("_undo")); - else if (!install_obj) - gtk_label_set_text (install_label, _("_install")); - else if (available_obj) { - int res = zypp::Edition::compare (install_obj->edition(), - available_obj->edition()); - if (res < 0) - gtk_label_set_text (install_label, _("_upgrade")); - else if (res > 0) - gtk_label_set_text (install_label, _("_downgrade")); - else - gtk_label_set_text (install_label, _("re-_install")); - } - } - gtk_label_set_use_underline (install_label, TRUE); - gtk_label_set_use_underline (remove_label, TRUE); +class PackageSelector : public Filters::Listener, public PackagesView::Listener +{ +PackagesView *m_packages; +Filters *m_filters; +PackageInfo *m_info; +PackageControl *m_control; +DiskView *m_disk; +GtkWidget *m_box; +TrashWindow *m_trashWin; - safeguard = false; - } +public: + GtkWidget *getWidget() + { return m_box; } - // install/remove/update/... selected packages - void markSelectedPackage (GtkTreeView *view, bool available, bool installed) + PackageSelector() { - IMPL - /* Since the filter model gets changed, get paths for the base model and - then do our stuff. */ - GList *selected = gtk_tree_selection_get_selected_rows ( - gtk_tree_view_get_selection (view), NULL); - - int selected_len = g_list_length (selected); - GtkTreeIter iters [selected_len]; - - GtkTreeModel *filter_model = gtk_tree_view_get_model (view); - GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (filter_model); - GtkTreeModel *model = gtk_tree_model_filter_get_model (filter); - - int i = 0; - for (GList *it = selected; it; it = it->next, i++) { - GtkTreePath *path = (GtkTreePath *) it->data; + m_packages = new PackagesView(); + m_packages->setListener (this); - GtkTreeIter filter_iter, iter; - gtk_tree_model_get_iter (filter_model, &filter_iter, path); - gtk_tree_path_free (path); + m_control = new PackageControl(); + m_info = new PackageInfo(); - gtk_tree_model_filter_convert_iter_to_child_iter (filter, &iter, &filter_iter); - iters[i] = iter; - } - g_list_free (selected); - for (i = 0; i < selected_len; i++) { - GtkTreeIter *iter = &iters[i]; - ZyppSelectablePtr sel = 0; - gtk_tree_model_get (model, iter, COL_SELECTABLE, &sel, -1); - if (sel && mark_selectable (sel, installed) /* install/remove */) { - loadPackageRow (model, iter, sel); // update model - - // mark also children (eg. for patterns and languages) - GtkTreeIter child; - if (gtk_tree_model_iter_children (model, &child, iter)) { - do { - gtk_tree_model_get (model, &child, COL_SELECTABLE, &sel, -1); - if (sel && mark_selectable (sel, installed)) - loadPackageRow (model, &child, sel); - } while (gtk_tree_model_iter_next (model, &child)); + GtkWidget *vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), m_packages->getWidget(), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), m_control->getWidget(), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), m_info->getWidget(), FALSE, TRUE, 0); - } - } - } + m_filters = new Filters(); + m_filters->setListener (this); + m_disk = new DiskView(); - m_disk_table->update(); + GtkWidget *left_box = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (left_box), m_filters->getWidget(), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (left_box), m_disk->getWidget(), FALSE, TRUE, 0); - // select path, so the buttons get updated and all (hacky) - GtkTreeView *other_view = GTK_TREE_VIEW ( - GTK_WIDGET (view) == m_installed_view ? m_available_view : m_installed_view); - package_clicked_cb (gtk_tree_view_get_selection (other_view), this); + m_box = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (m_box), left_box, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (m_box), vbox, TRUE, TRUE, 0); + gtk_widget_show_all (m_box); + + m_control->setPackages (std::list <Ypp::Package*> ()); + m_info->setPackage (NULL); + + m_trashWin = new TrashWindow(); } - static void install_button_clicked_cb (GtkButton *button, PackageSelector *pThis) + ~PackageSelector() { - IMPL - pThis->markSelectedPackage (GTK_TREE_VIEW (pThis->m_available_view), false, true); - gtk_widget_grab_focus (pThis->m_available_view); + delete m_packages; + delete m_control; + delete m_info; + delete m_filters; + delete m_disk; + delete m_trashWin; } - static void remove_button_clicked_cb (GtkButton *button, PackageSelector *pThis) + virtual void doQuery (Ypp::Query *query) { - IMPL - pThis->markSelectedPackage (GTK_TREE_VIEW (pThis->m_installed_view), true, false); - gtk_widget_grab_focus (pThis->m_installed_view); + m_packages->query (query); } - static void change_available_version_cb (YGtkCellRendererArrow *renderer, - guint arrow_type, const gchar *_path, PackageSelector *pThis) + virtual void packagesSelected (const std::list <Ypp::Package *> &packages) { - GtkTreeModel *model = gtk_tree_view_get_model ( - GTK_TREE_VIEW (pThis->m_available_view)); - GtkTreePath *path = gtk_tree_path_new_from_string (_path); - GtkTreeIter it; - gtk_tree_model_get_iter (model, &it, path); - gtk_tree_path_free (path); - - GtkTreeIter iter; - gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), - &iter, &it); - model = pThis->m_packages_model; - - ZyppSelectablePtr selectable; - gtk_tree_model_get (model, &iter, COL_SELECTABLE, &selectable, -1); - - ZyppObject candidate = selectable->candidateObj(); - for (zypp::ui::Selectable::available_iterator it = selectable->availableBegin(); - it != selectable->availableEnd(); it++) { - int cmp = zypp::Edition::compare ((*it)->edition(), candidate->edition()); - if (arrow_type == GTK_ARROW_UP) { // upgrade - if (cmp > 0) - candidate = *it; - } - else /*if (arrow_type == GTK_ARROW_DOWN)*/ { // downgrade - if (cmp < 0) - candidate = *it; - } - } - if (!selectable->setCandidate (candidate)) - y2warning ("Error: Could not %sgrade\n", arrow_type == GTK_ARROW_UP ? "up" : "down"); - pThis->loadPackageRow (model, &iter, selectable); + m_control->setPackages (packages); + if (packages.size() == 1) + m_info->setPackage (packages.front()); + else + m_info->setPackage (NULL); } - static gboolean dont_select_groups_cb (GtkTreeSelection *selection, GtkTreeModel *model, - GtkTreePath *path, gboolean selected, gpointer data) + void packageModified (Ypp::Package *package) { - GtkTreeIter iter; - if (gtk_tree_model_get_iter (model, &iter, path)) { - ZyppSelectablePtr selectable; - gtk_tree_model_get (model, &iter, COL_SELECTABLE, &selectable, -1); - return selectable != NULL; - } - return FALSE; + // GTK+ doesn't fire selection change when a selected row changes, so we need + // to re-load PackageControl in that occasions. + std::list <Ypp::Package *>::iterator it; + for (it = m_control->m_packages.begin(); it != m_control->m_packages.end(); it++) + if (*it == package) + break; + if (it != m_control->m_packages.end()) + m_control->setPackages (m_control->m_packages); } }; -// The ordinary package selector that displays all packages -class YGPackageSelector : public YPackageSelector, public YGWidget -{ - PackageSelector *m_package_selector; - - static bool confirm_cb (void *pThis) - { - return ((YGPackageSelector *)pThis)->checkDelete(); - } - - bool checkDelete() - { - bool changed = - zyppPool().diffState<zypp::Package >() || - zyppPool().diffState<zypp::Pattern >() || - zyppPool().diffState<zypp::Selection>() || - zyppPool().diffState<zypp::Language >() || - zyppPool().diffState<zypp::Patch >(); - if (!changed) - return true; +#include "YPackageSelector.h" - GtkWidget *dialog; - dialog = gtk_message_dialog_new_with_markup - (YGUI::ui()->currentWindow(), - GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, _("<b>Abandon all changes?</b>")); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_NO, - GTK_STOCK_QUIT, GTK_RESPONSE_YES, NULL); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), - GTK_RESPONSE_NO); - bool ok = gtk_dialog_run (GTK_DIALOG (dialog)) == - GTK_RESPONSE_YES; - gtk_widget_destroy (dialog); - return ok; - } +class YGPackageSelector : public YPackageSelector, public YGWidget, public Ypp::Interface +{ +PackageSelector *m_package_selector; public: YGPackageSelector (const YWidgetOpt &opt, YGWidget *parent) @@ -2422,27 +1385,19 @@ YGWidget (this, parent, true, YGTK_TYPE_WIZARD, NULL) { setBorder (0); - YGDialog *dialog = YGUI::ui()->currentYGDialog(); dialog->setCloseCallback (confirm_cb, this); - GtkWindow *window = dialog->getWindow(); - gtk_window_resize (window, MAX (680, GTK_WIDGET (window)->allocation.width), + + GtkWindow *window = dialog->getWindow(); + gtk_window_resize (window, GTK_WIDGET (window)->allocation.width, MAX (580, GTK_WIDGET (window)->allocation.height)); YGtkWizard *wizard = YGTK_WIZARD (getWidget()); - ygtk_wizard_set_header_icon (wizard, window, THEMEDIR "/icons/32x32/apps/yast-software.png"); - ygtk_wizard_set_header_text (wizard, window, "Package Selector"); + ygtk_wizard_set_header_text (wizard, window, _("Package Selector")); ygtk_wizard_set_help_text (wizard, - _("Two pools are presented; one with the available software, the other " - "with the installed one. To install software you choose a package " - "from the install pool and press Install. Similar method for removal " - "of software. When you are done press the Accept button.<br>" - "Information on a given package is displayed on the Package Information " - "expander at the bottom which may be enlarged.<br>" - "A categories view of the software is possible, as well as searching " - "for a given package.") + _("TO WRITE") ); ygtk_wizard_set_abort_button_label (wizard, _("_Cancel")); @@ -2453,15 +1408,16 @@ g_signal_connect (G_OBJECT (getWidget()), "action-triggered", G_CALLBACK (wizard_action_cb), this); - m_package_selector = new PackageSelector (!opt.searchMode.value()); + m_package_selector = new PackageSelector(); gtk_container_add (GTK_CONTAINER (wizard), m_package_selector->getWidget()); + + Ypp::get()->setInterface (this); } virtual ~YGPackageSelector() { - YGDialog *dialog = YGUI::ui()->currentYGDialog(); - dialog->unsetCloseCallback(); delete m_package_selector; + ygtk_zypp_model_finish(); } protected: @@ -2472,201 +1428,334 @@ const gchar *action = (gchar *) id; if (!strcmp (action, "accept")) { - if (zyppPool().diffState <zypp::Package> ()) { - // in case of changes, check problems, ask for confirmation and JFDI. - if (pThis->confirmChanges() && solveProblems()) { - y2milestone ("Closing PackageSelector with 'accept'"); - YGUI::ui()->sendEvent (new YMenuEvent (YCPSymbol ("accept"))); - } - } - else - YGUI::ui()->sendEvent (new YCancelEvent()); + y2milestone ("Closing PackageSelector with 'accept'"); + YGUI::ui()->sendEvent (new YMenuEvent (YCPSymbol ("accept"))); } else if (!strcmp (action, "cancel")) { y2milestone ("Closing PackageSelector with 'cancel'"); - if (pThis->checkDelete()) - YGUI::ui()->sendEvent (new YCancelEvent()); + if (pThis->confirmExit()) + YGUI::ui()->sendEvent (new YCancelEvent()); } } - // helper function for confirmChanges - static bool isInstalled (const string &package) - { - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>(); - it != zyppPool().byKindEnd <zypp::Package>(); it++) { - if ((*it)->hasInstalledObj() || (*it)->toInstall()) { - if (package == (*it)->name()) - return true; - ZyppObject obj = (*it)->theObj(); - const zypp::CapSet &caps = obj->dep (zypp::Dep::PROVIDES); - for (zypp::CapSet::const_iterator jt = caps.begin(); - jt != caps.end(); jt++) - if (package == jt->asString()) - return true; - } - } - return false; // doesn't even exist - } + bool confirmExit() + { + if (!Ypp::get()->isModified()) + return true; + + GtkWidget *dialog; + dialog = gtk_message_dialog_new + (YGUI::ui()->currentWindow(), + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, _("Changes not saved!")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("Quit anyway?")); + gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_NO, + GTK_STOCK_QUIT, GTK_RESPONSE_YES, NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); + + bool ok = gtk_dialog_run (GTK_DIALOG (dialog)) == + GTK_RESPONSE_YES; + gtk_widget_destroy (dialog); + return ok; + } + static bool confirm_cb (void *pThis) + { return ((YGPackageSelector *)pThis)->confirmExit(); } - bool confirmChanges() + virtual bool acceptLicense (Ypp::Package *package, const std::string &license) { - IMPL - if (zyppPool().empty <zypp::Package> ()) - return false; + std::string title = package->name() + _(" License Agreement"); + GtkWidget *dialog = gtk_dialog_new_with_buttons (title.c_str(), + YGUI::ui()->currentWindow(), GTK_DIALOG_NO_SEPARATOR, + _("_Reject"), GTK_RESPONSE_REJECT, _("_Accept"), GTK_RESPONSE_ACCEPT, NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); - GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Changes Summary"), - YGUI::ui()->currentWindow(), - GtkDialogFlags (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("C_onfirm"), GTK_RESPONSE_ACCEPT, NULL); - - GtkWidget *install_label, *remove_label, *install_view, *remove_view; - install_label = gtk_label_new (_("To install:")); - remove_label = gtk_label_new (_("To remove:")); - install_view = gtk_tree_view_new(); - remove_view = gtk_tree_view_new(); - - GtkWidget *install_window, *remove_window; - install_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (install_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type - (GTK_SCROLLED_WINDOW (install_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (install_window), install_view); - remove_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (remove_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + GtkWidget *license_view, *license_window; + + license_view = ygtk_html_wrap_new(); + ygtk_html_wrap_set_text (license_view, license.c_str()); + + license_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (license_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type - (GTK_SCROLLED_WINDOW (remove_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (remove_window), remove_view); + (GTK_SCROLLED_WINDOW (license_window), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (license_window), license_view); GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox); - gtk_box_pack_start (vbox, install_label, FALSE, FALSE, 6); - gtk_box_pack_start (vbox, install_window, TRUE, TRUE, 6); - gtk_box_pack_start (vbox, remove_label, FALSE, FALSE, 6); - gtk_box_pack_start (vbox, remove_window, TRUE, TRUE, 6); + gtk_box_pack_start (vbox, license_window, TRUE, TRUE, 6); - // create model - { - GtkTreeStore *install_store = gtk_tree_store_new (1, G_TYPE_STRING); - GtkTreeStore *remove_store = gtk_tree_store_new (1, G_TYPE_STRING); + gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400); + gtk_widget_show_all (dialog); - // install view - GtkTreeViewColumn *column; - column = gtk_tree_view_column_new_with_attributes (_("Install packages"), - gtk_cell_renderer_text_new(), "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (install_view), column); - - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (install_view), FALSE); - gtk_tree_view_set_model (GTK_TREE_VIEW (install_view), - GTK_TREE_MODEL (install_store)); - g_object_unref (G_OBJECT (install_store)); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (install_view)), GTK_SELECTION_NONE);; - - // remove view - column = gtk_tree_view_column_new_with_attributes (_("Remove packages"), - gtk_cell_renderer_text_new(), "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (remove_view), column); - - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (remove_view), FALSE); - gtk_tree_view_set_model (GTK_TREE_VIEW (remove_view), - GTK_TREE_MODEL (remove_store)); - g_object_unref (G_OBJECT (remove_store)); - gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (remove_view)), GTK_SELECTION_NONE);; - - // construct model - for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>(); - it != zyppPool().byKindEnd <zypp::Package>(); it++) + gint ret = gtk_dialog_run (GTK_DIALOG (dialog)); + bool confirmed = (ret == GTK_RESPONSE_ACCEPT); + + gtk_widget_destroy (dialog); + return confirmed; + } + + virtual bool resolveProblems (std::list <Ypp::Problem *> problems) + { +fprintf (stderr, "resolving %d problems\n", problems.size()); + // we can't use ordinary radio buttons, as gtk+ enforces that in a group + // one must be selected... + + enum ColumnAlias { + SHOW_TOGGLE_COL, ACTIVE_TOGGLE_COL, TEXT_COL, WEIGHT_TEXT_COL, + APPLY_PTR_COL, TOOLTIP_TEXT_COL + }; + + struct inner { + static void solution_toggled (GtkTreeModel *model, GtkTreePath *path) { - ZyppSelectable selectable = *it; - if (!selectable) - continue; - - GtkTreeStore *store; - if (selectable->toInstall()) - store = install_store; - else if (selectable->toDelete()) - store = remove_store; - else continue; + GtkTreeStore *store = GTK_TREE_STORE (model); + GtkTreeIter iter, parent; - GtkTreeIter iter; - gtk_tree_store_append (store, &iter, NULL); - gtk_tree_store_set (store, &iter, 0, selectable->name().c_str(), -1); + gboolean enabled; + bool *apply; + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, ACTIVE_TOGGLE_COL, &enabled, + APPLY_PTR_COL, &apply, -1); + + // disable all the other radios on the group, setting current + gtk_tree_model_get_iter (model, &iter, path); + if (gtk_tree_model_iter_parent (model, &parent, &iter)) { + gtk_tree_model_iter_children (model, &iter, &parent); + do { + gtk_tree_store_set (store, &iter, ACTIVE_TOGGLE_COL, FALSE, -1); + bool *apply; + gtk_tree_model_get (model, &iter, APPLY_PTR_COL, &apply, -1); + *apply = false; + } while (gtk_tree_model_iter_next (model, &iter)); + } - // show dependencies -- we just ask Zypp for dependencies in the form - // of a string (which is the only way to do it anyway). - if (store == install_store) { - GtkTreeIter dep_iter; - ZyppObject object = selectable->theObj(); - const zypp::CapSet &capSet = object->dep (zypp::Dep::REQUIRES); - for (zypp::CapSet::const_iterator it = capSet.begin(); - it != capSet.end(); it++) { - // don't show if it is already installed - if (isInstalled (it->asString())) - continue; - - gtk_tree_store_append (store, &dep_iter, &iter); - gtk_tree_store_set (store, &dep_iter, - 0, it->asString().c_str(), -1); - } + enabled = !enabled; + if (apply) + *apply = enabled; + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_store_set (store, &iter, ACTIVE_TOGGLE_COL, enabled, -1); + } +#if 0 + static void renderer_toggled_cb (GtkCellRenderer *render, gchar *path_str, + GtkTreeModel *model) + { + GtkTreePath *path = gtk_tree_path_new_from_string (path_str); + solution_toggled (model, path); + gtk_tree_path_free (path); + } +#endif + static void cursor_changed_cb (GtkTreeView *view, GtkTreeModel *model) + { + GtkTreePath *path; + gtk_tree_view_get_cursor (view, &path, NULL); + solution_toggled (model, path); + gtk_tree_path_free (path); + } + static gboolean query_tooltip_cb (GtkWidget *view, gint x, gint y, + gboolean keyboard_mode, GtkTooltip *tooltip, gpointer data) + { + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + if (gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (view), + &x, &y, keyboard_mode, &model, &path, &iter)) { + gchar *tooltip_str; + gtk_tree_model_get (model, &iter, TOOLTIP_TEXT_COL, + &tooltip_str, -1); + gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (view), tooltip, path); + gtk_tree_path_free (path); + if (tooltip_str) { + gtk_tooltip_set_text (tooltip, tooltip_str); + g_free (tooltip_str); + return TRUE; } + } + return FALSE; - // show packages that require this -- we will need to iterate through - // all the packages... (not very accurate) - else { - GtkTreeIter req_iter; - - for (ZyppPool::const_iterator it = - zyppPool().byKindBegin <zypp::Package>(); - it != zyppPool().byKindEnd <zypp::Package>(); it++) { - // only show if it is installed - if ((*it)->hasInstalledObj() || (*it)->toInstall()) { - ZyppSelectable dep_selectable = *it; - ZyppObject dep_object = dep_selectable->theObj(); - - const zypp::CapSet &capSet = dep_object->dep (zypp::Dep::REQUIRES); - for (zypp::CapSet::const_iterator it = capSet.begin(); - it != capSet.end(); it++) { - if (it->asString() == selectable->name()) { - gtk_tree_store_append (store, &req_iter, &iter); - gtk_tree_store_set (store, &req_iter, - 0, dep_selectable->name().c_str(), -1); - break; - } - } - } - } + +/* + GtkTreePath *path; + if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view), x, y, + &path, NULL, NULL, NULL)) { + GtkTreeIter iter; + gchar *tooltip_text; + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_path_free (path); + gtk_tree_model_get (model, &iter, + TOOLTIP_TEXT_COL, &tooltip_text, -1); + // some strings are just " ", so we need to check that + // now, + bool empty = true; + for (int i = 0; tooltip_text[i] && empty; i++) + if (tooltip_text[i] != ' ') + empty = false; + if (empty) + gtk_tooltip_set_text (tooltip, "(no details)"); + else + gtk_tooltip_set_text (tooltip, tooltip_text); + g_free (tooltip_text); + return TRUE; } + return FALSE; +*/ + } + }; + + // model + GtkTreeStore *store = gtk_tree_store_new (6, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_STRING, G_TYPE_INT, G_TYPE_POINTER, G_TYPE_STRING); + for (std::list <Ypp::Problem *>::iterator it = problems.begin(); + it != problems.end(); it++) { + GtkTreeIter problem_iter; + gtk_tree_store_append (store, &problem_iter, NULL); + gtk_tree_store_set (store, &problem_iter, SHOW_TOGGLE_COL, FALSE, + TEXT_COL, (*it)->description.c_str(), + WEIGHT_TEXT_COL, PANGO_WEIGHT_BOLD, APPLY_PTR_COL, NULL, + TOOLTIP_TEXT_COL, (*it)->details.c_str(), -1); + + for (int i = 0; (*it)->getSolution (i); i++) { + Ypp::Problem::Solution *solution = (*it)->getSolution (i); + GtkTreeIter solution_iter; + const gchar *tooltip_text = solution->details.c_str(); + if (solution->details.empty()) + tooltip_text = NULL; + gtk_tree_store_append (store, &solution_iter, &problem_iter); + gtk_tree_store_set (store, &solution_iter, SHOW_TOGGLE_COL, TRUE, + ACTIVE_TOGGLE_COL, FALSE, TEXT_COL, solution->description.c_str(), + APPLY_PTR_COL, &solution->apply, + TOOLTIP_TEXT_COL, tooltip_text, -1); + } + } + + // interface + GtkWidget *dialog = gtk_message_dialog_new (YGUI::ui()->currentWindow(), + GtkDialogFlags (0), GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, + _("There are some conflicts on the transaction that must be " + "solved manually.")); + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_APPLY); + + GtkWidget *view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); + g_object_unref (G_OBJECT (store)); + gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( + GTK_TREE_VIEW (view)), GTK_SELECTION_NONE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); + gtk_tree_view_set_search_column (GTK_TREE_VIEW (view), TEXT_COL); + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + renderer = gtk_cell_renderer_toggle_new(); + gtk_cell_renderer_toggle_set_radio ( + GTK_CELL_RENDERER_TOGGLE (renderer), TRUE); +/* g_signal_connect (G_OBJECT (renderer), "toggled", + G_CALLBACK (inner::renderer_toggled_cb), store);*/ + // we should not connect the actual toggle button, as we toggle on row press + g_signal_connect (G_OBJECT (view), "cursor-changed", + G_CALLBACK (inner::cursor_changed_cb), store); + column = gtk_tree_view_column_new_with_attributes ("", renderer, + "visible", SHOW_TOGGLE_COL, "active", ACTIVE_TOGGLE_COL, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes ("", renderer, + "text", TEXT_COL, "weight", WEIGHT_TEXT_COL, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + gtk_tree_view_expand_all (GTK_TREE_VIEW (view)); + gtk_widget_set_has_tooltip (view, TRUE); + g_signal_connect (G_OBJECT (view), "query-tooltip", + G_CALLBACK (inner::query_tooltip_cb), store); + + GtkWidget *scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), + GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (scroll), view); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scroll); + + +#if 0 + // version that uses viewport, labels and radio buttons -- unfortunately, + // gtk+ enforces that one radio button per group to be selected -- we don't + // want that as the user may decide to do nothing for a certain action. + // We also don't want to add a "Do nothing" radio, as that would imply would + // dismiss the conflict. No, we just want to let the user try to resolve current + // conflicts... + struct inner { + static void solution_toggled (GtkToggleButton *toggle, bool *apply) + { *apply = gtk_toggle_button_get_active (toggle); } + }; + + GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Problem Resolver"), + YGUI::ui()->currentWindow(), GtkDialogFlags (0), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, NULL); + + GtkWidget *view_port = gtk_viewport_new (NULL, NULL); + gtk_viewport_set_shadow_type (GTK_VIEWPORT (view_port), GTK_SHADOW_NONE); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), view_port, + TRUE, TRUE, 0); + GtkWidget *main_box = gtk_vbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (view_port), main_box); + +fprintf (stderr, "populating main box\n"); + for (std::list <Ypp::Problem *>::iterator it = problems.begin(); + it != problems.end(); it++) { + GtkWidget *label, *box; +fprintf (stderr, "creating label: %s\n", (*it)->description.c_str()); + label = gtk_label_new ((*it)->description.c_str()); + YGUtils::setWidgetFont (label, PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM); +fprintf (stderr, "setting tooltyp: %s\n", (*it)->details.c_str()); + if (!(*it)->details.empty()) + gtk_widget_set_tooltip_text (label, (*it)->details.c_str()); + + GSList *group = NULL; + box = gtk_vbox_new (FALSE, 6); + for (int i = 0; (*it)->getSolution (i); i++) { + Ypp::Problem::Solution *solution = (*it)->getSolution (i); +fprintf (stderr, "creating radio: %s\n", solution->description.c_str()); + GtkWidget *radio = gtk_radio_button_new_with_label ( + group, solution->description.c_str()); +fprintf (stderr, "setting tooltip: %s\n", (*it)->details.c_str()); + if (!solution->details.empty()) + gtk_widget_set_tooltip_text (radio, solution->details.c_str()); + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); + gtk_box_pack_start (GTK_BOX (box), radio, FALSE, TRUE, 0); + g_signal_connect (G_OBJECT (radio), "toggled", + G_CALLBACK (inner::solution_toggled), &solution->apply); } + + gtk_box_pack_start (GTK_BOX (main_box), label, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (main_box), box, FALSE, TRUE, 0); } +#endif - gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400); + gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE); + gtk_window_set_default_size (GTK_WINDOW (dialog), -1, 480); gtk_widget_show_all (dialog); - bool confirmed = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT; + bool apply = (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_APPLY); gtk_widget_destroy (dialog); + return apply; + } - return confirmed; + virtual void packageModified (Ypp::Package *package) + { + m_package_selector->packageModified (package); } YGWIDGET_IMPL_COMMON }; -#endif /*DISABLE_PACKAGE_SELECTOR*/ YWidget * YGUI::createPackageSelector (YWidget *parent, YWidgetOpt &opt, const YCPString &floppyDevice) { - // TODO: floppyDevice really needed? -#ifndef DISABLE_PACKAGE_SELECTOR - if (opt.youMode.value()) +/* if (opt.youMode.value()) return new YGPatchSelector (opt, YGWidget::get (parent)); - else + else*/ return new YGPackageSelector (opt, YGWidget::get (parent)); -#else - return NULL; -#endif } YWidget * Modified: trunk/gtk/src/YGProgressBar.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGProgressBar.cc?rev=4321... ============================================================================== --- trunk/gtk/src/YGProgressBar.cc (original) +++ trunk/gtk/src/YGProgressBar.cc Thu Dec 20 21:36:55 2007 @@ -120,8 +120,7 @@ { // ygtk_ratio_box_set_homogeneous (YGTK_RATIO_BOX (getWidget()), TRUE); ygtk_ratio_box_set_spacing (YGTK_RATIO_BOX (getWidget()), 2); - - for (int i = segments()-1; i >= 0; i--) { + for (int s = 0; s < segments(); s++) { GtkWidget* bar = gtk_progress_bar_new(); gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (bar), horizontal ? GTK_PROGRESS_LEFT_TO_RIGHT : GTK_PROGRESS_BOTTOM_TO_TOP); @@ -132,7 +131,7 @@ else gtk_widget_set_size_request (bar, -1, min_size); ygtk_ratio_box_pack (YGTK_RATIO_BOX (getWidget()), bar, - maxValue (i), TRUE, TRUE, 0); + getSegmentWeight (s), TRUE, TRUE, 0); } ygtk_adj_size_set_max (YGTK_ADJ_SIZE (m_adj_size), horizontal ? 200 : 0, @@ -143,17 +142,29 @@ virtual void doUpdate() { GList* children = gtk_container_get_children (GTK_CONTAINER (getWidget())); - int n = segments()-1; - for (GList *i = children; i && n >= 0; i = i->next, n--) { + int s = 0; + for (GList *i = children; i && s < segments(); i = i->next, s++) { GtkProgressBar *bar = GTK_PROGRESS_BAR (i->data); - gfloat fraction = 0; - if (currentValue (n) != -1) - fraction = 1.0 - ((gfloat) currentValue(n) / maxValue(n)); - gtk_progress_bar_set_fraction (bar, fraction); + gtk_progress_bar_set_fraction (bar, getSegmentValue (s)); } g_list_free (children); } + int getSegmentWeight (int n) + { + if (vertical()) + n = (segments() - n) - 1; + return maxValue (n); + } + float getSegmentValue (int n) + { + if (vertical()) + n = (segments() - n) - 1; + if (currentValue (n) == -1) + return 0; + return 1.0 - (((float) currentValue (n)) / maxValue (n)); + } + YGWIDGET_IMPL_COMMON }; Modified: trunk/gtk/src/YGPushButton.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGPushButton.cc?rev=43212... ============================================================================== --- trunk/gtk/src/YGPushButton.cc (original) +++ trunk/gtk/src/YGPushButton.cc Thu Dec 20 21:36:55 2007 @@ -30,8 +30,6 @@ G_CALLBACK (set_default_cb), this); } - virtual ~YGPushButton() {} - // YPushButton virtual void setLabel (const YCPString &label) { Modified: trunk/gtk/src/YGUI.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUI.cc?rev=43212&r1=4321... ============================================================================== --- trunk/gtk/src/YGUI.cc (original) +++ trunk/gtk/src/YGUI.cc Thu Dec 20 21:36:55 2007 @@ -644,9 +644,7 @@ // debug dialogs -static void destroy_dialog (GtkDialog *dialog, gint arg) -{ IMPL; gtk_widget_destroy (GTK_WIDGET (dialog)); } - +//#define IS_VALID_COL void dumpYastTree (YWidget *widget) { IMPL @@ -667,7 +665,11 @@ gchar *weight = g_strdup_printf ("%ld x %ld", widget->weight (YD_HORIZ), widget->weight (YD_VERT)); gtk_tree_store_set (store, &iter, 0, widget->widgetClass(), - 1, ygwidget->getDebugLabel().c_str(), 2, stretch, 3, weight, -1); + 1, ygwidget->getDebugLabel().c_str(), 2, stretch, 3, weight, +#ifdef IS_VALID_COL + 4, widget->isValid(), +#endif + -1); g_free (stretch); g_free (weight); @@ -675,14 +677,37 @@ for (int i = 0; i < container->numChildren(); i++) dumpYastTree (container->child (i), store, &iter); } + static void dialog_response_cb (GtkDialog *dialog, gint response, YWidget *ywidget) + { + if (response == 1) { + GtkTreeStore *store; + GtkTreeView *view; + store = (GtkTreeStore *) g_object_get_data (G_OBJECT (dialog), "store"); + view = (GtkTreeView *) g_object_get_data (G_OBJECT (dialog), "view"); + gtk_tree_store_clear (store); + dumpYastTree (ywidget, store, NULL); + gtk_tree_view_expand_all (view); + } + else + gtk_widget_destroy (GTK_WIDGET (dialog)); + } }; - GtkTreeStore *store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING); - inner::dumpYastTree (widget, store, NULL); + int cols = 4; +#ifdef IS_VALID_COL + cols++; +#endif + GtkTreeStore *store = gtk_tree_store_new (cols, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING +#ifdef IS_VALID_COL + , G_TYPE_BOOLEAN +#endif + ); GtkWidget *dialog = gtk_dialog_new_with_buttons ("YWidgets Tree", NULL, - GtkDialogFlags (GTK_DIALOG_NO_SEPARATOR), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); + GtkDialogFlags (GTK_DIALOG_NO_SEPARATOR), GTK_STOCK_REFRESH, 1, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); gtk_window_set_default_size (GTK_WINDOW (dialog), -1, 400); GtkWidget *view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); @@ -692,13 +717,19 @@ gtk_tree_view_append_column (GTK_TREE_VIEW (view), gtk_tree_view_column_new_with_attributes ("Label", gtk_cell_renderer_text_new(), "text", 1, NULL)); + gtk_tree_view_column_set_expand (gtk_tree_view_get_column ( + GTK_TREE_VIEW (view), 1), TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (view), gtk_tree_view_column_new_with_attributes ("Stretch", gtk_cell_renderer_text_new(), "text", 2, NULL)); gtk_tree_view_append_column (GTK_TREE_VIEW (view), gtk_tree_view_column_new_with_attributes ("Weight", gtk_cell_renderer_text_new(), "text", 3, NULL)); - gtk_tree_view_expand_all (GTK_TREE_VIEW (view)); +#ifdef IS_VALID_COL + gtk_tree_view_append_column (GTK_TREE_VIEW (view), + gtk_tree_view_column_new_with_attributes ("Valid", + gtk_cell_renderer_toggle_new(), "active", 4, NULL)); +#endif gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (view), TRUE); GtkWidget *scroll_win = gtk_scrolled_window_new (NULL, NULL); @@ -709,10 +740,16 @@ gtk_container_add (GTK_CONTAINER (scroll_win), view); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scroll_win); - gtk_widget_show_all (dialog); + inner::dumpYastTree (widget, store, NULL); + gtk_tree_view_expand_all (GTK_TREE_VIEW (view)); + + g_object_set_data (G_OBJECT (dialog), "view", view); + g_object_set_data (G_OBJECT (dialog), "store", store); g_signal_connect (G_OBJECT (dialog), "response", - G_CALLBACK (destroy_dialog), 0); + G_CALLBACK (inner::dialog_response_cb), widget); + + gtk_widget_show_all (dialog); } #include <YRichText.h> @@ -754,6 +791,8 @@ for (int i = 0; i < container->numChildren(); i++) dumpYastHtml (container->child (i), box); } + static void destroy_dialog (GtkDialog *dialog, gint arg) + { gtk_widget_destroy (GTK_WIDGET (dialog)); } }; IMPL @@ -765,6 +804,6 @@ gtk_widget_show_all (dialog); g_signal_connect (G_OBJECT (dialog), "response", - G_CALLBACK (destroy_dialog), 0); + G_CALLBACK (inner::destroy_dialog), 0); } Modified: trunk/gtk/src/YGUtils.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUtils.cc?rev=43212&r1=4... ============================================================================== --- trunk/gtk/src/YGUtils.cc (original) +++ trunk/gtk/src/YGUtils.cc Thu Dec 20 21:36:55 2007 @@ -66,6 +66,8 @@ void YGUtils::replace (string &str, const char *mouth, int mouth_len, const char *food) { + if (mouth_len < 0) + mouth_len = strlen (mouth); unsigned int i = 0; while ((i = str.find (mouth, i)) != string::npos) { @@ -87,83 +89,27 @@ gtk_text_buffer_delete_mark (buffer, end_mark); } -/* Strings can ask for not being escape with the comment - <!-- DT:Rich --> */ -static bool dont_escape (const string &str) -{ - const char *comment = "<!-- DT:Rich -->"; - if (str.length() < sizeof (comment)) - return false; - for (unsigned int i = 0; i < sizeof (comment); i++) - if (str[i] != comment[i]) - return false; - return true; -} - -string YGUtils::escape_markup (const string &str, bool break_lines) +void YGUtils::escapeMarkup (string &str) { - if (dont_escape (str)) - return string (str); - - string ret; - ret.reserve (str.length()); for (unsigned int i = 0; i < str.length(); i++) { - char ch = str[i]; - switch (ch) { + switch (str[i]) { case '<': - ret += "<"; + str.erase (i, 1); + str.insert (i, "<"); break; case '>': - ret += ">"; + str.erase (i, 1); + str.insert (i, ">"); break; case '&': - ret += "&"; - break; - case '\n': - ret += "<br/>"; + str.erase (i, 1); + str.insert (i, "&"); break; default: - ret += ch; break; } } - - return ret; -} - -#if 0 -string YGUtils::escape_break_lines (const string &str, bool paragraph_mode) -{ - if (dont_escape (str)) - return str; - string res; - res.reserve (str.length() + 6); - if (paragraph_mode) - res = "<p>"; - /* on paragraph mode, dont break when there is no text on the paragraph. - otherwise, just dont break at the start of the text. */ - bool dont_break = true; - for (unsigned int i = 0; i != str.length(); i++) { - char ch = str[i]; - if (paragraph_mode && ch == '\n' && str[i-1] == '\n') { - if (!dont_break) - res += "</p><p>"; - dont_break = true; - } - else if (!paragraph_mode && ch == '\n') { - if (!dont_break) - res += "<br>"; - } - else { - res += ch; - dont_break = false; - } - } - if (paragraph_mode) - res += "</p>"; - return res; } -#endif #define PROD_ENTITY "&product;" @@ -503,7 +449,9 @@ { std::list <string> parts; unsigned int i, j; - for (j = 0, i = 0; i < str.length(); i++) + // ignore first character, if separator + i = j = (str[0] == separator) ? 1 : 0; + for (; i < str.length(); i++) if (str[i] == separator) { parts.push_back (str.substr (j, i - j)); j = ++i; Modified: trunk/gtk/src/YGUtils.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUtils.h?rev=43212&r1=43... ============================================================================== --- trunk/gtk/src/YGUtils.h (original) +++ trunk/gtk/src/YGUtils.h Thu Dec 20 21:36:55 2007 @@ -9,6 +9,14 @@ #include <list> #include <gtk/gtktextview.h> #include <gtk/gtkeditable.h> +#include <gtk/gtktreeview.h> +#include <gtk/gtktreemodel.h> +#include <gtk/gtkcellrenderertoggle.h> + +// TODO: do a cleanup here. We should probably split string, gtk and stuff +// Some GtkTreeView should probably go to their own files +// Let's avoid GTK+ stuff, better to replicate that, if needed, than leave in +// this general purpose utils. /* YGUtils.h/cc have some functionality that is shared between different parts of the code. */ @@ -16,13 +24,13 @@ namespace YGUtils { /* Replaces Yast's '&' accelerator by Gnome's '_' (and proper escaping). */ - string mapKBAccel (const char *src); + std::string mapKBAccel (const char *src); /* Filters characters that are not on the valids_chars array from the text string Length is used to tell the length of text, in case it isn't NUL terminated (you may pass -1, if it is). Use the compare string member if you want to see if there was any change. */ - string filterText (const char* text, int length, const char* valid_chars); + std::string filterText (const char* text, int length, const char* valid_chars); /* Convenience call for widgets that implement GtkEditable interface. This function inserts and deletes text, if needed, so you may want @@ -31,11 +39,10 @@ const char *valid_chars); /* Replaces every 'mouth' by 'food' in 'str'. */ - void replace (string &str, const char *mouth, int mouth_len, const char *food); + void replace (std::string &str, const char *mouth, int mouth_len, const char *food); - /* Escapes markup text (eg. changes '<' by '\<'). - If break_line is true, the break line character will be transformed in <br/> */ - string escape_markup (const string &str, bool break_line = false); + /* Escapes markup text (eg. changes '<' by '\<'). */ + void escapeMarkup (std::string &str); /* Adds functionality to GtkTextView to scroll to bottom. */ void scrollTextViewDown(GtkTextView *text_view); @@ -52,11 +59,11 @@ int strcmp (const char *str1, const char *str2); /* Checks if a std::string contains some other string (case insensitive). */ - bool contains (const string &haystack, const string &needle); + bool contains (const std::string &haystack, const std::string &needle); /* Splits a string into parts as separated by the separator characters. eg: splitString ("Office/Writer", '/') => { "Office", "Writer" } */ - std::list <string> splitString (const string &str, char separator); + std::list <std::string> splitString (const std::string &str, char separator); /* Prints a GtkTreeModel for debugging purposes. */ void print_model (GtkTreeModel *model, int string_col); Modified: trunk/gtk/src/YGWizard.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGWizard.cc?rev=43212&r1=... ============================================================================== --- trunk/gtk/src/YGWizard.cc (original) +++ trunk/gtk/src/YGWizard.cc Thu Dec 20 21:36:55 2007 @@ -128,11 +128,9 @@ G_CALLBACK (action_triggered_cb), this); } - ~YGWizard() + virtual ~YGWizard() { - delete m_back_button; - delete m_abort_button; - delete m_next_button; + // m_back/abort/next_button are added as children and will be freed by ~YContainerWidget } /* The purpose of this function is to do some sanity checks, besides Modified: trunk/gtk/src/ygdkmngloader.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygdkmngloader.c?rev=43212... ============================================================================== --- trunk/gtk/src/ygdkmngloader.c (original) +++ trunk/gtk/src/ygdkmngloader.c Thu Dec 20 21:36:55 2007 @@ -113,7 +113,8 @@ return ret; is_file_mng_failed: - fclose (file); + if (file) + fclose (file); return FALSE; } Modified: trunk/gtk/src/ygtkratiobox.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkratiobox.h?rev=43212&... ============================================================================== --- trunk/gtk/src/ygtkratiobox.h (original) +++ trunk/gtk/src/ygtkratiobox.h Thu Dec 20 21:36:55 2007 @@ -96,8 +96,6 @@ gboolean *yfill, guint *padding, gboolean *expandable); -void ygtk_ratio_box_set_force_min_weight (YGtkRatioBox *box, gboolean force); - /* RatioHBox */ #define YGTK_TYPE_RATIO_HBOX (ygtk_ratio_hbox_get_type ()) Modified: trunk/gtk/src/ygtkwizard.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkwizard.c?rev=43212&r1... ============================================================================== --- trunk/gtk/src/ygtkwizard.c (original) +++ trunk/gtk/src/ygtkwizard.c Thu Dec 20 21:36:55 2007 @@ -312,7 +312,7 @@ wizard->m_title_image = gtk_image_new(); wizard->m_title_label = gtk_label_new(""); gtk_label_set_ellipsize (GTK_LABEL (wizard->m_title_label), PANGO_ELLIPSIZE_END); - gtk_misc_set_alignment (GTK_MISC (wizard->m_title_label), 0, 0); + gtk_misc_set_alignment (GTK_MISC (wizard->m_title_label), 0, 0.5); // setup label look gtk_widget_modify_fg (wizard->m_title_label, GTK_STATE_NORMAL, @@ -366,7 +366,7 @@ gtk_size_group_add_widget (buttons_group, wizard->m_abort_button); g_object_unref (G_OBJECT (buttons_group)); - //** The menu and the navigation widget will be created when requested. + //** The menu and the navigation widgets will be created when requested. //** Help dialog will be build on realize so we can give it a parent window. } @@ -413,8 +413,9 @@ DESTROY_WIDGET (wizard->m_title) DESTROY_WIDGET (wizard->m_buttons) DESTROY_WIDGET (wizard->m_menu) - DESTROY_WIDGET (wizard->m_navigation) + DESTROY_WIDGET (wizard->m_steps) DESTROY_WIDGET (wizard->m_title) + DESTROY_WIDGET (wizard->m_pane) #undef DESTROY_WIDGET if (wizard->m_help_dialog) { @@ -445,56 +446,75 @@ void ygtk_wizard_enable_steps (YGtkWizard *wizard) { - if (wizard->m_navigation) { - g_error ("YGtkWizard: a tree or steps widgets have already been enabled."); - return; - } - wizard->m_navigation_widget = ygtk_steps_new(); - wizard->m_navigation = wizard->m_navigation_widget; - gtk_widget_modify_text (wizard->m_navigation_widget, GTK_STATE_NORMAL, - &wizard->m_navigation_widget->style->fg [GTK_STATE_SELECTED]); + g_return_if_fail (wizard->m_steps == NULL); - gtk_widget_set_parent (wizard->m_navigation, GTK_WIDGET (wizard)); - gtk_widget_show_all (wizard->m_navigation); + wizard->m_steps = ygtk_steps_new(); + gtk_widget_modify_text (wizard->m_steps, GTK_STATE_NORMAL, + &wizard->m_steps->style->fg [GTK_STATE_SELECTED]); + + gtk_widget_set_parent (wizard->m_steps, GTK_WIDGET (wizard)); + gtk_widget_show (wizard->m_steps); + gtk_widget_queue_resize (GTK_WIDGET (wizard)); } void ygtk_wizard_enable_tree (YGtkWizard *wizard) { - if (wizard->m_navigation) { - g_error ("YGtkWizard: a tree or steps widgets have already been enabled."); - return; - } + g_return_if_fail (wizard->m_tree == NULL); - wizard->m_navigation_widget = gtk_tree_view_new_with_model + wizard->m_tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_STRING))); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (wizard->m_navigation_widget), - 0, "(no title)", gtk_cell_renderer_text_new(), "text", 0, NULL); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (wizard->m_navigation_widget), FALSE); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (wizard->m_tree_view), + 0, "", gtk_cell_renderer_text_new(), "text", 0, NULL); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (wizard->m_tree_view), FALSE); gtk_tree_selection_set_mode (gtk_tree_view_get_selection ( - GTK_TREE_VIEW (wizard->m_navigation_widget)), GTK_SELECTION_BROWSE); + GTK_TREE_VIEW (wizard->m_tree_view)), GTK_SELECTION_BROWSE); - g_signal_connect (G_OBJECT (wizard->m_navigation_widget), "cursor-changed", + g_signal_connect (G_OBJECT (wizard->m_tree_view), "cursor-changed", G_CALLBACK (tree_item_selected_cb), wizard); - wizard->m_navigation = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wizard->m_navigation), + wizard->m_tree = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wizard->m_tree), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (wizard->m_navigation), + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (wizard->m_tree), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (wizard->m_navigation), wizard->m_navigation_widget); - gtk_widget_set_size_request (wizard->m_navigation, 180, -1); + gtk_container_add (GTK_CONTAINER (wizard->m_tree), wizard->m_tree_view); + gtk_widget_set_size_request (wizard->m_tree, 180, -1); - gtk_widget_set_parent (wizard->m_navigation, GTK_WIDGET (wizard)); - gtk_widget_show_all (wizard->m_navigation); - gtk_widget_queue_draw (GTK_WIDGET (wizard)); + GtkWidget *child = wizard->m_child, *pane; + pane = gtk_hpaned_new(); + gtk_paned_pack1 (GTK_PANED (pane), wizard->m_tree, TRUE, TRUE); + gtk_widget_show_all (pane); + ygtk_wizard_set_child (wizard, pane); + wizard->m_pane = pane; + if (child) + gtk_container_add (GTK_CONTAINER (wizard), child); +} + +static void ygtk_wizard_add_child (GtkContainer *container, GtkWidget *child) +{ + YGtkWizard *wizard = YGTK_WIZARD (container); + wizard->m_child = child; + if (wizard->m_pane) + gtk_paned_pack2 (GTK_PANED (wizard->m_pane), child, TRUE, FALSE); + else + GTK_CONTAINER_CLASS (ygtk_wizard_parent_class)->add (container, child); +} + +static void ygtk_wizard_remove_child (GtkContainer *container, GtkWidget *child) +{ + YGtkWizard *wizard = YGTK_WIZARD (container); + wizard->m_child = NULL; + if (wizard->m_pane) + gtk_container_remove (GTK_CONTAINER (wizard->m_pane), child); + else + GTK_CONTAINER_CLASS (ygtk_wizard_parent_class)->remove (container, child); } void ygtk_wizard_set_child (YGtkWizard *wizard, GtkWidget *new_child) { - GtkWidget *child = GTK_BIN (wizard)->child; - if (child) - gtk_container_remove (GTK_CONTAINER (wizard), child); + if (wizard->m_child) + gtk_container_remove (GTK_CONTAINER (wizard), wizard->m_child); if (new_child) gtk_container_add (GTK_CONTAINER (wizard), new_child); } @@ -520,7 +540,7 @@ const char *text, const char *id) { GtkTreeModel *model = gtk_tree_view_get_model - (GTK_TREE_VIEW (wizard->m_navigation_widget)); + (GTK_TREE_VIEW (wizard->m_tree_view)); GtkTreeIter iter; if (!parent_id || !*parent_id) @@ -552,7 +572,7 @@ void ygtk_wizard_clear_tree (YGtkWizard *wizard) { - GtkTreeView *tree = GTK_TREE_VIEW (wizard->m_navigation_widget); + GtkTreeView *tree = GTK_TREE_VIEW (wizard->m_tree_view); gtk_tree_store_clear (GTK_TREE_STORE (gtk_tree_view_get_model (tree))); yg_hash_table_remove_all (wizard->tree_ids); } @@ -563,17 +583,17 @@ if (path == NULL) return FALSE; - g_signal_handlers_block_by_func (wizard->m_navigation_widget, + g_signal_handlers_block_by_func (wizard->m_tree_view, (gpointer) tree_item_selected_cb, wizard); - GtkWidget *widget = wizard->m_navigation_widget; + GtkWidget *widget = wizard->m_tree_view; gtk_tree_view_expand_to_path (GTK_TREE_VIEW (widget), path); gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path, NULL, FALSE); gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget), path, NULL, TRUE, 0.5, 0.5); - g_signal_handlers_unblock_by_func (wizard->m_navigation_widget, + g_signal_handlers_unblock_by_func (wizard->m_tree_view, (gpointer) tree_item_selected_cb, wizard); return TRUE; } @@ -766,15 +786,15 @@ void ygtk_wizard_add_step_header (YGtkWizard *wizard, const char *text) { - g_return_if_fail (wizard->m_navigation_widget != NULL); - ygtk_steps_append_heading (YGTK_STEPS (wizard->m_navigation_widget), text); + g_return_if_fail (wizard->m_steps != NULL); + ygtk_steps_append_heading (YGTK_STEPS (wizard->m_steps), text); } void ygtk_wizard_add_step (YGtkWizard *wizard, const char* text, const char *id) { guint step_nb; - g_return_if_fail (wizard->m_navigation_widget != NULL); - step_nb = ygtk_steps_append (YGTK_STEPS (wizard->m_navigation_widget), text); + g_return_if_fail (wizard->m_steps != NULL); + step_nb = ygtk_steps_append (YGTK_STEPS (wizard->m_steps), text); g_hash_table_insert (wizard->steps_ids, g_strdup (id), GINT_TO_POINTER (step_nb)); } @@ -783,14 +803,13 @@ gpointer step_nb = g_hash_table_lookup (wizard->steps_ids, id); if (!step_nb) return FALSE; - ygtk_steps_set_current (YGTK_STEPS (wizard->m_navigation_widget), - GPOINTER_TO_INT (step_nb)); + ygtk_steps_set_current (YGTK_STEPS (wizard->m_steps), GPOINTER_TO_INT (step_nb)); return TRUE; } void ygtk_wizard_clear_steps (YGtkWizard *wizard) { - ygtk_steps_clear (YGTK_STEPS (wizard->m_navigation_widget)); + ygtk_steps_clear (YGTK_STEPS (wizard->m_steps)); yg_hash_table_remove_all (wizard->steps_ids); } @@ -809,7 +828,7 @@ const gchar *ygtk_wizard_get_tree_selection (YGtkWizard *wizard) { GtkTreePath *path; - gtk_tree_view_get_cursor (GTK_TREE_VIEW (wizard->m_navigation_widget), + gtk_tree_view_get_cursor (GTK_TREE_VIEW (wizard->m_tree_view), &path, NULL); if (path == NULL) return NULL; @@ -825,7 +844,7 @@ void ygtk_wizard_set_sensitive (YGtkWizard *wizard, gboolean sensitive) { - // FIXME: check if this chains through + // TODO: check if this chains through gtk_widget_set_sensitive (GTK_WIDGET (wizard), sensitive); if (ygtk_wizard_is_next_button_protected (wizard)) @@ -862,8 +881,8 @@ { GtkRequisition nav_req, child_req; - if (wizard->m_navigation) { - gtk_widget_size_request (wizard->m_navigation, &nav_req); + if (wizard->m_steps) { + gtk_widget_size_request (wizard->m_steps, &nav_req); nav_req.width += content_padding * 2; nav_req.height += content_padding * 2; } @@ -951,8 +970,8 @@ nav_area.x = child_area.x; nav_area.y = child_area.y; nav_area.height = child_area.height; - if (wizard->m_navigation) { - gtk_widget_get_child_requisition (wizard->m_navigation, &req); + if (wizard->m_steps) { + gtk_widget_get_child_requisition (wizard->m_steps, &req); nav_area.width = req.width + content_padding*2; child_area.x += nav_area.width; @@ -981,9 +1000,9 @@ } // navigation pane - if (wizard->m_navigation) { + if (wizard->m_steps) { apply_allocation_padding (&nav_area, content_padding); - gtk_widget_size_allocate (wizard->m_navigation, &nav_area); + gtk_widget_size_allocate (wizard->m_steps, &nav_area); } // buttons @@ -1025,10 +1044,10 @@ w -= content_padding*2; y += wizard->m_title->allocation.height + header_padding*2 + content_padding; h -= wizard->m_title->allocation.height + header_padding*2 + content_padding*2; - if (wizard->m_navigation) { - int navigation_w = wizard->m_navigation->allocation.width; - x += navigation_w + content_padding; - w -= navigation_w + content_padding; + if (wizard->m_steps) { + int steps_w = wizard->m_steps->allocation.width; + x += steps_w + content_padding; + w -= steps_w + content_padding; } gdk_cairo_set_source_color (cr, &widget->style->bg [GTK_STATE_NORMAL]); @@ -1042,8 +1061,8 @@ if (wizard->m_menu) gtk_container_propagate_expose (container, wizard->m_menu, event); gtk_container_propagate_expose (container, wizard->m_title, event); - if (wizard->m_navigation) - gtk_container_propagate_expose (container, wizard->m_navigation, event); + if (wizard->m_steps) + gtk_container_propagate_expose (container, wizard->m_steps, event); gtk_container_propagate_expose (container, wizard->m_buttons, event); if (GTK_BIN (container)->child) gtk_container_propagate_expose (container, GTK_BIN (container)->child, event); @@ -1059,8 +1078,8 @@ (*callback) (wizard->m_buttons, callback_data); if (wizard->m_menu) (*callback) (wizard->m_menu, callback_data); - if (wizard->m_navigation) - (*callback) (wizard->m_navigation, callback_data); + if (wizard->m_steps) + (*callback) (wizard->m_steps, callback_data); } GtkWidget *containee = GTK_BIN (container)->child; @@ -1068,150 +1087,6 @@ (*callback) (containee, callback_data); } -/* Accessibility support */ - -static gint ygtk_wizard_accessible_get_n_children (AtkObject *accessible) -{ - return 1 /* content*/ + 5 /* buttons*/; -} - -static AtkObject *ygtk_wizard_accessible_ref_child (AtkObject *accessible, - gint index) -{ - GtkWidget *widget = GTK_ACCESSIBLE (accessible)->widget; - if (!widget) - return NULL; - YGtkWizard *wizard = YGTK_WIZARD (widget); - - if (index == 0) { - GtkWidget *child = GTK_BIN (wizard)->child; - if (child) - return g_object_ref (G_OBJECT (child)); - return NULL; - } - - if (index >= 1 && index <= 5) { - GtkWidget *buttons[5] = { wizard->m_back_button, wizard->m_abort_button, - wizard->m_next_button, wizard->m_help_button, - wizard->m_release_notes_button }; - GtkWidget *button = buttons [index-1]; - - if (GTK_WIDGET_VISIBLE (button)) - return g_object_ref (G_OBJECT (button)); - return NULL; - } - // out of range - return NULL; -} - -static void ygtk_wizard_accessible_class_init (AtkObjectClass *class) -{ - class->get_n_children = ygtk_wizard_accessible_get_n_children; - class->ref_child = ygtk_wizard_accessible_ref_child; -} - -static GType ygtk_wizard_accessible_get_type (void) -{ - static GType type = 0; - if (!type) { - AtkObjectFactory *factory; - GType derived_type; - GTypeQuery query; - GType derived_atk_type; - - derived_type = g_type_parent (YGTK_TYPE_WIZARD); - factory = atk_registry_get_factory (atk_get_default_registry (), derived_type); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - g_type_query (derived_atk_type, &query); - - GTypeInfo type_info = { 0 }; - type_info.class_size = query.class_size; - type_info.class_init = (GClassInitFunc) ygtk_wizard_accessible_class_init; - type_info.instance_size = query.instance_size; - - type = g_type_register_static (derived_atk_type, "YGtkWizardAccessible", - &type_info, 0); - -/* - type = g_type_register_static_simple (derived_atk_type, - "YGtkWizardAccessible", query.class_size, - (GClassInitFunc) ygtk_wizard_accessible_class_init, - query.instance_size, NULL, 0); -*/ - } - return type; -} - -static AtkObject *ygtk_wizard_accessible_new (GObject *obj) -{ - AtkObject *accessible; - g_return_val_if_fail (YGTK_IS_WIZARD (obj), NULL); - - accessible = g_object_new (ygtk_wizard_accessible_get_type (), NULL); - atk_object_initialize (accessible, obj); - return accessible; -} - -static GType ygtk_wizard_accessible_factory_get_accessible_type() -{ - return ygtk_wizard_accessible_get_type (); -} - -static AtkObject*ygtk_wizard_accessible_factory_create_accessible (GObject *obj) -{ - return ygtk_wizard_accessible_new (obj); -} - -static void ygtk_wizard_accessible_factory_class_init (AtkObjectFactoryClass *class) -{ - class->create_accessible = ygtk_wizard_accessible_factory_create_accessible; - class->get_accessible_type = ygtk_wizard_accessible_factory_get_accessible_type; -} - -static GType ygtk_wizard_accessible_factory_get_type (void) -{ - static GType type = 0; - if (!type) { - GTypeInfo type_info = { 0 }; - type_info.class_size = sizeof (AtkObjectFactoryClass); - type_info.class_init = (GClassInitFunc) ygtk_wizard_accessible_factory_class_init; - type_info.instance_size = sizeof (AtkObjectFactory); - - type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY, - "YGtkWizardAccessibleFactory", &type_info, 0); - -/* - type = g_type_register_static_simple (ATK_TYPE_OBJECT_FACTORY, - "YGtkWizardAccessibleFactory", sizeof (AtkObjectFactoryClass), - (GClassInitFunc) ygtk_wizard_accessible_factory_class_init, - sizeof (AtkObjectFactory), NULL, 0); -*/ - } - return type; -} - -static AtkObject *ygtk_wizard_get_accessible (GtkWidget *widget) -{ - static gboolean first_time = TRUE; - if (first_time) { - AtkObjectFactory *factory; - AtkRegistry *registry; - GType derived_type; - GType derived_atk_type; - - derived_type = g_type_parent (YGTK_TYPE_WIZARD); - registry = atk_get_default_registry (); - factory = atk_registry_get_factory (registry, derived_type); - derived_atk_type = atk_object_factory_get_accessible_type (factory); - if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE)) { - atk_registry_set_factory_type (registry, YGTK_TYPE_WIZARD, - ygtk_wizard_accessible_factory_get_type ()); - } - first_time = FALSE; - } - return GTK_WIDGET_CLASS (ygtk_wizard_parent_class)->get_accessible (widget); -} - static void ygtk_wizard_class_init (YGtkWizardClass *klass) { ygtk_wizard_parent_class = g_type_class_peek_parent (klass); @@ -1222,10 +1097,11 @@ widget_class->realize = ygtk_wizard_realize; widget_class->size_request = ygtk_wizard_size_request; widget_class->size_allocate = ygtk_wizard_size_allocate; - widget_class->get_accessible = ygtk_wizard_get_accessible; GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); container_class->forall = ygtk_wizard_forall; + container_class->add = ygtk_wizard_add_child; + container_class->remove = ygtk_wizard_remove_child; GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); gtkobject_class->destroy = ygtk_wizard_destroy; Modified: trunk/gtk/src/ygtkwizard.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkwizard.h?rev=43212&r1... ============================================================================== --- trunk/gtk/src/ygtkwizard.h (original) +++ trunk/gtk/src/ygtkwizard.h Thu Dec 20 21:36:55 2007 @@ -81,11 +81,12 @@ GHashTable *steps_ids; /* gchar* -> guint */ /* Widgets for layout. */ - GtkWidget *m_menu, *m_title, *m_navigation, *m_buttons; + GtkWidget *m_menu, *m_title, *m_steps, *m_tree, *m_buttons; + GtkWidget *m_child, *m_pane; // containee can be accessed via GTK_BIN (wizard)->child /* Widgets we need to have access to. */ - GtkWidget *m_title_label, *m_title_image, *m_navigation_widget, + GtkWidget *m_title_label, *m_title_image, *m_tree_view, *m_back_button, *m_abort_button, *m_next_button, *m_help_button, *m_release_notes_button; -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org
participants (1)
-
rpmcruz@svn.opensuse.org