Author: tgoettlicher
Date: Mon Aug 1 09:44:45 2011
New Revision: 65095
URL: http://svn.opensuse.org/viewcvs/yast?rev=65095&view=rev
Log: (empty)
Added:
branches/SuSE-Code-11-SP2-Branch/gtk/CMakeLists.txt
branches/SuSE-Code-11-SP2-Branch/gtk/FindGTK2.cmake
branches/SuSE-Code-11-SP2-Branch/gtk/HACKING
branches/SuSE-Code-11-SP2-Branch/gtk/MAINTAINER
branches/SuSE-Code-11-SP2-Branch/gtk/Makefile
branches/SuSE-Code-11-SP2-Branch/gtk/Makefile.cvs
branches/SuSE-Code-11-SP2-Branch/gtk/README
branches/SuSE-Code-11-SP2-Branch/gtk/RPMNAME
branches/SuSE-Code-11-SP2-Branch/gtk/TODO
branches/SuSE-Code-11-SP2-Branch/gtk/VERSION
branches/SuSE-Code-11-SP2-Branch/gtk/VERSION.cmake
branches/SuSE-Code-11-SP2-Branch/gtk/config.h.cmake
branches/SuSE-Code-11-SP2-Branch/gtk/package/
branches/SuSE-Code-11-SP2-Branch/gtk/package/yast2-gtk.changes
branches/SuSE-Code-11-SP2-Branch/gtk/src/
branches/SuSE-Code-11-SP2-Branch/gtk/src/CMakeLists.txt
branches/SuSE-Code-11-SP2-Branch/gtk/src/Y2CCGtk.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGBarGraph.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGComboBox.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDumbTab.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGFrame.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGImage.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGInputField.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGIntField.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLabel.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLayout.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGMenuButton.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginIf.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginStub.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGProgressBar.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPushButton.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGRadioButton.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGText.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGTreeView.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWizard.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/YGi18n.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/dummy.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/hr.xpm
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/CMakeLists.txt
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/pkg-selector-help.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerywidget.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/test.cc
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygdkmngloader.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygdkmngloader.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkbargraph.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkbargraph.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkfieldentry.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkfieldentry.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkfixed.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkfixed.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkhtmlwrap.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkhtmlwrap.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkimage.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkimage.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtklinklabel.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtklinklabel.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkmenubutton.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkmenubutton.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkratiobox.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkratiobox.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkrichtext.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkrichtext.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtksteps.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtksteps.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtktextview.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtktextview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtktimezonepicker.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtktimezonepicker.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtktreeview.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtktreeview.h
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkwizard.c
branches/SuSE-Code-11-SP2-Branch/gtk/src/ygtkwizard.h
branches/SuSE-Code-11-SP2-Branch/gtk/tests/
branches/SuSE-Code-11-SP2-Branch/gtk/tests/ButtonOrder.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Cursor.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Dialog-Several.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/FileDialog.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Frame.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/IconButton.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/IconItems-ComboBox.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/IconItems-MultiSelectionBox.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/IconItems-SelectionBox.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Image.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/ImageMng.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/InputField-Event.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/InvalidWidget.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Label-Underline.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Align-Weight.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-AlignStretch.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Expand.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Frame2.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-HVCenter-Align.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-ReplacePoint.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Split-Split.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Truncated-Widget.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Wizard-BackgroundWidget.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Wizard-OneWidget.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Layout-Wizard3.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/LogView.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/MainDialogs.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/MultiLine.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/MultiProgressMeterHuge.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/MultiProgressMeterVer.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/MultiSelectionBox.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/PollInput.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/ProgressBar.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/RichText1.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/RichText2.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/RussianAccel.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/SelectionBox.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Sleep.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Slider-Event.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/StockButtons.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/StockIcons.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Table-Edit.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Table3-4.ycp (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Tree-rebuild.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Tree3.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Wizard-ChangingTitle.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Wizard.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/Wizard2.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/WizardList.ycp
branches/SuSE-Code-11-SP2-Branch/gtk/tests/image.gif (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie1.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie2.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie3.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie4.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie5.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie6.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie7.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/tests/movie8.mng (with props)
branches/SuSE-Code-11-SP2-Branch/gtk/yast2-gtk.spec.in
branches/SuSE-Code-11-SP2-Branch/gtk/ycc/
branches/SuSE-Code-11-SP2-Branch/gtk/ycc/Makefile
branches/SuSE-Code-11-SP2-Branch/gtk/ycc/ycc.cpp
Added: branches/SuSE-Code-11-SP2-Branch/gtk/CMakeLists.txt
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/CMakeLists.txt?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/CMakeLists.txt (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/CMakeLists.txt Mon Aug 1 09:44:45 2011
@@ -0,0 +1,53 @@
+# cmake 2.6 requires this
+cmake_minimum_required (VERSION 2.4)
+
+project (yast2-gtk)
+
+## configure
+
+
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_BINARY_DIR}/../")
+
+find_package (GTK2 REQUIRED gtk)
+find_package (Libyui REQUIRED)
+find_package (Zypp REQUIRED)
+
+# debug while GTK2 support is shaky
+message (STATUS "GTK2 includes:" ${GTK2_INCLUDE_DIRS})
+message (STATUS "GTK2 libraries:" ${GTK2_LIBRARIES})
+
+# set libyui and libzypp versions
+execute_process (COMMAND pkg-config --modversion yast2-libyui COMMAND awk -F. "{ printf \"%d\", ($1 * 1000 + $2) * 1000 + $3;}" OUTPUT_VARIABLE YAST2_VERSION)
+if (NOT YAST2_VERSION)
+ message (FATAL_ERROR "Could not parse YaST2 (libyui) version.")
+endif (NOT YAST2_VERSION)
+
+execute_process (COMMAND pkg-config --modversion libzypp COMMAND awk -F. "{ printf \"%d\", ($1 * 1000 + $2) * 1000 + $3;}" OUTPUT_VARIABLE ZYPP_VERSION)
+if (NOT ZYPP_VERSION)
+ message (FATAL_ERROR "Could not parse Zypp version.")
+endif (NOT ZYPP_VERSION)
+
+set (CMAKE_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/share/YaST2/data/devtools/cmake/modules" ${CMAKE_MODULE_PATH})
+include (YastCommon)
+set (YAST_INCLUDE_DIR ${CMAKE_INSTALL_PREFIX}/include/YaST2)
+
+#set (DATADIR ${CMAKE_INSTALL_PREFIX}/share/YaST2/gtk/)
+set (LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/YaST2/locale)
+set (THEMEDIR ${CMAKE_INSTALL_PREFIX}/share/YaST2/theme/current)
+
+# create config.h (see config.h.cmake)
+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+
+## gcc flags
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Woverloaded-virtual -Wno-deprecated")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall")
+set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
+
+## make package
+
+set (RPMNAME "yast2-gtk")
+generate_packaging (${RPMNAME} ${VERSION})
+
+add_subdirectory (src)
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/FindGTK2.cmake
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/FindGTK2.cmake?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/FindGTK2.cmake (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/FindGTK2.cmake Mon Aug 1 09:44:45 2011
@@ -0,0 +1,554 @@
+# - FindGTK2.cmake
+# This module can find the GTK2 widget libraries and several of its other
+# optional components like gtkmm, glade, and glademm.
+#
+# NOTE: If you intend to use version checking, CMake 2.6.2 or later is
+# required.
+#
+# Specify one or more of the following components
+# as you call this find module. See example below.
+#
+# gtk
+# gtkmm
+# glade
+# glademm
+#
+# The following variables will be defined for your use
+#
+# GTK2_FOUND - Were all of your specified components found?
+# GTK2_INCLUDE_DIRS - All include directories
+# GTK2_LIBRARIES - All libraries
+#
+# GTK2_VERSION - The version of GTK2 found (x.y.z)
+# GTK2_MAJOR_VERSION - The major version of GTK2
+# GTK2_MINOR_VERSION - The minor version of GTK2
+# GTK2_PATCH_VERSION - The patch version of GTK2
+#
+# Optional variables you can define prior to calling this module:
+#
+# GTK2_DEBUG - Enables verbose debugging of the module
+# GTK2_SKIP_MARK_AS_ADVANCED - Disable marking cache variables as advanced
+#
+#=================
+# Example Usage:
+#
+# Call find_package() once, here are some examples to pick from:
+#
+# Require GTK 2.6 or later
+# find_package(GTK2 2.6 REQUIRED gtk)
+#
+# Require GTK 2.10 or later and Glade
+# find_package(GTK2 2.10 REQUIRED gtk glade)
+#
+# Search for GTK/GTKMM 2.8 or later
+# find_package(GTK2 2.8 COMPONENTS gtk gtkmm)
+#
+# if(GTK2_FOUND)
+# include_directories(${GTK2_INCLUDE_DIRS})
+# add_executable(mygui mygui.cc)
+# target_link_libraries(mygui ${GTK2_LIBRARIES})
+# endif()
+#
+
+#=============================================================================
+# Copyright 2009 Kitware, Inc.
+# Copyright 2008-2009 Philip Lowman
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+# Version 0.8 (1/4/2010)
+# * Get module working under MacOSX fink by adding /sw/include, /sw/lib
+# to PATHS and the gobject library
+# Version 0.7 (3/22/09)
+# * Checked into CMake CVS
+# * Added versioning support
+# * Module now defaults to searching for GTK if COMPONENTS not specified.
+# * Added HKCU prior to HKLM registry key and GTKMM specific environment
+# variable as per mailing list discussion.
+# * Added lib64 to include search path and a few other search paths where GTK
+# may be installed on Unix systems.
+# * Switched to lowercase CMake commands
+# * Prefaced internal variables with _GTK2 to prevent collision
+# * Changed internal macros to functions
+# * Enhanced documentation
+# Version 0.6 (1/8/08)
+# Added GTK2_SKIP_MARK_AS_ADVANCED option
+# Version 0.5 (12/19/08)
+# Second release to cmake mailing list
+
+#=============================================================
+# _GTK2_GET_VERSION
+# Internal function to parse the version number in gtkversion.h
+# _OUT_major = Major version number
+# _OUT_minor = Minor version number
+# _OUT_micro = Micro version number
+# _gtkversion_hdr = Header file to parse
+#=============================================================
+function(_GTK2_GET_VERSION _OUT_major _OUT_minor _OUT_micro _gtkversion_hdr)
+ file(READ ${_gtkversion_hdr} _contents)
+ if(_contents)
+ string(REGEX REPLACE ".*#define GTK_MAJOR_VERSION[ \t]+\\(([0-9]+)\\).*" "\\1" ${_OUT_major} "${_contents}")
+ string(REGEX REPLACE ".*#define GTK_MINOR_VERSION[ \t]+\\(([0-9]+)\\).*" "\\1" ${_OUT_minor} "${_contents}")
+ string(REGEX REPLACE ".*#define GTK_MICRO_VERSION[ \t]+\\(([0-9]+)\\).*" "\\1" ${_OUT_micro} "${_contents}")
+
+ if(NOT ${_OUT_major} MATCHES "[0-9]+")
+ message(FATAL_ERROR "Version parsing failed for GTK2_MAJOR_VERSION!")
+ endif()
+ if(NOT ${_OUT_minor} MATCHES "[0-9]+")
+ message(FATAL_ERROR "Version parsing failed for GTK2_MINOR_VERSION!")
+ endif()
+ if(NOT ${_OUT_micro} MATCHES "[0-9]+")
+ message(FATAL_ERROR "Version parsing failed for GTK2_MICRO_VERSION!")
+ endif()
+
+ set(${_OUT_major} ${${_OUT_major}} PARENT_SCOPE)
+ set(${_OUT_minor} ${${_OUT_minor}} PARENT_SCOPE)
+ set(${_OUT_micro} ${${_OUT_micro}} PARENT_SCOPE)
+ else()
+ message(FATAL_ERROR "Include file ${_gtkversion_hdr} does not exist")
+ endif()
+endfunction()
+
+#=============================================================
+# _GTK2_FIND_INCLUDE_DIR
+# Internal function to find the GTK include directories
+# _var = variable to set
+# _hdr = header file to look for
+#=============================================================
+function(_GTK2_FIND_INCLUDE_DIR _var _hdr)
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "_GTK2_FIND_INCLUDE_DIR( ${_var} ${_hdr} )")
+ endif()
+
+ set(_relatives
+ # FIXME
+ glibmm-2.4
+ glib-2.0
+ atk-1.0
+ atkmm-1.6
+ cairo
+ cairomm-1.0
+ gdkmm-2.4
+ giomm-2.4
+ gtk-2.0
+ gtkmm-2.4
+ libglade-2.0
+ libglademm-2.4
+ pango-1.0
+ pangomm-1.4
+ sigc++-2.0
+ )
+
+ set(_suffixes)
+ foreach(_d ${_relatives})
+ list(APPEND _suffixes ${_d})
+ list(APPEND _suffixes ${_d}/include) # for /usr/lib/gtk-2.0/include
+ endforeach()
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "include suffixes = ${_suffixes}")
+ endif()
+
+ find_path(${_var} ${_hdr}
+ PATHS
+ /usr/local/lib64
+ /usr/local/lib
+ /usr/lib64
+ /usr/lib
+ /opt/gnome/include
+ /opt/gnome/lib
+ /opt/openwin/include
+ /usr/openwin/lib
+ /sw/include
+ /sw/lib
+ $ENV{GTKMM_BASEPATH}/include
+ $ENV{GTKMM_BASEPATH}/lib
+ [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/include
+ [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/lib
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/include
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/lib
+ PATH_SUFFIXES
+ ${_suffixes}
+ )
+
+ if(${_var})
+ set(GTK2_INCLUDE_DIRS ${GTK2_INCLUDE_DIRS} ${${_var}} PARENT_SCOPE)
+ if(NOT GTK2_SKIP_MARK_AS_ADVANCED)
+ mark_as_advanced(${_var})
+ endif()
+ endif()
+
+endfunction(_GTK2_FIND_INCLUDE_DIR)
+
+#=============================================================
+# _GTK2_FIND_LIBRARY
+# Internal function to find libraries packaged with GTK2
+# _var = library variable to create
+#=============================================================
+function(_GTK2_FIND_LIBRARY _var _lib _expand_vc _append_version)
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "_GTK2_FIND_LIBRARY( ${_var} ${_lib} ${_expand_vc} ${_append_version} )")
+ endif()
+
+ # Not GTK versions per se but the versions encoded into Windows
+ # import libraries (GtkMM 2.14.1 has a gtkmm-vc80-2_4.lib for example)
+ # Also the MSVC libraries use _ for . (this is handled below)
+ set(_versions 2.20 2.18 2.16 2.14 2.12
+ 2.10 2.8 2.6 2.4 2.2 2.0
+ 1.20 1.18 1.16 1.14 1.12
+ 1.10 1.8 1.6 1.4 1.2 1.0)
+
+ set(_library)
+ set(_library_d)
+
+ set(_library ${_lib})
+
+ if(_expand_vc)
+ # Add vc80/vc90 midfixes
+ if(MSVC80)
+ set(_library ${_library}-vc80)
+ set(_library_d ${_library}-d)
+ elseif(MSVC90)
+ set(_library ${_library}-vc90)
+ set(_library_d ${_library}-d)
+ endif()
+ endif()
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "After midfix addition = ${_library} and ${_library_d}")
+ endif()
+
+ set(_lib_list)
+ set(_libd_list)
+ if(_append_version)
+ foreach(_ver ${_versions})
+ list(APPEND _lib_list "${_library}-${_ver}")
+ list(APPEND _libd_list "${_library_d}-${_ver}")
+ endforeach()
+ else()
+ set(_lib_list ${_library})
+ set(_libd_list ${_library_d})
+ endif()
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "library list = ${_lib_list} and library debug list = ${_libd_list}")
+ endif()
+
+ # For some silly reason the MSVC libraries use _ instead of .
+ # in the version fields
+ if(_expand_vc AND MSVC)
+ set(_no_dots_lib_list)
+ set(_no_dots_libd_list)
+ foreach(_l ${_lib_list})
+ string(REPLACE "." "_" _no_dots_library ${_l})
+ list(APPEND _no_dots_lib_list ${_no_dots_library})
+ endforeach()
+ # And for debug
+ set(_no_dots_libsd_list)
+ foreach(_l ${_libd_list})
+ string(REPLACE "." "_" _no_dots_libraryd ${_l})
+ list(APPEND _no_dots_libd_list ${_no_dots_libraryd})
+ endforeach()
+
+ # Copy list back to original names
+ set(_lib_list ${_no_dots_lib_list})
+ set(_libd_list ${_no_dots_libd_list})
+ endif()
+
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "While searching for ${_var}, our proposed library list is ${_lib_list}")
+ endif()
+
+ find_library(${_var}
+ NAMES ${_lib_list}
+ PATHS
+ /opt/gnome/lib
+ /opt/gnome/lib64
+ /usr/openwin/lib
+ /usr/openwin/lib64
+ /sw/lib
+ $ENV{GTKMM_BASEPATH}/lib
+ [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/lib
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/lib
+ )
+
+ if(_expand_vc AND MSVC)
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "While searching for ${_var}_DEBUG our proposed library list is ${_libd_list}")
+ endif()
+
+ find_library(${_var}_DEBUG
+ NAMES ${_libd_list}
+ PATHS
+ $ENV{GTKMM_BASEPATH}/lib
+ [HKEY_CURRENT_USER\\SOFTWARE\\gtkmm\\2.4;Path]/lib
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\gtkmm\\2.4;Path]/lib
+ )
+
+ if(${_var} AND ${_var}_DEBUG)
+ if(NOT GTK2_SKIP_MARK_AS_ADVANCED)
+ mark_as_advanced(${_var}_DEBUG)
+ endif()
+ set(GTK2_LIBRARIES ${GTK2_LIBRARIES} optimized ${${_var}} debug ${${_var}_DEBUG})
+ set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE)
+ endif()
+ else()
+ if(NOT GTK2_SKIP_MARK_AS_ADVANCED)
+ mark_as_advanced(${_var})
+ endif()
+ set(GTK2_LIBRARIES ${GTK2_LIBRARIES} ${${_var}})
+ set(GTK2_LIBRARIES ${GTK2_LIBRARIES} PARENT_SCOPE)
+ # Set debug to release
+ set(${_var}_DEBUG ${${_var}})
+ set(${_var}_DEBUG ${${_var}} PARENT_SCOPE)
+ endif()
+endfunction(_GTK2_FIND_LIBRARY)
+
+#=============================================================
+
+#
+# main()
+#
+
+set(GTK2_FOUND)
+set(GTK2_INCLUDE_DIRS)
+set(GTK2_LIBRARIES)
+
+if(NOT GTK2_FIND_COMPONENTS)
+ # Assume they only want GTK
+ set(GTK2_FIND_COMPONENTS gtk)
+endif()
+
+#
+# If specified, enforce version number
+#
+if(GTK2_FIND_VERSION)
+ cmake_minimum_required(VERSION 2.6.2)
+ set(GTK2_FAILED_VERSION_CHECK true)
+ if(GTK2_DEBUG)
+ message(STATUS "[FindGTK2.cmake:${CMAKE_CURRENT_LIST_LINE}] "
+ "Searching for version ${GTK2_FIND_VERSION}")
+ endif()
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h)
+ if(GTK2_GTK_INCLUDE_DIR)
+ _GTK2_GET_VERSION(GTK2_MAJOR_VERSION
+ GTK2_MINOR_VERSION
+ GTK2_PATCH_VERSION
+ ${GTK2_GTK_INCLUDE_DIR}/gtk/gtkversion.h)
+ set(GTK2_VERSION
+ ${GTK2_MAJOR_VERSION}.${GTK2_MINOR_VERSION}.${GTK2_PATCH_VERSION})
+ if(GTK2_FIND_VERSION_EXACT)
+ if(GTK2_VERSION VERSION_EQUAL GTK2_FIND_VERSION)
+ set(GTK2_FAILED_VERSION_CHECK false)
+ endif()
+ else()
+ if(GTK2_VERSION VERSION_EQUAL GTK2_FIND_VERSION OR
+ GTK2_VERSION VERSION_GREATER GTK2_FIND_VERSION)
+ set(GTK2_FAILED_VERSION_CHECK false)
+ endif()
+ endif()
+ else()
+ # If we can't find the GTK include dir, we can't do version checking
+ if(GTK2_FIND_REQUIRED AND NOT GTK2_FIND_QUIETLY)
+ message(FATAL_ERROR "Could not find GTK2 include directory")
+ endif()
+ return()
+ endif()
+
+ if(GTK2_FAILED_VERSION_CHECK)
+ if(GTK2_FIND_REQUIRED AND NOT GTK2_FIND_QUIETLY)
+ if(GTK2_FIND_VERSION_EXACT)
+ message(FATAL_ERROR "GTK2 version check failed. Version ${GTK2_VERSION} was found, version ${GTK2_FIND_VERSION} is needed exactly.")
+ else()
+ message(FATAL_ERROR "GTK2 version check failed. Version ${GTK2_VERSION} was found, at least version ${GTK2_FIND_VERSION} is required")
+ endif()
+ endif()
+
+ # If the version check fails, exit out of the module here
+ return()
+ endif()
+endif()
+
+#
+# Find all components
+#
+
+foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
+ if(_GTK2_component STREQUAL "gtk")
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIB_INCLUDE_DIR glib.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBCONFIG_INCLUDE_DIR glibconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLIB_LIBRARY glib false true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GOBJECT_INCLUDE_DIR gobject/gobject.h)
+ _GTK2_FIND_LIBRARY (GTK2_GOBJECT_LIBRARY gobject false true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDK_INCLUDE_DIR gdk/gdk.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDKCONFIG_INCLUDE_DIR gdkconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-x11 false true)
+ _GTK2_FIND_LIBRARY (GTK2_GDK_LIBRARY gdk-win32 false true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTK_INCLUDE_DIR gtk/gtk.h)
+ _GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-x11 false true)
+ _GTK2_FIND_LIBRARY (GTK2_GTK_LIBRARY gtk-win32 false true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_CAIRO_INCLUDE_DIR cairo.h)
+ _GTK2_FIND_LIBRARY (GTK2_CAIRO_LIBRARY cairo false false)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_PANGO_INCLUDE_DIR pango/pango.h)
+ _GTK2_FIND_LIBRARY (GTK2_PANGO_LIBRARY pango false true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_ATK_INCLUDE_DIR atk/atk.h)
+ _GTK2_FIND_LIBRARY (GTK2_ATK_LIBRARY atk false true)
+
+ #elseif(_GTK2_component STREQUAL "gdk_pixbuf")
+ #_GTK2_FIND_INCLUDE_DIR(GTK2_GDKPIXBUF_INCLUDE_DIR gdk-pixbuf/gdk-pixbuf.h)
+ #_GTK2_FIND_LIBRARY (GTK2_GDKPIXBUF_LIBRARY gdk_pixbuf false true)
+
+ elseif(_GTK2_component STREQUAL "gtkmm")
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMM_INCLUDE_DIR glibmm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLIBMMCONFIG_INCLUDE_DIR glibmmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLIBMM_LIBRARY glibmm true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMM_INCLUDE_DIR gdkmm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GDKMMCONFIG_INCLUDE_DIR gdkmmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GDKMM_LIBRARY gdkmm true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMM_INCLUDE_DIR gtkmm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GTKMMCONFIG_INCLUDE_DIR gtkmmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GTKMM_LIBRARY gtkmm true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_CAIROMM_INCLUDE_DIR cairomm/cairomm.h)
+ _GTK2_FIND_LIBRARY (GTK2_CAIROMM_LIBRARY cairomm true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_PANGOMM_INCLUDE_DIR pangomm.h)
+ _GTK2_FIND_LIBRARY (GTK2_PANGOMM_LIBRARY pangomm true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++_INCLUDE_DIR sigc++/sigc++.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_SIGC++CONFIG_INCLUDE_DIR sigc++config.h)
+ _GTK2_FIND_LIBRARY (GTK2_SIGC++_LIBRARY sigc true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMM_INCLUDE_DIR giomm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GIOMMCONFIG_INCLUDE_DIR giommconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GIOMM_LIBRARY giomm true true)
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_ATKMM_INCLUDE_DIR atkmm.h)
+ _GTK2_FIND_LIBRARY (GTK2_ATKMM_LIBRARY atkmm true true)
+
+ elseif(_GTK2_component STREQUAL "glade")
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLADE_INCLUDE_DIR glade/glade.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLADE_LIBRARY glade false true)
+
+ elseif(_GTK2_component STREQUAL "glademm")
+
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMM_INCLUDE_DIR libglademm.h)
+ _GTK2_FIND_INCLUDE_DIR(GTK2_GLADEMMCONFIG_INCLUDE_DIR libglademmconfig.h)
+ _GTK2_FIND_LIBRARY (GTK2_GLADEMM_LIBRARY glademm true true)
+
+ else()
+ message(FATAL_ERROR "Unknown GTK2 component ${_component}")
+ endif()
+endforeach()
+
+#
+# Solve for the GTK2 version if we haven't already
+#
+if(NOT GTK2_FIND_VERSION AND GTK2_GTK_INCLUDE_DIR)
+ _GTK2_GET_VERSION(GTK2_MAJOR_VERSION
+ GTK2_MINOR_VERSION
+ GTK2_PATCH_VERSION
+ ${GTK2_GTK_INCLUDE_DIR}/gtk/gtkversion.h)
+ set(GTK2_VERSION ${GTK2_MAJOR_VERSION}.${GTK2_MINOR_VERSION}.${GTK2_PATCH_VERSION})
+endif()
+
+#
+# Try to enforce components
+#
+
+set(_GTK2_did_we_find_everything true) # This gets set to GTK2_FOUND
+
+include(FindPackageHandleStandardArgs)
+
+foreach(_GTK2_component ${GTK2_FIND_COMPONENTS})
+ string(TOUPPER ${_GTK2_component} _COMPONENT_UPPER)
+
+ if(_GTK2_component STREQUAL "gtk")
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "Some or all of the gtk libraries were not found."
+ GTK2_GTK_LIBRARY
+ GTK2_GTK_INCLUDE_DIR
+
+ GTK2_GLIB_INCLUDE_DIR
+ GTK2_GLIBCONFIG_INCLUDE_DIR
+ GTK2_GLIB_LIBRARY
+
+ GTK2_GDK_INCLUDE_DIR
+ GTK2_GDKCONFIG_INCLUDE_DIR
+ GTK2_GDK_LIBRARY
+ )
+ elseif(_GTK2_component STREQUAL "gtkmm")
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "Some or all of the gtkmm libraries were not found."
+ GTK2_GTKMM_LIBRARY
+ GTK2_GTKMM_INCLUDE_DIR
+ GTK2_GTKMMCONFIG_INCLUDE_DIR
+
+ GTK2_GLIBMM_INCLUDE_DIR
+ GTK2_GLIBMMCONFIG_INCLUDE_DIR
+ GTK2_GLIBMM_LIBRARY
+
+ GTK2_GDKMM_INCLUDE_DIR
+ GTK2_GDKMMCONFIG_INCLUDE_DIR
+ GTK2_GDKMM_LIBRARY
+ )
+ elseif(_GTK2_component STREQUAL "glade")
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "The glade library was not found."
+ GTK2_GLADE_LIBRARY
+ GTK2_GLADE_INCLUDE_DIR
+ )
+ elseif(_GTK2_component STREQUAL "glademm")
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(GTK2_${_COMPONENT_UPPER} "The glademm library was not found."
+ GTK2_GLADEMM_LIBRARY
+ GTK2_GLADEMM_INCLUDE_DIR
+ GTK2_GLADEMMCONFIG_INCLUDE_DIR
+ )
+ endif()
+
+ if(NOT GTK2_${_COMPONENT_UPPER}_FOUND)
+ set(_GTK2_did_we_find_everything false)
+ endif()
+endforeach()
+
+if(_GTK2_did_we_find_everything AND NOT GTK2_VERSION_CHECK_FAILED)
+ set(GTK2_FOUND true)
+else()
+ # Unset our variables.
+ set(GTK2_FOUND false)
+ set(GTK2_VERSION)
+ set(GTK2_VERSION_MAJOR)
+ set(GTK2_VERSION_MINOR)
+ set(GTK2_VERSION_PATCH)
+ set(GTK2_INCLUDE_DIRS)
+ set(GTK2_LIBRARIES)
+endif()
+
+if(GTK2_INCLUDE_DIRS)
+ list(REMOVE_DUPLICATES GTK2_INCLUDE_DIRS)
+endif()
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/HACKING
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/HACKING?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/HACKING (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/HACKING Mon Aug 1 09:44:45 2011
@@ -0,0 +1,250 @@
+/* Documentation on YaST-GTK */
+
+YaST basis
+
+ Yast-core is a simple byte-code interpreted programming
+ language. On execution, two threads will be fired: one
+ for the interpreter that runs the YCP application, the other
+ for the interface. This is so because a user may want
+ to setup another machine while sitting confortably
+ with its GTK+ interface.
+
+ Yast-core offers an interface API, called YWidgets, that
+ is then wrapped, by dynamic loading at run-time, by
+ one of the available interface modules that the user
+ specified. This code is one of these modules.
+
+ Yast is usually distributed with the /sbin/yast script
+ that automatically looks for the best interface for
+ the environment.
+ Yast-core is located at /usr/lib/YaST2/bin/y2base ,
+ on the Suse distribution.
+
+ You don't need to know to program YCP, but you should
+ have a look at its API because it will give you some
+ insight into the platform. Yast documentation:
+ http://forgeftp.novell.com//yast/doc/SL10.1/tdg/
+
+Code structure
+
+ Hierarchy of some of the widgets:
+
+ YGWidget YWidget
+ | |
+ | /|
+ | / |
+ |\ YContainerWidget |
+ |\\ / |
+ |\\YGSplit |
+ |\\YGEmpty |
+ |\\YGSpacing |
+ | \YSSquash |
+ | YGAlignment /-------|
+ | / |
+ |\ YLabel |
+ | \ / |
+ | \---YGLabel |
+ | |
+ | |
+ |\ /|
+ | \ YTextEntry |
+ | YGLabeledWidget / |
+ | | \ / |
+ | | YGTextEntry |
+ | | |
+ | \ |
+ | YGScrolledWidget /---|
+ | \ / |
+ | \ YRichText |
+ | \ / |
+ | YGRichText |
+ | |
+ |..........................|
+
+
+ As you may see, everything inherits from both YGWidget
+ and YWidget. YWidget derivated classes provide virtual functions
+ that we must fill. A pointer to the interface class wrapper may
+ always be obtain with widgetRep().
+
+ On the other hand, YGWidget provides a common set of functionaly
+ with great value for code re-use and also makes the code more
+ robust and flexible since it provides an infrastructure to the
+ whole code.
+ YGWidgets always creates an associated GtkWidget object, as asked
+ by the class that inherits it, and that can be obtained via
+ getWidget().
+
+ Every YGWidget has an associated parent, with the single exception
+ of YGDialog, that provides their children with a GtkFixed container
+ that they sit upon. getFixed() is the recursive function that asks
+ the parent for its associated GtkFixed. Container widgets replace
+ getFixed() by one that returns a GtkFixed that they created, thus
+ closing the cycle.
+
+ YGLabeledWidget and YGSrolledWidget are simple children of
+ YGWidget that create the asked widget with a label or inside
+ a GtkScrolledWindow for code re-use value.
+
+ The force behind the all thing is in YGUI. Its header has the declaration
+ for the creation of all the widgets, while its implementation is done
+ on the widgets files, and also specifies whatever one widget is
+ supported or not. YGUI.cc has, for the most part, the code that switches
+ between our code and the main YWidget, since we all use the same thread.
+
+On specific widgets
+
+ Layout widgets
+
+ Old approach
+ What yast-ncurses and -qt do, and we used to follow, is to let
+ YWidget layout framework do that work for us.
+
+ Every container widget we implemented had an associated GtkFixed
+ that it returned with a getFixed(). Other widgets getFixed()
+ would request the parent's getFixed().
+
+ However this approach was actually quite complicated, because we
+ had to implement nicesize() and setSize() on container widgets in
+ a way that the containee would be placed there correctly. So, for
+ instance, for YGDumbTab, we had to request informations like the
+ tabs labels height, the frame around the page, etc. Furthermore,
+ the ultimate decision to drop the approach was when we redesigned
+ YGtkWizard. This time the steps widget was dynamic and the work
+ to check of any size change and report to YWidget just felt too
+ hackish. Attempts at abstracting this were successful, but not
+ very satisfactory from a code's point of view.
+
+ Current approach
+ Currently, we just implement the layout widgets ourselves. The
+ most important is YGSplit, which would be the equivalent of
+ GtkBox (though we use our YGtkRatioBox to support the weight
+ childs attribute).
+
+ The YGLayout code is just a little bigger than the previous, it's
+ easy to understand, and overall it made the code base smaller.
+ Furthermore, YWidgets had bugs like labels getting truncated
+ (which had to be avoided by an explicit request for recalculating
+ the whole layout geometry) that we don't suffer. The layout is
+ also a lot faster.
+
+ To set minimum size to widgets, to make them look prettier, we
+ install all widgets in our YGtkMinSize container. To be able
+ to honor the stretchable attribute, we also install this
+ into a GtkAlignment. So, YGWidget's getWidget() returns the
+ inner widget that is the one that our YWidget implementation ask
+ it to create, while getLayout() should be used for layouts to get
+ the outter widget, which would be the GtkAlignment. Furthermore
+ the GtkAlignment allows us to align the widget on YGAlignment
+ (which is just a proxy).
+
+ Most of the widgets are a no brainer. Any other widget should have
+ some comments as appropriate.
+
+Code practices
+
+ As you may have noticed from YGWidget.h, we use macros a lot to
+ enable common functionality, instead of virtual functions. This is
+ because simply in a few cases virtual functions would not apply --
+ ie. the need to call a parent class function. You would have to
+ override the virtual function everytime. With a macro, we may do:
+ #define YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (ParentClass) \
+ virtual setLabel (const YCPString &label) { \
+ doSetLabel (label); \
+ ParentClass::setLabel (label); \
+ }
+
+ The code style is heavily inspired on the Linux guideline:
+ http://pantransit.reptiles.org/prog/CodingStyle.html
+ There may be some differences as it obviously doesn't mention
+ C++ classes.
+ For indentations, tabs are used. For layout, spaces are used.
+ Example:
+ <tab>int variable_with_very_long_name = function (arg1,
+ <tab>.............................................arg2);
+ This ensures the code lays well in whatever editor the reader uses.
+ Lines must just be ensured to be breaked before the 80th column on
+ 4 stop tabs.
+
+ Speaking of classes, we don't use headers, unless we have to, as
+ opposite to the other interfaces code. There is no reason to
+ make them publicaly available and it just adds even more
+ files to the pool.
+ Also, we generally don't split classes into declaration and
+ implementation code, for the same reasons.
+
+ Variables and functions names follow Yast style (variableNameOne),
+ for the most part. Our Gtk widgets (on ygtk* files) are written
+ in C and follow this_name_style to fit better with GTK+ one.
+ We always prefix m_ to class memeber variables.
+
+ For GTK+ widgets, we follow some scheme. Most standing, we avoid declaring
+ functions, and do the class initilization, where the overloading is set,
+ at the bottom. When doing a widget, just copy and paste from another.
+
+Morphing Suse to use Yast-GTK
+
+ We haven't yet managed to create a Suse GTK-based installer, but
+ these steps should be close to that end.
+
+ 1. Pick the 1st CD of some Suse edition version ISO
+ (let's say it is named SUSE.iso)
+
+ 2. Ensure you have a live / working gtk+/Gnome install
+
+ 3. Get cramfs (not included on suse cds, just google it and it will be 1st
+ result), and compile it.
+
+ 4. Tweak the variables in gtkize-iso to suit
+ + you need a chunk of tmp space to unpack & re-build the iso
+
+ 5. Run ./gtkize-iso SUSE.iso /tmp/new.iso
+
+ 6. Ready to burn and try.
+
+LibZypp API overview
+
+ The Zypp library is a wrapper around at least two package repository
+ systems (zmd and rug). It is quite a monster with no clear API or
+ documentation, thus this section.
+
+ The first thing we need to do when using Zypp is to initializate it.
+ This is done for us by yast-core, so we don't have to care about that.
+
+ To get a list of packages, you iterate the Zypp pool, that you can get
+ with zypp::getZYpp()->poolProxy(). So, if you want to iterate through
+ the package pool, you would do:
+ for (zypp::ResPoolProxy::const_iterator it =
+ zypp::getZYpp()->poolProxy().byKindBegin zypp::Package();
+ it != zypp::getZYpp()->poolProxy().byKindEnd zypp::Package(); it++)
+ To iterate through patches, use zypp::Patch as the kind.
+
+ The iterators point to objects of type zypp::ui::Selectable::Ptr, where Ptr
+ is a boost intrusive_ptr -- so, you may turn that into a C pointers with
+ a "zypp::ui::Selectable *sel = get_pointer (*it);"
+
+ A Selectable object contains pointers to the installed version and all
+ available (through repositories) versions of some packages whose name
+ you may get with a zypp::ui::Selectable::name(). The package it considers
+ as the best from the available packages is what it calls a candidate.
+ Check /usr/include/zypp/ui/Selectable.h for its API.
+
+ You may get more details on a given packages by retriving the correspondent
+ zypp::ResObject from the Selectable of the version you want.
+ Check /usr/include/zypp/ResObject.h for its API.
+
+ To get even more information, you may cast the zypp::ResObject to a
+ zypp::Package or zypp::Patch, according to what you are iterating.
+ Since this is boost pointers we are dealing with, you would cast a
+ zypp::ResObject::constPtr like
+ zypp::dynamic_pointer_cast <const zypp::Package> (res_object);
+ Check /usr/include/zypp/Package.h / Patch.h for their API.
+
+ The reason why our categories tree is build in an ackward way is because you
+ get the category of a package with zypp::Package::group() which returns a
+ std::string like "Productivity/Networking/Email/Utilities". You can't build
+ the tree before you start adding packages since you don't have a way to know
+ its hierarchy.
+
+ To avoid the lengthy names of Zypp, we use some typedefs and inline helper
+ functions that you may find right on the start of YGPackageSelector.cc.
Added: branches/SuSE-Code-11-SP2-Branch/gtk/MAINTAINER
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/MAINTAINER?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/MAINTAINER (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/MAINTAINER Mon Aug 1 09:44:45 2011
@@ -0,0 +1,2 @@
+Ricardo Cruz \
+Michael Meeks
Added: branches/SuSE-Code-11-SP2-Branch/gtk/Makefile
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/Makefile?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/Makefile (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/Makefile Mon Aug 1 09:44:45 2011
@@ -0,0 +1,21 @@
+# Makefile meant only for convenience and to provide a nicer
+# interface for the newcomer.
+
+all:
+ make -f Makefile.cvs
+
+install:
+ make -f Makefile.cvs install
+
+clean:
+ rm -rf build
+
+package:
+ cd build ; make package_source
+ mv build/*.tar.bz2 build/package/* package
+
+test:
+ build/src/test
+
+.PHONY: all install clean package test
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/Makefile.cvs
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/Makefile.cvs?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/Makefile.cvs (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/Makefile.cvs Mon Aug 1 09:44:45 2011
@@ -0,0 +1,23 @@
+#
+# Makefile.cvs
+#
+
+LIB = $(shell y2tool get-lib)
+
+PREFIX = /usr
+
+configure:
+ mkdir -p build ;\
+ cd build ;\
+ cmake -DCMAKE_INSTALL_PREFIX=$(PREFIX) -DLIB=$(LIB) .. && make
+
+# use "VERBOSE=1 make" to read full gcc argument
+
+install: configure
+ cd build ;\
+ make && make install
+
+reconf:
+ cd build ;\
+ cmake rebuild_cache
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/README
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/README?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/README (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/README Mon Aug 1 09:44:45 2011
@@ -0,0 +1,58 @@
+/* Light information on YaST-GTK */
+
+License
+
+ This code is licensed under the GNU Lesser General Public License (LGPL)
+ version 2, or, at your option, any higher.
+
+A native GTK+ YaST2 UI !
+
+ This code creates a GTK+ plugin for YaST2. This plugin parallel
+ installs with everything else, and will never be used unless
+ explicitely invoked on the yast2 command line - ie. it won't break
+ your system; go-on you know you want to install it.
+
+Build pre-requisites
+
+ To make this compile you'll need the following packages installed
+ (at a minimum):
+
+ gcc-c++ cmake gtk2-devel yast2-devtools yast2-core-devel yast2-libyui-devel libzypp-devel
+
+ They all are distributed with Suse's CDs.
+
+Building / Installing
+
+ make && sudo make install [1]
+
+ [1] - if you want sudo not to ask you a password, add yourself to the
+ wheel group, and uncomment the related lines in /etc/sudoers
+
+Running
+
+ /usr/lib/YaST2/bin/y2base /usr/share/doc/packages/yast2-core/libyui/examples/HelloWorld.ycp gtk
+
+ From OpenSuse 10.3 on, it should be picked up automatically if you use Gnome.
+ For other desktops, you can set yast-gtk to be used by editing /etc/sysconfig/yast2 .
+
+ In case of oddness append --nothreads to the cmdline,
+ Also check the log file: ~/.y2log
+
+Documentation
+
+ A code overview is given on the HACKING file.
+ For documentation of YaST in general:
+ http://developer.novell.com/wiki/index.php/Special:Downloads/yast/doc
+
+ChangeLog
+
+ Changes associated with version releases are recorded at
+ package/yast2-gtk.changes
+
+ Individual svn changes can be read by issueing: svn log | less
+
+ Other usage examples:
+ Last 50 changes: svn log -l 50
+ Show also files changed: svn log -v
+ Changes for a given file: svn log src/YGUI.cc
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/RPMNAME
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/RPMNAME?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/RPMNAME (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/RPMNAME Mon Aug 1 09:44:45 2011
@@ -0,0 +1 @@
+yast2-gtk
Added: branches/SuSE-Code-11-SP2-Branch/gtk/TODO
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/TODO?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/TODO (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/TODO Mon Aug 1 09:44:45 2011
@@ -0,0 +1,58 @@
+/* List of missing features, actual bugs and other issues */
+
+Bugs
+
+ tests/Layout-TruncatedWidget.ycp
+ unlike yast2-qt, we trigger recalculation events on widget property
+ changes like the label or the button text.
+ Difficulty: High - Priority: Low
+
+ Honor YDialog's YWizardDialog directive
+ see bug 457758. We also want to make multiple Wizard instances
+ share the same help window. Overall, move a bunch of YGWizard
+ stuff into YGDialog domain.
+ Difficulty: Medium - Priority: Low
+
+Enhancements
+
+ Package manager search syntax
+ add proper Google syntax support. Consider also adding regex (add
+ radio boxes to entry's context menu).
+ Difficulty: Medium - Priority: Low
+
+ YGTextEntry / YGMultiLineEdit
+ Add undo/redo support. (Possibly work out a patch for GTK+.)
+ Difficulty: Low - Priority: Medium
+
+ YGtkFindEntry
+ Deprecate YGtkFindEntry usage in favor of GTK 2.16 GtkEntry new
+ APIs. Notice the requirements for the Package Manager: change
+ icon to reflect that of the context menu, and show arrow next
+ to the search icon.
+ Difficulty: Low - Priority: Low
+
+ YGPackageSelector.cc: FlexPane class
+ Deprecate in favor of GTK 2.16 GtkOrientation API for GtkPaned.
+ Difficulty: Low - Priority: Low
+
+ Installer look
+ Port or adopt yast2-qt's installer style file.
+ Difficulty: High - Priority: Low
+
+Build procedure
+
+ YGRichText
+ should use GtkHtml when available, so that we get support for tables.
+
+ Road block: the problem here is that Webkit doesn't work well for our
+ package-selector use (outside a scrolled window). Does it make sense to
+ keep YGtkRichText for that sole purpose?
+ Difficulty: Medium - Priority: Medium
+
+Test Framework
+
+ Regression tests
+ setup LDTP to run through all the tests/ and provoke as many code-paths
+ as possible.
+ Difficulty: High (tiresome) - Priority: Low
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/VERSION
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/VERSION?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/VERSION (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/VERSION Mon Aug 1 09:44:45 2011
@@ -0,0 +1 @@
+2.21.96
Added: branches/SuSE-Code-11-SP2-Branch/gtk/VERSION.cmake
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/VERSION.cmake?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/VERSION.cmake (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/VERSION.cmake Mon Aug 1 09:44:45 2011
@@ -0,0 +1,3 @@
+SET(VERSION_MAJOR "2")
+SET(VERSION_MINOR "21")
+SET(VERSION_PATCH "96")
Added: branches/SuSE-Code-11-SP2-Branch/gtk/config.h.cmake
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/config.h.cmake?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/config.h.cmake (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/config.h.cmake Mon Aug 1 09:44:45 2011
@@ -0,0 +1,8 @@
+/* Important paths */
+#cmakedefine THEMEDIR "${THEMEDIR}"
+#cmakedefine LOCALEDIR "${LOCALEDIR}"
+
+/* Version enumerations to develop backward compability */
+#cmakedefine YAST2_VERSION ${YAST2_VERSION}
+#cmakedefine ZYPP_VERSION ${ZYPP_VERSION}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/package/yast2-gtk.changes
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/package/yast2-gtk.changes?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/package/yast2-gtk.changes (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/package/yast2-gtk.changes Mon Aug 1 09:44:45 2011
@@ -0,0 +1,1177 @@
+-------------------------------------------------------------------
+Mon Jun 20 10:52:12 CET 2011 - tgoettlicher@suse.de
+
+- fixed build on SLE11SP2 (missing cmake module)
+
+-------------------------------------------------------------------
+Sat Apr 16 13:51:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.96
+- Tree widget: add recursiveSelection flag from yast2-libyui
+2.20.3.
+
+-------------------------------------------------------------------
+Fri Apr 15 20:45:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.95
+- use same keyboard string mnemonics as rest of yast2, to
+avoid confusing translators. (bnc#686452).
+
+-------------------------------------------------------------------
+Wed Mar 16 10:50:31 CET 2011 - tgoettlicher@suse.de
+
+- 2.21.94
+- fixed dependencies (bnc#667938)
+
+-------------------------------------------------------------------
+Fri Mar 04 09:07:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.93
+- firewall tool crash fix (bnc#677007).
+- refer to LibreOffice rather than OpenOffice.org in help text
+(bnc#675486).
+
+-------------------------------------------------------------------
+Fri Feb 11 15:05:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.92
+- fixed freeze in webpin search tool, and possibly others
+(bnc#670625).
+
+-------------------------------------------------------------------
+Tue Feb 08 18:28:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.91
+- fixed compatibility with upcoming yast2-libyui 2.20.1.
+
+-------------------------------------------------------------------
+Tue Feb 01 22:43:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.90
+- printer crash fix: printer tool was misbehaving, somestimes
+crashing, when selecting tree item. (Reported by Atri Bhattacharya.)
+
+-------------------------------------------------------------------
+Fri Jan 28 18:03:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.89
+- sw_single bug fix: the versions box is showing the to-install
+as marked for all versions, not merely the one who is actually
+going to get installed. (Reported by Atri.)
+
+-------------------------------------------------------------------
+Thu Jan 20 20:22:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.88
+- sw_single: using buttons instead of radios for the
+versions-box.
+- allow moving window by dragging the header.
+
+-------------------------------------------------------------------
+Wed Jan 05 23:00:00 WET 2011 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.87
+- bug fix: YTree was crashing with new libyui
+- YMultiSelectionBox and YTree: show selection count
+when main widget
+- sw_single: show "re-install" popup menu option
+for single package selections.
+
+-------------------------------------------------------------------
+Tue Dec 23 03:10:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.86
+- bug fix: combo box honor selection flag.
+
+-------------------------------------------------------------------
+Tue Dec 23 02:57:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.85
+- cope with upcoming libyui 2.19.2: implemented new
+YTree::multi-selection flag.
+
+-------------------------------------------------------------------
+Tue Dec 15 13:13:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.84
+- code to close packagekit deamon when running will be moved
+to the sw_single ycp level (bnc#659522)
+
+-------------------------------------------------------------------
+Thu Dec 09 23:33:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.83
+- fix: can't use combo-box popup menu when items are too
+long (bnc#595560).
+- table fix: not showing all popup entries on right-click.
+- log view fix: fixed flickering, and allow user to freely
+scroll.
+- sw_single: use same height for "all packages" item, and
+keep items sorted by name when sorting by status or another
+column.
+
+-------------------------------------------------------------------
+Wed Nov 10 18:07:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.82
+- tables: when pressing the context-menu key, show the popup
+menu next to the selected row, not under the mouse cursor.
+- sw_single: use bold for "all packages" or "all patches" row.
+
+-------------------------------------------------------------------
+Mon Nov 01 16:49:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.81
+- fix build for 11.2 (added cmake requirement version).
+
+-------------------------------------------------------------------
+Mon Nov 01 16:49:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.80
+- fix: show the software manager header bar.
+
+-------------------------------------------------------------------
+Sun Oct 31 18:43:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.79
+- work-around bug in global-menubar-applet, which isn't
+showing the software manager menu bar (bnc#595560)
+- improved performance of the upgrades filter.
+
+-------------------------------------------------------------------
+Wed Oct 20 21:06:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.78
+- fixes crash on inetd when sorting table (bnc#620513)
+
+-------------------------------------------------------------------
+Fri Oct 08 21:36:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.77
+- another string review.
+- added mnemonics to menu-bar.
+
+-------------------------------------------------------------------
+Thu Oct 07 13:22:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.76
+- sw_single: run solver at end, fixes bnc#620513.
+- rpm spec fix (now compatible with both 11.3 and factory).
+- got rid of included FindGTK2.cmake module.
+- overall string review.
+- text domain changed from "yast2-gtk" to "gtk".
+
+-------------------------------------------------------------------
+Mon Aug 30 10:48:27 CEST 2010 - vuntz@opensuse.org
+
+- Add yast2-gtk-fix-FindGTK2-gdk-pixbuf.patch to fix build with
+ gtk2 2.21.x: gdk-pixbuf was split and the include paths are
+ different now.
+
+-------------------------------------------------------------------
+Mon Aug 23 00:40:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.70
+- sw_single: package count wrong on the filters box when
+show-debug or show-devel when de-selected (bcn#632377)
+- fixed potential crash when file picking file of esoteric
+filename (bnc#633173)
+- window size too small when using big fonts: correlate
+window size to font size (bnc#633498)
+
+-------------------------------------------------------------------
+Mon Jul 26 19:28:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.69
+- sw_single: fix file > import / export menu items (bcn#624310)
+
+-------------------------------------------------------------------
+Wed Jul 14 13:39:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.68
+- sw_single: fixed duplicate separator item in context menu.
+
+-------------------------------------------------------------------
+Wed Jul 14 11:41:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.67
+- build for bnc#620513 patch.
+
+-------------------------------------------------------------------
+Tue Jul 13 16:04:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.66
+- adjust window size to cope with big fonts.
+
+-------------------------------------------------------------------
+Mon Jul 12 15:32:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.65
+- more comsmetic fixes related to bnc#620513.
+
+-------------------------------------------------------------------
+Sat Jul 10 21:56:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.64
+- comsmetic fixes related to bnc#620513.
+
+-------------------------------------------------------------------
+Sat Jul 10 18:42:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.63
+- typo correction.
+
+-------------------------------------------------------------------
+Sat Jul 10 18:32:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.62
+- fix sw_single post-procedure scrolling glitch.
+
+-------------------------------------------------------------------
+Sat Jul 10 13:49:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.61
+- dependencies box sometimes freezes when open (bnc#620513).
+
+-------------------------------------------------------------------
+Wed Jul 06 20:10:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.60
+- versions box not visible enough: swap position with
+details box (bnc#620513).
+
+-------------------------------------------------------------------
+Tue Jul 05 18:32:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.59
+- ommit online-update configuration menu item when
+not running online-update (bnc#609778s)
+
+-------------------------------------------------------------------
+Fri Jul 02 13:25:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.58
+- sw_single window too big for some screens (bnc#618951)
+
+-------------------------------------------------------------------
+Fri Jun 26 15:37:00 WET 2010 - badshah400@gmail.com
+
+- 2.21.57
+- don't steal window focus (bnc#615927)
+
+-------------------------------------------------------------------
+Sun Jun 13 10:28:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.56
+- don't reset zypp options.
+- omit options menu for online update.
+
+-------------------------------------------------------------------
+Fri Jun 11 17:45:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.55
+- qt plugin gap: "cleanup deps" and "allow vendor" flags
+missing.
+
+-------------------------------------------------------------------
+Tue Jun 8 17:35:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.54
+- honor run solver dialog's cancel button, on switch repository.
+
+-------------------------------------------------------------------
+Tue Jun 8 17:12:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.53
+- internationalization of some files broken (bnc#610313)
+- solver not automatically run on repository switch and
+on a couple of the menus, when dependencies check enabled.
+
+-------------------------------------------------------------------
+Sun Apr 25 11:15:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.52
+- sw_single: undo window: show 'inconsistent' when
+env variable PKGMGR_ACTION_AT_EXIT==summary.
+
+-------------------------------------------------------------------
+Sun Apr 25 10:48:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.51
+- sw_single: upgrades: don't lose patch information after
+package is set for upgrade.
+
+-------------------------------------------------------------------
+Fri Apr 23 23:15:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.50
+- sw_single: history window: fixed potential crash.
+
+-------------------------------------------------------------------
+Fri Apr 23 20:16:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.49
+- sw_single: history window fix: show downgrades and
+re-installs as such, not upgrades.
+- sw_single list: show patch mark next to version number,
+not name.
+
+-------------------------------------------------------------------
+Fri Apr 23 12:16:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.48
+- sw_single: added patch mark for upgrades.
+
+-------------------------------------------------------------------
+Fri Apr 23 08:59:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.47
+- sw_single: bug fix: patches were being (redundantly)
+marked as "auto" in the history window.
+
+-------------------------------------------------------------------
+Thu Apr 22 15:52:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.46
+- sw_single: bug fix: ups: broke the is-installed flag
+for patterns in the previous version.
+- sw_single (main list and history dialog): bug fix: on
+arabic, tooltips were showing in the wrong columns.
+- sw_single: don't show patterns view when none is available.
+
+-------------------------------------------------------------------
+Wed Apr 21 13:09:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.45
+- online_update: several fixes, that encompassthe list and the
+version widgets.
+
+-------------------------------------------------------------------
+Tue Apr 20 15:53:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.44
+- sw_single: fixed visually disconsonant sub-lines between
+the package lists and the repository/pattern ones.
+
+-------------------------------------------------------------------
+Tue Apr 20 14:02:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.43
+- online_update: several fixes, especially in the versions
+lists.
+- sw_single: bug fix: history window wouldn't function
+when closing by pressing Escape.
+- sw_single: bug fix: upgrade button wouldn't show up.
+- sw_single: show summary lines in gray.
+
+-------------------------------------------------------------------
+Mon Apr 19 14:39:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.42
+- wizard & sw_single: several bug fixes for users of
+esoteric color schemes.
+
+-------------------------------------------------------------------
+Mon Apr 19 11:51:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.41
+- sw_single: fix patterns filter padding on the headers.
+
+-------------------------------------------------------------------
+Mon Apr 19 11:32:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.40
+- sw_single: fix glitches while loading the sidebar count
+numbers.
+
+-------------------------------------------------------------------
+Sun Apr 18 17:26:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.39
+- sw_single: bug fix: upgrade button should not be selected
+when the button presses anywhere in the column it is in.
+
+-------------------------------------------------------------------
+Thu Apr 15 14:23:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.38
+- sw_single: arabic fixes on the detail box.
+- table: using gtk stock image renderer.
+
+-------------------------------------------------------------------
+Wed Apr 14 12:32:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.37
+- sw_single: added visual feedback that history dialog may
+take a bit to load, and cached it for repetitive use.
+
+-------------------------------------------------------------------
+Sun Apr 11 14:42:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.36
+- sw_single: some polishing to the history dialog.
+
+-------------------------------------------------------------------
+Sun Apr 11 13:55:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.35
+- sw_single: added go-to as a context-menu entry to the
+history dialog.
+
+-------------------------------------------------------------------
+Sun Apr 11 12:39:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.34
+- sw_single: fixed crash on history dialog when parsing some
+logs.
+- selection-box, multi-box and tree widgets: fixed crash on
+right-click.
+
+-------------------------------------------------------------------
+Sat Apr 10 16:29:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.33
+- sw_single: several improvements to the "history of changes"
+window.
+- over-load GTK Arabic treatment for lists and trees (bnc#594840)
+
+-------------------------------------------------------------------
+Fri Apr 02 23:23:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.32
+- sw_single: bug fix: find entry didn't show clear icon when
+requires or provides links were clicked.
+- button icons: map icons for untranslated terms.
+
+-------------------------------------------------------------------
+Thu Apr 01 04:42:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.31
+- sw_single: added history of changes dialog.
+- sw_single: align side-bar count number to the right.
+
+-------------------------------------------------------------------
+Thu Mar 25 18:54:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.30
+- sw_single: speed up query a little bit.
+- sw_single: show busy cursor when modifying some list item.
+- sw_single: disable Lock context-menu item when package is being
+installed or remove, in which case it won't have an effect.
+And replaced I/U/R by Undo when package changed.
+
+-------------------------------------------------------------------
+Thu Mar 25 05:22:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.29
+- sw_single: bug fix2: highlight could (still) get mangled
+when searching for more than one keyword, when the 2nd was part
+of a tag.
+
+-------------------------------------------------------------------
+Thu Mar 25 01:05:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.28
+- sw_single: bug fix: various glitches when searching for
+certain small sub-strings.
+- sw_single: speed fix: pin-down the cause of the overall
+slowness of a query update.
+
+-------------------------------------------------------------------
+Wed Mar 24 15:56:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.27
+- sw_single: improved yielding of our refresh pseudo-thread.
+
+-------------------------------------------------------------------
+Sun Mar 21 15:26:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.26
+- fixed crash when clicking on the search patterns tooltip.
+
+-------------------------------------------------------------------
+Sun Mar 21 14:54:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.25
+- repo view: added undo button.
+- bug fix: repositories count was broken, as was the 'none' entry.
+- wizard look: set buttons spacing.
+
+-------------------------------------------------------------------
+Sun Mar 21 13:06:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.24
+- changed pkg-manager refresh strategy: it should feel faster.
+
+-------------------------------------------------------------------
+Thu Mar 18 18:37:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.23
+- fixed potential crash.
+
+-------------------------------------------------------------------
+Thu Mar 18 18:27:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.22
+- look fix: enlarge wizard and dialog buttons to reflect settings
+from GtkButtonBox.
+- look fix: use yellow color for search entry when changed like
+Rhythmbox and other gnome apps.
+
+-------------------------------------------------------------------
+Tue Mar 16 14:51:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.21
+- wrong installed number in pattern list (bnc#588561)
+
+-------------------------------------------------------------------
+Thu Mar 11 01:53:45 CET 2010 - ro@suse.de
+
+- added rpmlintrc as source in the specfile
+
+-------------------------------------------------------------------
+Wed Mar 10 18:16:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.20
+- changed undo line and dialog as response to feedback
+by Atri Bhattacharya.
+- undo line fix: truncate text when there is not enough
+room.
+
+-------------------------------------------------------------------
+Wed Mar 05 00:54:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.19
+- software manager fixes:
+- ensured description view visible by default in small
+displays.
+- fixed crash on search with trailing whitespace.
+- show better status-bar string for initial packages set
+for install after installing a new system.
+
+-------------------------------------------------------------------
+Wed Mar 04 00:09:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.18
+- online_update enhancements.
+
+-------------------------------------------------------------------
+Wed Mar 03 17:17:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.17
+- fixed strings untranslated (bnc#582148)
+
+-------------------------------------------------------------------
+Fri Feb 25 16:45:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.16
+- several small icon fixes (bnc#582536), (bnc#582560),
+(bnc#582533).
+
+-------------------------------------------------------------------
+Fri Feb 24 17:14:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.15
+- change fallback icon for the expert button to Edit (bnc#581800).
+
+-------------------------------------------------------------------
+Fri Feb 24 16:52:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.14
+- GTK maps some icons wrongly (bnc#581800).
+
+-------------------------------------------------------------------
+Fri Feb 24 14:37:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.13
+- software manager bug fix: fixed the dependencies
+links to search only for the package name.
+
+-------------------------------------------------------------------
+Fri Feb 23 16:03:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.12
+- html renderer: <li> element and headers ending with colon were
+not being given right-to-left treatment for languages like Arabic
+(bnc#581800).
+
+-------------------------------------------------------------------
+Fri Feb 22 17:02:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.11
+- extend previous fix to groups of packages.
+
+-------------------------------------------------------------------
+Fri Feb 22 16:26:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.10
+- revert user change when he clicks Cancel on the dependency
+solver.
+
+-------------------------------------------------------------------
+Fri Feb 21 19:00:00 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.1 - 2.21.9
+- build attempts.
+
+-------------------------------------------------------------------
+Fri Feb 19 16:51:03 WET 2010 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.21.0
+- Many UI fixes and improvements to the software manager and
+online update.
+- software manager code now resides in its own library, linked
+only when needed.
+- several bug fixes.
+
+-------------------------------------------------------------------
+Tue Oct 27 05:23:28 UTC 2009 - coolo@novell.com
+
+- cherry pick gcc 4.4 issues
+
+-------------------------------------------------------------------
+Fri Oct 21 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.20.1 - 2.20.5
+- build attempts.
+
+-------------------------------------------------------------------
+Fri Oct 21 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.20.0
+- revert to 11.1 code (bcn#547075).
+
+-------------------------------------------------------------------
+Fri Oct 16 15:44:01 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.17
+- fixes crash on online_update (on applies-to property).
+
+-------------------------------------------------------------------
+Fri Oct 16 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.16
+- improved speed up fix: only query libzypp when
+respective expander is open.
+- bug fix: don't over-suffix "B" to size strings.
+- popup confirm dialog, rather than having the user to
+double-click apply button.
+- don't disable installed tab on repositories view.
+- disable version action button if the action is already
+undertaken.
+
+-------------------------------------------------------------------
+Fri Oct 02 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.15
+- another try.
+
+-------------------------------------------------------------------
+Fri Oct 02 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.14
+- trigger rebuild.
+
+-------------------------------------------------------------------
+Fri Oct 01 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.13
+- bug fix: failing to map packages to a couple of categories.
+- speed fix: improved startup speed.
+
+-------------------------------------------------------------------
+Thu Sep 30 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.11
+- bug fix: package details box now respond to scroll keys.
+
+-------------------------------------------------------------------
+Thu Sep 24 00:00:00 GMT 2009 - rpmcruz@alunos.dcc.fc.up.pt
+
+- 2.19.10
+- package manager got a face re-lift
+- fire the browser as the session's user (bcn#523694).
+- table selection ignored for a few seconds (bnc#513085).
+- complement our label mapping strategy with an array
+of translatable yast2 labels (bnc#446524)
+- always use black color on the text against the white
+background regardless style (bnc#471059).
+- don't show lock&remove options for patterns (bnc#489016).
+
+-------------------------------------------------------------------
+Thu Jun 4 15:23:35 CEST 2009 - mkudlvasr@novell.com
+
+- teared away PackageSelector. It now resides in a separate plugin
+ package yast2-gtk-pkg
+
+-------------------------------------------------------------------
+Thu Jun 4 11:52:25 CEST 2009 - coolo@novell.com
+
+- adapt to new libzypp
+- 2.18.1
+
+-------------------------------------------------------------------
+Mon Apr 27 11:28:40 CEST 2009 - coolo@suse.de
+
+- fix compilation with gcc 4.4
+- 2.18.0
+
+-------------------------------------------------------------------
+Wed Jan 07 12:20:00 CET 2009 - michael.meeks@novell.com
+
+ * label / tick spacing in wizard #449320#
+ * table multi-select fix #460746#
+ * layout / alignment fix #460728#
+ * another Arabic fixes #449627#, #449600#
+ * fixed issue with small displays #442052#
+ * fixed labeling and button icon problems. #449740#, #446524#
+ * fix window / titling issues #449385#, #449194#
+ * package selector fixes #457563#, #448309#, #459313#
+ * misc. other fixes #443214#, #446352#, #445950#
+
+-------------------------------------------------------------------
+Wed Dec 01 10:25:17 CET 2008 - coolo@suse.de
+
+ * fixes to cope with Arabic and other languages of
+ a right-to-left writing style.
+ * 2.17.8
+
+-------------------------------------------------------------------
+Wed Nov 21 10:25:17 CET 2008 - coolo@suse.de
+
+ * fixed online update (bnc#446352)
+ * fixed patterns order.
+ * 2.17.7
+
+-------------------------------------------------------------------
+Wed Nov 19 10:25:17 CET 2008 - coolo@suse.de
+
+- new version on behalf of Ricardo: 2.17.6
+ * a couple of esoteric yet nasty bugs (read:
+ crashes) have since been fixed.
+ (bnc#442052 & bnc#445158)
+
+-------------------------------------------------------------------
+Sun Nov 9 09:35:05 CET 2008 - coolo@suse.de
+
+- Update to 2.17.5
+ * several fixes in the wizard and package selector
+- fix spec file to build
+
+-------------------------------------------------------------------
+Wed Oct 29 10:54:07 CEST 2008 - michael.meeks@novell.com
+
+- Update to 2.17.4
+ * sizing fixes to wizard, partition splitter, ratiobox
+ * improved tooltips
+ * package selector fixes: updated zypper API use,
+ add unsupported support, updated recent spin box, png
+ icons, ergonomic fixes, sync groups with qt, support
+ non-edit mode
+ * bar graph color fixes
+ * help / history
+ * selectable multi-line labels
+ * fixes to scrolling widgets
+
+-------------------------------------------------------------------
+Mon Oct 13 10:21:07 CEST 2008 - michael.meeks@novell.com
+
+- Update to 2.17.3
+ * fix up unit tests
+ * fix strechability & sizing
+
+-------------------------------------------------------------------
+Wed Oct 08 13:56:07 CEST 2008 - michael.meeks@novell.com
+
+- Update to 2.17.2
+ * tons of bug fixes: 428974, 432705, 428965, 428965,
+ 428193, 428162, 388172 including:
+ * improved accessibility support: dialog roles, wizard overview
+ * improved tooltip support, and new tooltips
+ * use WebKit for better html rendering
+ * fix g_log redirection crasher
+ * support background image with html
+ * use gtk+ stock icons for stock dialogs
+
+-------------------------------------------------------------------
+Tue Sep 30 13:56:07 CEST 2008 - kmachalkova@suse.cz
+
+- Update to 2.17.1
+ * YGDialog: support for setDialogTitle().
+ * ygtkfindentry: added support embed context menu which pairs the find icon to
+ the menu item.
+ * YGPackageSelector: changed find entry check-based menu popup to
+ a criteria choice one.
+ * ygtkfindentry: added auto-completion support.
+ * makes progress bar a bit smoother.
+ * show download size in the progress bar.
+ * bnc #421794: clean any emitted event when destroyed. The new
+ libyui crashes when doing YWidget::isValid()
+ * YGText: set MultiLineEdit wrap mode as WORD_CHAR.
+ * YGDialog: only enable spy code for recent libyuis.
+ * YGTable: expand tree's row when selected
+ * YGPushButton: only enable role code for recent libyuis.
+ Also moved helpButton support to set icon code.
+ * added support for YDialog::highlight()
+ * coupled dumpGtk and dumpYast trees into the same dialog
+ * YGPackageSelector: fixed context menu for objects like Language
+ that can't be locked.
+ * YGUtils: added fallback to setStockIcon().
+ * YGPushButton: use Role as a fallback to derive the stock icon.
+ * YGWizard: made the wizard button wrappers to change the button
+ label & etc through the YGtkWizard API
+
+-------------------------------------------------------------------
+Thu Sep 11 08:35:23 CEST 2008 - jsrain@suse.cz
+
+- merged texts from proofread
+
+-------------------------------------------------------------------
+Tue Sep 9 13:36:25 CEST 2008 - visnov@suse.cz
+
+- Update to 2.17.0
+* added support for Languages in package selector
+* fixed Pattern installed status.
+* got rid of patterns remove button.
+* clear search entry on UI change.
+* bug fix: not syncing icon properly when entry text was deleted by
+ instruction as an insert is triggered.
+* redirect GTK log messages to libyui system.
+* enable html parsing warnings that go to libyui.
+* fixed repositories query (related to bnc #418781).
+* scaping the URL as some characters (like &) were confusing the Pango parser.
+ Use the FILE stock icon for the ISO.
+
+-------------------------------------------------------------------
+Mon Sep 8 22:32:59 EDT 2008 - jpr@novell.com
+
+- Update to 2.16.18
+* use "Software Manager" instead of "Package Selector" for
+ consistency (bnc #418781)
+* follow GNOME HIG for button layout
+* when filtering a repository, the most appropriate version wasn't
+ the one selected (bnc #418896)
+* catch null package repo (bnc #418781)
+* use title capitalization for group names (bnc #418676)
+* add ATK hooks so the screen reader does its job in pixbuf cell
+ renderer (bnc #416554)
+* show bugzilla entries in patch description
+* ygtkrichtext glitches (bnc #396692, bnc #404817)
+* fix occasional crash in printer tool
+* show arch for Version and url for Repository
+* new widgets: handlebox, linklabel
+* tabs can now have shortcuts: honor them (bnc #411890)
+
+-------------------------------------------------------------------
+Mon Jul 21 20:36:09 EDT 2008 - jpr@novell.com
+
+- Update to 2.16.17
+* extra whitespace typo in a string (bnc#383897)
+* honor flag for last column (bnc#410341)
+* let the wrapper do an initial check on changes (bnc#400635)
+* implement YTable's multiSelection flag
+* implement shortcutChanged() to set tab labels shortcuts
+* implement setHelpButton() set the help stock icon
+* remove the space for the expanders if the side navegation bar
+ is a plain list, as is the case for the firewall tool
+* tweaked some icons as suggested (bnc#404818)
+* don't always iuse the label "upgrade" if re-installs or
+ downgrades (bnc#404382)
+* keyboard mnemonics for install/remove buttons (bnc#399256)
+* consider a pattern or a patch installed or not using
+ isSatisfied() like yast2-qt. Also made initial patterns loading
+ faster. And removed some checks on patches that were causing them
+ not to be displayed (bnc#402855)
+* added a background for <pre>.
+
+-------------------------------------------------------------------
+Sun Jun 22 18:34:15 CEST 2008 - jpr@suse.de
+
+- Update to 2.16.16
+* fixed bnc#402316: run the dependency solver at the startup.
+* fixed bnc#402262: fix textdomain error when packaging.
+* fixed bnc#401767: popup menu install entry was using the remove
+ icon, while the remove entry was using the
+ install icon.
+
+-------------------------------------------------------------------
+Fri Jun 20 18:34:15 CEST 2008 - jpr@suse.de
+
+- Update to 2.16.15
+* fixed bnc#401336: unable to resize column in sysconfig editor
+* fixed bnc#386410: label widgets are set uppercase.
+* fixed bnc#401835: if radio buttons weren't set in a radio group,
+ then they'd crash when clicked
+* fixed bnc#401228: "Children widgets aren't disabled in gtk ui
+* fixed bnc#401285: HSpacing broken in gtk ui
+* fixed bnc#399465: for some package show empty software
+ dependence window
+* fixed bnc#396692: glitches with breaklines and spaces around
+ inline tag: for some package show empty
+ software dependence window
+
+-------------------------------------------------------------------
+Sun Jun 8 10:34:15 CEST 2008 - coolo@suse.de
+
+- Update to 2.16.14
+* fixed bnc#395484: Wrong check that assumed error was set, crashing...
+* fixed bnc#396731: popup menu from the button up when near the bottom corner.
+* fixed bnc#396360: ignoring the alignment for the last column, so it aligns left
+* fixed bnc#396033: Some minor bug
+* fixed bnc#393143: cursor ownership was not judged properly
+* fixed bnc#398272: enable scroll bar on Filtered Repositories
+
+-------------------------------------------------------------------
+Tue Jun 3 07:46:59 CEST 2008 - coolo@suse.de
+
+- Update to version 2.16.13
+* tag more missing strings for translation (bnc#395803)
+* fixed bnc#395484
+* various fixes in the package selector by Ricardo
+
+-------------------------------------------------------------------
+Mon May 19 11:05:00 BST 2008 - mmichael@suse.de
+
+- Update to version 2.16.12
+* make PackageSelector more usable bnc #390471
+* impl. mnemonics on frames bnc #390244
+* fix window transience (hidden popups) bnc #389635
+* add recommended/selected to categories
+* tag main package-selector buttons for translation
+* calm progress bar warnings (for stupid values eg. -5%)
+
+-------------------------------------------------------------------
+Wed May 14 12:17:00 BST 2008 - mmichael@suse.de
+
+- Update to version 2.16.11
+* fix various 640x480 sizing problems
+* fix window-larger-than-screen issue bnc #373159
+* fix size allocation issue bnc #390031
+
+-------------------------------------------------------------------
+Mon May 12 13:50:49 CEST 2008 - mmichael@suse.de
+
+- Update to version 2.16.10
+* fix i18n issues
+* remove size cropping bnc #388715
+* fix focus issue bnc #388718
+* repo filter fix bnc #386536
+
+-------------------------------------------------------------------
+Mon May 7 20:13:49 CEST 2008 - jpr@suse.de
+
+- Update to version 2.16.9
+* only set 'fullscreen' on the main bnc #385563
+* property OpenItems of Tree widget broken bnc #381648
+* CurrentItem in Tree widget also grabs keyboard focus bnc #387114
+* allow for smaller windows bnc #381689, partly bnc #373159
+* Query items of DumbTab broken bnc #381195
+* support all radio buttons being disabled bnc #373160
+* property SelectedItems for widget MultiSelectionBox broken
+ bnc #381746
+* debug message on abort User and Group Administration bnc #384135)
+* scroll YLog text down properly
+* finish button not highlighted bnc #384649
+* fix patterns installstate, and added popup with info about them
+ like -qt.
+* added highlighting for exact package matches
+* add support for repoMgrEnabled bnc #381956
+
+-------------------------------------------------------------------
+Mon Apr 21 20:13:49 CEST 2008 - jpr@suse.de
+
+- Fix live installer sizing (bnc #381153)
+- Combo box improvements
+- Minor warning fixes
+
+-------------------------------------------------------------------
+Thu Apr 3 23:04:05 CEST 2008 - coolo@suse.de
+
+- adopt to latest libzypp
+
+-------------------------------------------------------------------
+Tue Mar 28 21:28:56 CET 2008 - jpr@suse.de
+
+- don't hide package info/control view once shown (bnc #373474)
+
+-------------------------------------------------------------------
+Tue Mar 25 21:28:56 CET 2008 - coolo@suse.de
+
+- update from SVN to compile with latest libzypp
+
+-------------------------------------------------------------------
+Thu Feb 28 13:54:27 CET 2008 - coolo@suse.de
+
+- fix make dist
+
+-------------------------------------------------------------------
+Wed Feb 27 16:37:02 CET 2008 - coolo@suse.de
+
+- make it link again
+
+-------------------------------------------------------------------
+Mon Feb 25 16:24:12 CET 2008 - sh@suse.de
+
+- V 2.16.5
+- Added "Provides: yast2_ui_pkg" to .spec file (bnc #363958)
+
+-------------------------------------------------------------------
+Thu Feb 21 12:22:22 CET 2008 - coolo@suse.de
+
+- fix build
+
+-------------------------------------------------------------------
+Thu Feb 21 07:29:11 CET 2008 - coolo@suse.de
+
+- compile against yast2-core and libzypp
+- V 2.16.4
+
+-------------------------------------------------------------------
+Mon Feb 4 20:19:03 CET 2008 - coolo@suse.de
+
+- adapt once more to latest yast2-core
+
+-------------------------------------------------------------------
+Thu Jan 31 20:11:40 CET 2008 - coolo@suse.de
+
+- make it compile against latest yast2-core
+
+-------------------------------------------------------------------
+Sun Jan 27 21:03:57 CET 2008 - coolo@suse.de
+
+- fix changelog
+
+-------------------------------------------------------------------
+Fri Jan 18 14:08:57 CET 2008 - coolo@suse.de
+
+- Ricardo fixed make test
+
+-------------------------------------------------------------------
+Wed Jan 16 14:42:56 CET 2008 - coolo@suse.de
+
+- update to latest yast2-core API
+
+-------------------------------------------------------------------
+Fri Jan 11 23:36:13 CET 2008 - btimothy@suse.de
+
+- Updating the tarball directly from SVN Trunk revision to be
+ version 2.15.9r43566 so the package won't fail to build anymore.
+- Removed all the old patches since they are no longer necessary
+ with newer code.
+
+-------------------------------------------------------------------
+Wed Oct 24 19:21:59 CEST 2007 - btimothy@suse.de
+
+- Include patches from SVN head to fix various package selector
+ bugs. Included are fixes for bugzilla.novell.com bugs: 300390
+ 300750, 300737, 330235, 330467, 336124.
+
+-------------------------------------------------------------------
+Wed Oct 6 15:32:01 BST 2007 - mmichael@suse.de
+
+- n#300750: big speedup wrt. search / sort
+
+-------------------------------------------------------------------
+Wed Sep 26 01:29:22 CEST 2007 - sreeves@suse.de
+
+- Partial fix for Bug# 328213 - package selector untranslated
+
+-------------------------------------------------------------------
+Wed Aug 26 15:32:01 BST 2007 - mmichael@suse.de
+
+- n#300390: warn if cancelling a non-submitted transaction.
+
+-------------------------------------------------------------------
+Fri Aug 10 18:01:20 CEST 2007 - mvidner@suse.cz
+
+- Finished integrating Feature #120292, UI as a namespace callable
+ from yast2-*-bindings.
+- 2.5.9
+
+-------------------------------------------------------------------
+Wed Aug 8 15:32:01 BST 2007 - mmichael@suse.de
+
+- #296945: pulse progress bar impl.
+- FaTE #302018: details on how to print the license
+- 2.15.8
+
+-------------------------------------------------------------------
+Wed Aug 8 09:22:32 CEST 2007 - mvidner@suse.cz
+
+- Don't build-require yast2-devel-doc.
+- 2.15.7.2
+
+-------------------------------------------------------------------
+Mon Aug 6 14:00:37 CEST 2007 - mvidner@suse.cz
+
+- Adapted to changes in yast2-core needed for making UI callable from
+ yast2-*-bindings.
+- 2.15.7.1
+
+-------------------------------------------------------------------
+Thu Jul 26 07:28:31 CEST 2007 - jsrain@suse.cz
+
+- removed yast2-devel from BuildRequires
+- 2.15.7
+
+-------------------------------------------------------------------
+Mon Jul 23 15:32:01 BST 2007 - mmichael@suse.de
+
+- fix crash-on-start n#293065
+- fix uninitialized warnings
+- fix empty-partition divide by 0 case
+- 2.15.6
+
+-------------------------------------------------------------------
+Mon Jul 16 17:07:01 CEST 2007 - jsrain@suse.cz
+
+- adapted to new libzypp
+- added support for translations
+- 2.15.5
+
+-------------------------------------------------------------------
+Thu Jun 21 10:24:55 CEST 2007 - mmichael@suse.de
+
+- upgrade to yast2-gtk-2.15.4, fixes many bugs, pwrt.
+ package selector, improved search, multi-select for
+ installations &, large scale robustness & functionality
+ table-sorting fix, progress bar fix, initial easter-egg,
+ add rpmlintrc to avoid complaints about plugin .so name
+
+-------------------------------------------------------------------
+Fri May 11 18:19:10 CEST 2007 - mmichael@suse.de
+
+- upgrade to yast2-gtk-2.15.3, fixes #268146, #271716
+ and improves package selector search / sort.
+
+-------------------------------------------------------------------
+Tue Apr 17 15:58:40 CEST 2007 - mmichael@suse.de
+
+- upgrade to yast2-gtk-2.15.2, fixes upgrade.ycp
+
+-------------------------------------------------------------------
+Fri Mar 16 13:36:04 CET 2007 - mmichael@suse.de
+
+- upgrade to yast2-gtk-2.15.1, several fixes, including #247682, #247683
+
+-------------------------------------------------------------------
+Wed Feb 7 11:26:07 CET 2007 - mmichael@suse.de
+
+- update to yast2-gtk-2.15.0, fixes build and adds new Frame type
+
+-------------------------------------------------------------------
+Wed Aug 30 10:56:28 CEST 2006 - cthiel@suse.de
+
+- added yast2-gtk-autogen.patch to fix build with latests yast2-devtools
+
+-------------------------------------------------------------------
+Mon Aug 28 11:34:13 CEST 2006 - cthiel@suse.de
+
+- fix build
+
+-------------------------------------------------------------------
+Wed Aug 23 18:20:30 CEST 2006 - mmichael@suse.de
+
+- import yast2-gtk into autobuild.
+
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/CMakeLists.txt
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/CMakeLists.txt?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/CMakeLists.txt (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/CMakeLists.txt Mon Aug 1 09:44:45 2011
@@ -0,0 +1,74 @@
+## Makefile.am
+
+set (gtk_yast_plugin_SRCS
+ YGBarGraph.cc
+ YGComboBox.cc
+ YGDialog.cc
+ YGDumbTab.cc
+ YGFrame.cc
+ YGInputField.cc
+ YGIntField.cc
+ YGImage.cc
+ YGMenuButton.cc
+ YGLabel.cc
+ YGLayout.cc
+ YGPackageSelectorPluginStub.cc
+ YGPushButton.cc
+ YGProgressBar.cc
+ YGRadioButton.cc
+ YGSelectionStore.cc
+ YGText.cc
+ YGTreeView.cc
+ YGUtils.cc
+ YGUI.cc
+ YGWidget.cc
+ YGWizard.cc
+ ygdkmngloader.c
+ ygtkbargraph.c
+ ygtkfieldentry.c
+ ygtkhtmlwrap.c
+ ygtkmenubutton.c
+ ygtklinklabel.c
+ ygtkfixed.c
+ ygtkimage.c
+ ygtkratiobox.c
+ ygtkrichtext.c
+ ygtksteps.c
+ ygtktextview.c
+ ygtktimezonepicker.c
+ ygtktreeview.c
+ ygtkwizard.c
+ )
+
+## includes:
+
+include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+include_directories (${GTK2_INCLUDE_DIRS})
+include_directories (${LIBYUI_INCLUDE_DIR})
+
+## target:
+
+add_library (py2gtk SHARED ${gtk_yast_plugin_SRCS})
+
+## libraries:
+
+target_link_libraries (py2gtk ${GTK2_LIBRARIES})
+target_link_libraries (py2gtk ${LIBYUI_LIBRARY})
+set_target_properties (py2gtk PROPERTIES SOVERSION 2)
+set_target_properties (py2gtk PROPERTIES LINK_FLAGS "--no-undefined")
+
+## install:
+
+install (TARGETS py2gtk LIBRARY DESTINATION ${UI_PLUGIN_DIR})
+
+add_subdirectory (pkg)
+
+## test:
+
+link_directories (${CMAKE_BINARY_DIR}/src)
+add_executable (test test.cc)
+add_dependencies (test py2gtk)
+target_link_libraries (test libpy2gtk.so)
+target_link_libraries (test ${GTK2_LIBRARIES})
+target_link_libraries (test ${LIBYUI_LIBRARY})
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/Y2CCGtk.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/Y2CCGtk.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/Y2CCGtk.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/Y2CCGtk.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,20 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include
+#include
+#include
+
+YUI * createUI( bool withThreads )
+{
+ static YGUI *_ui = 0;
+
+ if ( ! _ui )
+ {
+ _ui = new YGUI( withThreads );
+ }
+
+ return _ui;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGBarGraph.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGBarGraph.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGBarGraph.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGBarGraph.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,172 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "ygtkbargraph.h"
+
+#include "YBarGraph.h"
+
+class YGBarGraph : public YBarGraph, public YGWidget
+{
+public:
+ YGBarGraph (YWidget *parent)
+ : YBarGraph (NULL)
+ , YGWidget (this, parent, YGTK_TYPE_BAR_GRAPH, NULL)
+ {}
+
+ // YBarGraph
+ virtual void doUpdate()
+ {
+ YGtkBarGraph *graph = YGTK_BAR_GRAPH (getWidget());
+ ygtk_bar_graph_create_entries (graph, segments());
+ for (int i = 0; i < segments(); i++) {
+ const YBarGraphSegment &s = segment (i);
+ ygtk_bar_graph_setup_entry (graph, i, s.label().c_str(), s.value());
+ if (s.hasSegmentColor()) {
+ GdkColor color = ycolorToGdk (s.segmentColor());
+ ygtk_bar_graph_customize_bg (graph, i, &color);
+ }
+ if (s.hasTextColor()) {
+ GdkColor color = ycolorToGdk (s.textColor());
+ ygtk_bar_graph_customize_fg (graph, i, &color);
+ }
+ }
+ }
+
+ static GdkColor ycolorToGdk (const YColor &ycolor)
+ {
+ GdkColor color = { 0, guint16(ycolor.red() << 8), guint16(ycolor.green() << 8), guint16(ycolor.blue() << 8) };
+ return color;
+ }
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ { return dim == YD_HORIZ ? 80 : 30; }
+
+ YGWIDGET_IMPL_COMMON (YBarGraph)
+};
+
+YBarGraph *YGOptionalWidgetFactory::createBarGraph (YWidget *parent)
+{
+ return new YGBarGraph (parent);
+}
+
+#include "YPartitionSplitter.h"
+
+class YGPartitionSplitter : public YPartitionSplitter, public YGWidget
+{
+public:
+ YGtkBarGraph *m_barGraph;
+ GtkWidget *m_scale, *m_free_spin, *m_new_spin;
+
+ YGPartitionSplitter (YWidget *parent, int usedSize, int totalFreeSize, int newPartSize,
+ int minNewPartSize, int minFreeSize, const string &usedLabel, const string &freeLabel,
+ const string &newPartLabel, const string &freeFieldLabel, const string &newPartFieldLabel)
+ : YPartitionSplitter (NULL, usedSize, totalFreeSize, newPartSize, minNewPartSize,
+ minFreeSize, usedLabel, freeLabel, newPartLabel, freeFieldLabel, newPartFieldLabel)
+ , YGWidget (this, parent, GTK_TYPE_VBOX, NULL)
+ {
+ /* Bar graph widget */
+ GtkWidget *graph = ygtk_bar_graph_new();
+ m_barGraph = YGTK_BAR_GRAPH (graph);
+ ygtk_bar_graph_create_entries (m_barGraph, 3);
+ ygtk_bar_graph_setup_entry (m_barGraph, 0, usedLabel.c_str(), usedSize);
+
+ /* Labels over the slider */
+ GtkWidget *labels_box = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (labels_box),
+ gtk_label_new (freeFieldLabel.c_str()), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (labels_box), gtk_label_new (NULL), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (labels_box),
+ gtk_label_new (newPartFieldLabel.c_str()), FALSE, TRUE, 0);
+
+ /* Slider and the spinners */
+ GtkWidget *slider_box = gtk_hbox_new (FALSE, 0);
+ m_scale = gtk_hscale_new_with_range ((gdouble) minFreeSize, maxFreeSize(), 1);
+ gtk_scale_set_draw_value (GTK_SCALE (m_scale), FALSE);
+ m_free_spin = gtk_spin_button_new_with_range
+ (minFreeSize, maxFreeSize(), 1);
+ m_new_spin = gtk_spin_button_new_with_range
+ (minNewPartSize, maxNewPartSize(), 1);
+
+ // keep the partition's order
+ gtk_widget_set_direction (labels_box, GTK_TEXT_DIR_LTR);
+ gtk_widget_set_direction (slider_box, GTK_TEXT_DIR_LTR);
+
+ gtk_box_pack_start (GTK_BOX (slider_box), m_free_spin, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (slider_box), m_scale, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (slider_box), m_new_spin, FALSE, FALSE, 0);
+
+ connect (m_scale, "value-changed", G_CALLBACK (scale_changed_cb), this);
+ connect (m_free_spin, "value-changed", G_CALLBACK (free_spin_changed_cb), this);
+ connect (m_new_spin, "value-changed", G_CALLBACK (new_spin_changed_cb), this);
+
+ /* Main layout */
+ gtk_box_pack_start (GTK_BOX (getWidget()), graph, TRUE, TRUE, 6);
+ gtk_box_pack_start (GTK_BOX (getWidget()), labels_box, FALSE, TRUE, 2);
+ gtk_box_pack_start (GTK_BOX (getWidget()), slider_box, FALSE, TRUE, 2);
+
+ setValue (newPartSize); // initialization
+ gtk_widget_show_all (getWidget());
+ }
+
+ // YPartitionSplitter
+ virtual int value()
+ {
+ return gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (m_new_spin));
+ }
+
+ virtual void setValue (int newValue)
+ {
+ BlockEvents block (this);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_new_spin), newValue);
+ int freeSize = totalFreeSize() - newValue;
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_free_spin), freeSize);
+ gtk_range_set_value (GTK_RANGE (m_scale), freeSize);
+
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_free_spin), freeSize);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_new_spin), newValue);
+
+ ygtk_bar_graph_setup_entry (m_barGraph, 1, freeLabel().c_str(), freeSize);
+ ygtk_bar_graph_setup_entry (m_barGraph, 2, newPartLabel().c_str(), newValue);
+ }
+
+ static void scale_changed_cb (GtkRange *range, YGPartitionSplitter *pThis)
+ {
+ int newFreeSize = (int) gtk_range_get_value (range);
+ int newPartSize = pThis->totalFreeSize() - newFreeSize;
+
+ pThis->setValue (newPartSize);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void free_spin_changed_cb (GtkSpinButton *spin, YGPartitionSplitter *pThis)
+ {
+ int newFreeSize = gtk_spin_button_get_value_as_int (spin);
+ int newPartSize = pThis->totalFreeSize() - newFreeSize;
+ pThis->setValue (newPartSize);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void new_spin_changed_cb (GtkSpinButton *spin, YGPartitionSplitter *pThis)
+ {
+ pThis->setValue (gtk_spin_button_get_value_as_int (spin));
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ YGWIDGET_IMPL_COMMON (YPartitionSplitter)
+};
+
+YPartitionSplitter *YGOptionalWidgetFactory::createPartitionSplitter (YWidget *parent,
+ int usedSize, int totalFreeSize, int newPartSize, int minNewPartSize,
+ int minFreeSize, const string &usedLabel, const string &freeLabel,
+ const string &newPartLabel, const string &freeFieldLabel,
+ const string &newPartFieldLabel)
+{
+ return new YGPartitionSplitter (parent, usedSize, totalFreeSize, newPartSize,
+ minNewPartSize, minFreeSize, usedLabel, freeLabel, newPartLabel, freeFieldLabel,
+ newPartFieldLabel);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGComboBox.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGComboBox.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGComboBox.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGComboBox.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,139 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include
+#include "YGUtils.h"
+#include "YComboBox.h"
+#include "YGSelectionStore.h"
+#include "YGWidget.h"
+
+class YGComboBox : public YComboBox, public YGLabeledWidget, public YGSelectionStore
+{
+ public:
+ YGComboBox (YWidget *parent, const string &label, bool editable)
+ : YComboBox (NULL, label, editable),
+ YGLabeledWidget (this, parent, label, YD_HORIZ,
+ editable ? GTK_TYPE_COMBO_BOX_ENTRY : GTK_TYPE_COMBO_BOX, NULL),
+ YGSelectionStore (false)
+ {
+ const GType types[2] = { GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ createStore (2, types);
+ gtk_combo_box_set_model (getComboBox(), getModel());
+
+ GtkCellRenderer* cell = gtk_cell_renderer_pixbuf_new();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (getWidget()), cell, FALSE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
+ "pixbuf", 0, NULL);
+
+ if (editable)
+ gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (getWidget()), 1);
+ else {
+ cell = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (getWidget()), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
+ "text", 1, NULL);
+ }
+
+ connect (getWidget(), "changed", G_CALLBACK (selected_changed_cb), this);
+ }
+
+ inline GtkComboBox *getComboBox()
+ { return GTK_COMBO_BOX (getWidget()); }
+
+ GtkEntry *getEntry()
+ { return GTK_ENTRY (gtk_bin_get_child (GTK_BIN (getWidget()))); }
+
+ // YGSelectionModel
+
+ void blockSelected() {}
+
+ void doAddItem (YItem *item)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ setRowText (&iter, 0, item->iconName(), 1, item->label(), this);
+ if (item->selected())
+ doSelectItem (item, true);
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ {
+ if (select) {
+ BlockEvents block (this);
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ gtk_combo_box_set_active_iter (getComboBox(), &iter);
+ }
+ }
+
+ void doDeselectAllItems()
+ {
+ BlockEvents block (this);
+ gtk_combo_box_set_active (getComboBox(), -1);
+ }
+
+ YItem *doSelectedItem()
+ {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (getComboBox(), &iter))
+ return getYItem (&iter);
+ return NULL;
+ }
+
+ // YComboBox
+
+ virtual std::string text()
+ {
+ gchar *str;
+ if (GTK_IS_COMBO_BOX_ENTRY (getWidget()))
+ str = gtk_combo_box_get_active_text (getComboBox());
+ else {
+ GtkTreeIter iter;
+ if (gtk_combo_box_get_active_iter (getComboBox(), &iter))
+ gtk_tree_model_get (getModel(), &iter, 1, &str, -1);
+ else
+ return "";
+ }
+ std::string ret (str);
+ g_free (str);
+ return ret;
+ }
+
+ virtual void setText (const std::string &value)
+ {
+ BlockEvents block (this);
+ GtkTreeIter iter;
+ if (findLabel (1, value, &iter))
+ gtk_combo_box_set_active_iter (getComboBox(), &iter);
+ else
+ gtk_entry_set_text (getEntry(), value.c_str());
+ }
+
+ virtual void setInputMaxLength (int length)
+ {
+ YComboBox::setInputMaxLength (length);
+ gtk_entry_set_width_chars (getEntry(), length);
+ }
+
+ virtual void setValidChars (const string &validChars)
+ {
+ YComboBox::setValidChars (validChars);
+ YGUtils::setFilter (getEntry(), validChars);
+ }
+
+ // callbacks
+ static void selected_changed_cb (GtkComboBox *widget, YGComboBox *pThis)
+ { pThis->emitEvent (YEvent::ValueChanged); }
+
+ YGLABEL_WIDGET_IMPL (YComboBox)
+ YGSELECTION_WIDGET_IMPL (YComboBox)
+};
+
+YComboBox *YGWidgetFactory::createComboBox (YWidget *parent, const string &label, bool editable)
+{
+ return new YGComboBox (parent, label, editable);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,585 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGDialog.h"
+#include "YGUtils.h"
+#if YAST2_VERSION >= 2017006
+#include
+#endif
+#include
+#include // easter
+#include
+
+/* In the main dialog case, it doesn't necessarly have a window of its own. If
+ there is already a main window, it should replace its content -- and when closed,
+ the previous dialog restored.
+
+ Therefore, we have a YGDialog (the YDialog implementation), and a YGWindow
+ that does the windowing work and has a YWidget has its children, which can
+ be a YGDialog and is swap-able.
+*/
+
+//#define DEFAULT_WIDTH 750
+//#define DEFAULT_HEIGHT 650
+#define DEFAULT_CHAR_WIDTH 60
+#define DEFAULT_CHAR_HEIGHT 28
+#define DEFAULT_PIXEL_WIDTH 330
+#define DEFAULT_PIXEL_HEIGHT 200
+
+class YGWindow;
+static YGWindow *main_window = 0;
+
+class YGWindow
+{
+ GtkWidget *m_widget;
+ int m_refcount;
+ // we keep a pointer of the child just for debugging
+ // (ie. dump yast tree)
+ YWidget *m_child;
+ GdkCursor *m_busyCursor;
+ bool m_isBusy;
+
+public:
+ YGWindowCloseFn m_canClose;
+ void *m_canCloseData;
+
+ YGWindow (bool _main_window, YGDialog *ydialog)
+ {
+ m_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_object_ref_sink (G_OBJECT (m_widget));
+ g_object_set (G_OBJECT (m_widget), "allow-shrink", TRUE, NULL);
+
+ m_refcount = 0;
+ m_child = NULL;
+ m_canClose = NULL;
+ m_busyCursor = NULL;
+ m_isBusy = false;
+
+ {
+ std::stack &stack = YDialog::_dialogStack;
+ YDialog *ylast = stack.size() ? stack.top() : 0;
+ if (ylast == ydialog) {
+ if (stack.size() > 1) {
+ YDialog *t = ylast;
+ stack.pop();
+ ylast = stack.top();
+ stack.push (t);
+ }
+ else
+ ylast = NULL;
+ }
+
+ GtkWindow *parent = NULL;
+ if (ylast) {
+ YGDialog *yglast = static_cast (ylast);
+ parent = GTK_WINDOW (yglast->m_window->getWidget());
+ }
+ GtkWindow *window = GTK_WINDOW (m_widget);
+
+ if (parent) {
+ // if there is a parent, this would be a dialog
+ gtk_window_set_title (window, "");
+ gtk_window_set_modal (window, TRUE);
+ gtk_window_set_transient_for (window, parent);
+ gtk_window_set_type_hint (window, GDK_WINDOW_TYPE_HINT_DIALOG);
+ AtkObject *peer = gtk_widget_get_accessible (GTK_WIDGET (window));
+ if (peer != NULL)
+ atk_object_set_role (peer, ATK_ROLE_DIALOG);
+ }
+ else {
+ gtk_window_set_title (window, "YaST");
+ if (YGUI::ui()->unsetBorder())
+ gtk_window_set_decorated (window, FALSE);
+ }
+
+ if (_main_window) {
+ // window default width is calculated as a proportion of a default
+ // char and pixel width to compensate for the fact that each widget's
+ // required size comes from a proportion of both parameters
+ int width = YGUtils::getCharsWidth (m_widget, DEFAULT_CHAR_WIDTH);
+ width += DEFAULT_PIXEL_WIDTH;
+ int height = YGUtils::getCharsHeight (m_widget, DEFAULT_CHAR_HEIGHT);
+ height += DEFAULT_PIXEL_HEIGHT;
+
+ if (YGUI::ui()->isSwsingle())
+ height += YGUtils::getCharsHeight (m_widget, 10);
+
+ width = MIN (width, YUI::app()->displayWidth());
+ height = MIN (height, YUI::app()->displayHeight());
+
+ gtk_window_set_default_size (window, width, height);
+ if (YGUI::ui()->setFullscreen())
+ gtk_window_fullscreen (window);
+ else if (YUI::app()->displayWidth() <= 800 || YUI::app()->displayHeight() <= 600)
+ // maximize window for small displays
+ gtk_window_maximize (window);
+ }
+
+ gtk_window_set_role (window, "yast2");
+ }
+
+ if (_main_window)
+ main_window = this;
+
+ g_signal_connect (G_OBJECT (m_widget), "delete-event",
+ G_CALLBACK (close_window_cb), this);
+ g_signal_connect_after (G_OBJECT (m_widget), "key-press-event",
+ G_CALLBACK (key_pressed_cb), this);
+ g_signal_connect (G_OBJECT (m_widget), "focus-in-event",
+ G_CALLBACK (focus_in_event_cb), this);
+ // set busy cursor at start
+ g_signal_connect_after (G_OBJECT (m_widget), "realize",
+ G_CALLBACK (realize_cb), this);
+ }
+
+ ~YGWindow()
+ {
+ setChild (NULL);
+ if (m_busyCursor)
+ gdk_cursor_unref (m_busyCursor);
+ gtk_widget_destroy (m_widget);
+ g_object_unref (G_OBJECT (m_widget));
+ }
+
+ void show()
+ { gtk_widget_show (m_widget); }
+
+ void normalCursor()
+ {
+ if (m_isBusy)
+ gdk_window_set_cursor (m_widget->window, NULL);
+ m_isBusy = false;
+ }
+
+ void busyCursor()
+ {
+ if (!m_busyCursor) {
+ GdkDisplay *display = gtk_widget_get_display (m_widget);
+ m_busyCursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+ gdk_cursor_ref (m_busyCursor);
+ }
+ if (!m_isBusy)
+ gdk_window_set_cursor (m_widget->window, m_busyCursor);
+ m_isBusy = true;
+ }
+
+ void setChild (YWidget *new_child)
+ {
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (m_widget));
+ if (child)
+ gtk_container_remove (GTK_CONTAINER (m_widget), child);
+ if (new_child) {
+ child = YGWidget::get (new_child)->getLayout();
+ gtk_container_add (GTK_CONTAINER (m_widget), child);
+ }
+ m_child = new_child;
+ }
+
+ static void ref (YGWindow *window)
+ {
+ window->m_refcount++;
+ }
+
+ static void unref (YGWindow *window)
+ {
+ if (--window->m_refcount == 0) {
+ bool is_main_window = (window == main_window);
+ delete window;
+ if (is_main_window)
+ main_window = NULL;
+ }
+ }
+
+ // Y(G)Widget-like methods
+ GtkWidget *getWidget() { return m_widget; }
+ YWidget *getChild() { return m_child; }
+
+private:
+ void close()
+ {
+ if (!m_canClose || m_canClose (m_canCloseData))
+ YGUI::ui()->sendEvent (new YCancelEvent());
+ }
+
+ static gboolean close_window_cb (GtkWidget *widget, GdkEvent *event,
+ YGWindow *pThis)
+ {
+ // never let GTK+ destroy the window! just inform YCP, and let it
+ // do its thing.
+ pThis->close();
+ return TRUE;
+ }
+
+ static gboolean key_pressed_cb (GtkWidget *widget, GdkEventKey *event,
+ YGWindow *pThis)
+ {
+ // if not main dialog, close it on escape
+ if (event->keyval == GDK_Escape &&
+ /* not main window */ main_window != pThis) {
+ pThis->close();
+ return TRUE;
+
+ }
+
+ if (event->state & GDK_SHIFT_MASK) {
+ switch (event->keyval) {
+ case GDK_F8:
+ YGUI::ui()->askSaveLogs();
+ return TRUE;
+ default:
+ break;
+ }
+ }
+ if ((event->state & GDK_CONTROL_MASK) && (event->state & GDK_SHIFT_MASK)
+ && (event->state & GDK_MOD1_MASK)) {
+ yuiMilestone() << "Caught YaST2 magic key combination\n";
+ switch (event->keyval) {
+ case GDK_S:
+ YGUI::ui()->makeScreenShot();
+ return TRUE;
+ case GDK_M:
+ YGUI::ui()->toggleRecordMacro();
+ return TRUE;
+ case GDK_P:
+ YGUI::ui()->askPlayMacro();
+ return TRUE;
+ case GDK_D:
+ YGUI::ui()->sendEvent (new YDebugEvent());
+ return TRUE;
+ case GDK_X:
+ yuiMilestone() << "Starting xterm\n";
+ (void) system ("/usr/bin/xterm &");
+ return TRUE;
+ case GDK_H:
+ dumpYastHtml (pThis->getChild());
+ return TRUE;
+ case GDK_E: // easter egg
+ static guint explode_timeout = 0;
+ if (explode_timeout == 0)
+ explode_timeout = g_timeout_add (10000, expode_window_timeout_cb, pThis);
+ else {
+ g_source_remove (explode_timeout);
+ explode_timeout = 0;
+ }
+ return TRUE;
+ case GDK_Y:
+ yuiMilestone() << "Opening dialog spy" << endl;
+ YDialogSpy::showDialogSpy();
+ YGUI::ui()->normalCursor();
+ break;
+ default:
+ break;
+ }
+ }
+ return FALSE;
+ }
+
+ static gboolean focus_in_event_cb (GtkWidget *widget, GdkEventFocus *event)
+ { gtk_window_set_urgency_hint (GTK_WINDOW (widget), FALSE); return FALSE; }
+
+ static void realize_cb (GtkWidget *widget, YGWindow *pThis)
+ { pThis->busyCursor(); }
+
+ static gboolean expode_window_timeout_cb (gpointer data)
+ {
+ YGWindow *pThis = (YGWindow *) data;
+ GtkWindow *window = GTK_WINDOW (pThis->m_widget);
+ srand (time (NULL));
+ gint x, y;
+ gtk_window_get_position (window, &x, &y);
+ #if 0
+ // OVAL MOVE
+ for (int i = 180; i < 360+180; i++) {
+ gtk_window_move (window, x+(int)(sin((i*G_PI)/180)*50),
+ y+(int)(cos((i*G_PI)/180)*50)+50);
+ while (gtk_events_pending())
+ gtk_main_iteration();
+ usleep (25);
+ }
+ #else
+ // EXPLOSION
+ for (int i = 0; i < 40; i++) {
+ gtk_window_move (window, x+(int)((((float)(rand())/RAND_MAX)*40)-20),
+ y+(int)((((float)(rand())/RAND_MAX)*40)-20));
+ while (gtk_events_pending())
+ gtk_main_iteration();
+ usleep (200);
+ }
+ #endif
+ gtk_window_move (window, x, y);
+ return TRUE;
+ }
+};
+
+YGDialog::YGDialog (YDialogType dialogType, YDialogColorMode colorMode)
+ : YDialog (dialogType, colorMode),
+ YGWidget (this, NULL, GTK_TYPE_HBOX, NULL)
+{
+ setBorder (0);
+ m_stickyTitle = false;
+ m_containee = gtk_event_box_new();
+ if (dialogType == YMainDialog && main_window)
+ m_window = main_window;
+ else
+ m_window = new YGWindow (dialogType == YMainDialog, this);
+ YGWindow::ref (m_window);
+
+ if (colorMode != YDialogNormalColor) {
+ // emulate a warning / info dialog
+ GtkWidget *icon = gtk_image_new_from_stock
+ (colorMode == YDialogWarnColor ? GTK_STOCK_DIALOG_WARNING : GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0);
+ gtk_misc_set_padding (GTK_MISC (icon), 0, 12);
+
+ gtk_box_pack_start (GTK_BOX (getWidget()), icon, FALSE, FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_containee, TRUE, TRUE, 0);
+ }
+ else
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_containee, TRUE, TRUE, 0);
+ gtk_widget_show_all (getWidget());
+
+ // NOTE: we need to add this containter to the window right here, else
+ // weird stuff happens (like if we set a pango font description to a
+ // GtkLabel, size request would output the size without that description
+ // set...)
+ m_window->setChild (this);
+}
+
+YGDialog::~YGDialog()
+{
+ YGWindow::unref (m_window);
+}
+
+void YGDialog::openInternal()
+{
+ m_window->show();
+}
+
+void YGDialog::activate()
+{
+ m_window->setChild (this);
+}
+
+void YGDialog::present()
+{
+ GtkWindow *window = GTK_WINDOW (m_window->getWidget());
+ if (!gtk_window_is_active (window))
+ gtk_window_set_urgency_hint (window, TRUE);
+}
+
+YGDialog *YGDialog::currentDialog()
+{
+ YDialog *ydialog = YDialog::currentDialog (false);
+ if (ydialog)
+ return static_cast (ydialog);
+ return NULL;
+}
+
+GtkWindow *YGDialog::currentWindow()
+{
+ YGDialog *ydialog = YGDialog::currentDialog();
+ if (ydialog)
+ return GTK_WINDOW (ydialog->m_window->getWidget());
+ return NULL;
+}
+
+void YGDialog::setCloseCallback (YGWindowCloseFn canClose, void *canCloseData)
+{
+ m_window->m_canClose = canClose;
+ m_window->m_canCloseData = canCloseData;
+}
+
+void YGDialog::unsetCloseCallback()
+{
+ m_window->m_canClose = NULL;
+}
+
+void YGDialog::normalCursor()
+{
+ m_window->normalCursor();
+}
+
+void YGDialog::busyCursor()
+{
+ m_window->busyCursor();
+}
+
+// YWidget
+
+void YGDialog::doSetSize (int width, int height)
+{
+ // libyui calls YDialog::setSize() to force a geometry recalculation as a
+ // result of changed layout properties
+ GtkWidget *window = m_window->getWidget();
+ if (GTK_WIDGET_REALIZED (window)) {
+ gtk_widget_queue_resize (window);
+ width = MIN (width, YUI::app()->displayWidth());
+ height = MIN (height, YUI::app()->displayHeight());
+#if 1
+ bool resize = false;
+ if (isMainDialog()) {
+ if (window->allocation.width < width || window->allocation.height < height) {
+ resize = true;
+ width = MAX (width, window->allocation.width),
+ height = MAX (height, window->allocation.height);
+ }
+ }
+ else
+ resize = true;
+ if (resize)
+#else
+ if (!isMainDialog())
+#endif
+ gtk_window_resize (GTK_WINDOW (window), width, height);
+ }
+}
+
+void YGDialog::highlight (YWidget *ywidget)
+{
+ struct inner {
+ static gboolean expose_highlight_cb (GtkWidget *widget,
+ GdkEventExpose *event)
+ {
+ GtkAllocation *alloc = &widget->allocation;
+ int x = alloc->x, y = alloc->y, w = alloc->width, h = alloc->height;
+
+ cairo_t *cr = gdk_cairo_create (widget->window);
+ cairo_rectangle (cr, x, y, w, h);
+ cairo_set_source_rgb (cr, 0xff/255.0, 0x88/255.0, 0);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+ return FALSE;
+ }
+
+ static bool hasWindow (GtkWidget *widget)
+ {
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ return true;
+ // widgets like GtkButton add their windows to parent's
+ for (GList *children = gdk_window_peek_children (widget->window);
+ children; children = children->next) {
+ GdkWindow *child = (GdkWindow *) children->data;
+ gpointer data;
+ gdk_window_get_user_data (child, &data);
+ if ((GtkWidget *) data == widget)
+ return true;
+ }
+ return false;
+ }
+
+ };
+ static YWidget *previousWidget = NULL;
+ if (previousWidget && previousWidget->isValid()) {
+ YGWidget *prev = YGWidget::get (previousWidget);
+ if (prev) {
+ GtkWidget *widget = prev->getWidget();
+ if (inner::hasWindow (widget)) {
+ gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_base (widget, GTK_STATE_NORMAL, NULL);
+ }
+ else {
+ g_signal_handlers_disconnect_by_func (widget,
+ (gpointer) inner::expose_highlight_cb, NULL);
+ gtk_widget_queue_draw (widget);
+ }
+ }
+ }
+ if (ywidget) {
+ YGWidget *ygwidget = YGWidget::get (ywidget);
+ if (ygwidget) {
+ GtkWidget *widget = ygwidget->getWidget();
+ if (inner::hasWindow (widget)) {
+ GdkColor bg_color = { 0, 0xffff, 0xaaaa, 0 };
+ GdkColor base_color = { 0, 0xffff, 0xeeee, 0 };
+ gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &bg_color);
+ gtk_widget_modify_base (widget, GTK_STATE_NORMAL, &base_color);
+ }
+ else {
+ g_signal_connect (G_OBJECT (widget), "expose-event",
+ G_CALLBACK (inner::expose_highlight_cb), NULL);
+ gtk_widget_queue_draw (widget);
+ }
+ }
+ }
+ previousWidget = ywidget;
+}
+
+void YGDialog::setTitle (const std::string &title, bool sticky)
+{
+ if (title.empty())
+ return;
+ if (!m_stickyTitle || sticky) {
+ GtkWindow *window = GTK_WINDOW (m_window->getWidget());
+ gchar *str = g_strdup_printf ("%s - YaST", title.c_str());
+ gtk_window_set_title (window, str);
+ g_free (str);
+ m_stickyTitle = sticky;
+ }
+ present();
+}
+
+extern "C" {
+ void ygdialog_setTitle (const gchar *title, gboolean sticky);
+};
+
+void ygdialog_setTitle (const gchar *title, gboolean sticky)
+{
+ YGDialog::currentDialog()->setTitle (title, sticky);
+}
+
+void YGDialog::setIcon (const std::string &icon)
+{
+ GtkWindow *window = GTK_WINDOW (m_window->getWidget());
+ GdkPixbuf *pixbuf = YGUtils::loadPixbuf (icon);
+ if (pixbuf) {
+ gtk_window_set_icon (window, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+}
+
+typedef bool (*FindWidgetsCb) (YWidget *widget, void *data) ;
+
+static void findWidgets (
+ std::list *widgets, YWidget *widget, FindWidgetsCb find_cb, void *cb_data)
+{
+ if (find_cb (widget, cb_data))
+ widgets->push_back (widget);
+ for (YWidgetListConstIterator it = widget->childrenBegin();
+ it != widget->childrenEnd(); it++)
+ findWidgets (widgets, *it, find_cb, cb_data);
+}
+
+static bool IsFunctionWidget (YWidget *widget, void *data)
+{ return widget->functionKey() == GPOINTER_TO_INT (data); }
+
+YWidget *YGDialog::getFunctionWidget (int key)
+{
+ std::list widgets;
+ findWidgets (&widgets, this, IsFunctionWidget, GINT_TO_POINTER (key));
+ return widgets.empty() ? NULL : widgets.front();
+}
+
+static bool IsClassWidget (YWidget *widget, void *data)
+{ return !strcmp (widget->widgetClass(), (char *) data); }
+
+std::list YGDialog::getClassWidgets (const char *className)
+{
+ std::list widgets;
+ findWidgets (&widgets, this, IsClassWidget, (void *) className);
+ return widgets;
+}
+
+YDialog *YGWidgetFactory::createDialog (YDialogType dialogType, YDialogColorMode colorMode)
+{ return new YGDialog (dialogType, colorMode); }
+
+YEvent *YGDialog::waitForEventInternal (int timeout_millisec)
+{ return YGUI::ui()->waitInput (timeout_millisec, true); }
+
+YEvent *YGDialog::pollEventInternal()
+{ return YGUI::ui()->waitInput (0, false); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDialog.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,58 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGDIALOG_H
+#define YGDIALOG_H
+
+#include "YGWidget.h"
+#include "YDialog.h"
+
+class YGWindow;
+typedef bool (*YGWindowCloseFn) (void *closure);
+
+class YGDialog : public YDialog, public YGWidget
+{
+ friend class YGWindow;
+ GtkWidget *m_containee;
+ YGWindow *m_window;
+ bool m_stickyTitle;
+
+public:
+ YGDialog (YDialogType dialogType, YDialogColorMode colorMode);
+ virtual ~YGDialog();
+
+ virtual GtkWidget *getContainer() { return m_containee; }
+
+ void setCloseCallback (YGWindowCloseFn closeCallback, void *closeData);
+ void unsetCloseCallback();
+
+ void normalCursor();
+ void busyCursor();
+
+ // convenience function to be used rather than currentDialog()
+ static YGDialog *currentDialog();
+ static GtkWindow *currentWindow();
+
+ virtual void doSetSize (int width, int height);
+
+ virtual void openInternal();
+ virtual void activate();
+ void present();
+
+ virtual YEvent *waitForEventInternal (int timeout_millisec);
+ virtual YEvent *pollEventInternal();
+
+ virtual void highlight (YWidget * child);
+
+ void setTitle (const std::string &title, bool sticky = false);
+ void setIcon (const std::string &icon);
+
+ YWidget *getFunctionWidget (int key);
+ std::list getClassWidgets (const char *className);
+
+ YGWIDGET_IMPL_CONTAINER (YDialog)
+};
+
+#endif // YGDIALOG_H
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDumbTab.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDumbTab.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDumbTab.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGDumbTab.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,160 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "YGUtils.h"
+#include "YDumbTab.h"
+
+#include "ygtkratiobox.h"
+
+class YGDumbTab : public YDumbTab, public YGWidget
+{
+ GtkWidget *m_containee;
+ GtkWidget *m_last_tab;
+
+public:
+ YGDumbTab (YWidget *parent)
+ : YDumbTab (NULL),
+ YGWidget (this, parent, GTK_TYPE_NOTEBOOK, NULL)
+ {
+ m_containee = gtk_event_box_new();
+ g_object_ref_sink (G_OBJECT (m_containee));
+ gtk_widget_show (m_containee);
+
+ m_last_tab = 0;
+ // GTK+ keeps the notebook size set to the biggset page. We can't
+ // do this since pages are set dynamically, but at least don't let
+ // the notebook reduce its size.
+ ygtk_adj_size_set_only_expand (YGTK_ADJ_SIZE (m_adj_size), TRUE);
+
+ connect (getWidget(), "switch-page", G_CALLBACK (switch_page_cb), this);
+ }
+
+ virtual ~YGDumbTab()
+ {
+ gtk_widget_destroy (m_containee);
+ g_object_unref (G_OBJECT (m_containee));
+ }
+
+ virtual GtkWidget *getContainer()
+ { return m_containee; }
+
+ virtual void addItem (YItem *item)
+ {
+ BlockEvents block (this);
+ YDumbTab::addItem (item);
+ GtkWidget *tab_label, *image = 0, *label;
+ label = gtk_label_new (YGUtils::mapKBAccel (item->label()).c_str());
+ gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+ if (item->hasIconName()) {
+ string path = iconFullPath (item->iconName());
+ GdkPixbuf *pixbuf = YGUtils::loadPixbuf (path);
+ if (pixbuf) {
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ }
+ if (image) {
+ tab_label = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (tab_label), image, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, 0);
+ }
+ else
+ tab_label = label;
+ gchar *label_id = g_strdup_printf ("label-%d", item->index());
+ g_object_set_data (G_OBJECT (getWidget()), label_id, label);
+ g_free (label_id);
+ gtk_widget_show_all (tab_label);
+
+ GtkNotebook *notebook = GTK_NOTEBOOK (getWidget());
+
+ GtkWidget *page = gtk_event_box_new();
+ gtk_widget_show (page);
+ item->setData ((void *) page);
+ g_object_set_data (G_OBJECT (page), "yitem", item);
+
+ gtk_notebook_append_page (notebook, page, tab_label);
+ selectItem (item, item->selected() || !m_last_tab /*first tab*/);
+ }
+
+ virtual void deleteAllItems()
+ {
+ GList *children = gtk_container_get_children (GTK_CONTAINER (getWidget()));
+ for (GList *i = children; i; i = i->next)
+ gtk_container_remove (GTK_CONTAINER (getWidget()), (GtkWidget *) i->data);
+ g_list_free (children);
+ YDumbTab::deleteAllItems();
+ }
+
+ // to re-use the same widget in all tabs (m_fixed), we will remove and
+ // add to the tabs' child as tabs are changed
+ void syncTabPage()
+ {
+ if (m_last_tab)
+ gtk_container_remove (GTK_CONTAINER (m_last_tab), m_containee);
+
+ GtkNotebook *notebook = GTK_NOTEBOOK (getWidget());
+ int nb = gtk_notebook_get_current_page (notebook);
+ m_last_tab = gtk_notebook_get_nth_page (notebook, nb);
+ gtk_container_add (GTK_CONTAINER (m_last_tab), m_containee);
+ }
+
+ virtual YItem *selectedItem()
+ {
+ GtkNotebook *notebook = GTK_NOTEBOOK (getWidget());
+ int nb = gtk_notebook_get_current_page (notebook);
+ if (nb < 0) return NULL;
+ GtkWidget *child = gtk_notebook_get_nth_page (notebook, nb);
+ return (YItem *) g_object_get_data (G_OBJECT (child), "yitem");
+ }
+
+ virtual void selectItem (YItem *item, bool selected)
+ {
+ if (selected) {
+ BlockEvents block (this);
+ GtkWidget *child = (GtkWidget *) item->data();
+ int page = gtk_notebook_page_num (GTK_NOTEBOOK (getWidget()), child);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (getWidget()), page);
+ syncTabPage();
+ }
+ YDumbTab::selectItem (item, selected);
+ }
+
+ virtual void shortcutChanged()
+ {
+ for (YItemConstIterator it = itemsBegin(); it != itemsEnd(); it++) {
+ YItem *item = *it;
+ gchar *label_id = g_strdup_printf ("label-%d", item->index());
+ GtkWidget *label;
+ label = (GtkWidget *) g_object_get_data (G_OBJECT (getWidget()), label_id);
+ g_free (label_id);
+
+ std::string text = YGUtils::mapKBAccel (item->label());
+ gtk_label_set_text (GTK_LABEL (label), text.c_str());
+ gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
+ }
+ }
+
+ // callbacks
+ static void switch_page_cb (GtkNotebook *notebook, GtkNotebookPage *page,
+ guint tab_nb, YGDumbTab *pThis)
+ {
+ GtkWidget *child = gtk_notebook_get_nth_page (notebook, tab_nb);
+ YItem *item = (YItem *) g_object_get_data (G_OBJECT (child), "yitem");
+
+ pThis->YDumbTab::selectItem (item);
+ YGUI::ui()->sendEvent (new YMenuEvent (item));
+ pThis->syncTabPage();
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YDumbTab)
+};
+
+YDumbTab *YGOptionalWidgetFactory::createDumbTab (YWidget *parent)
+{ return new YGDumbTab (parent); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGFrame.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGFrame.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGFrame.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGFrame.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,182 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "YGUtils.h"
+
+// Instead of traditional looking frames, we use Gnome convention for the
+// frame's look. That is: don't draw a frame, use bold header and pad the child.
+#define CHILD_INDENTATION 8
+
+class YGBaseFrame : public YGWidget
+{
+protected:
+// a GtkAlignment to set some indentation on the child
+GtkWidget *m_containee;
+
+public:
+ YGBaseFrame (YWidget *ywidget, YWidget *parent)
+ : YGWidget (ywidget, parent,
+ GTK_TYPE_FRAME, "shadow-type", GTK_SHADOW_NONE, NULL)
+ {
+ m_containee = gtk_alignment_new (0, 0, 1, 1);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (m_containee),
+ 0, 0, CHILD_INDENTATION, 0);
+ gtk_widget_show (m_containee);
+ gtk_container_add (GTK_CONTAINER (getWidget()), m_containee);
+ }
+
+ virtual GtkWidget *getContainer()
+ { return m_containee; }
+};
+
+#include "YFrame.h"
+
+static GtkWidget *findFirstFocusable (GtkContainer *container)
+{
+ g_return_val_if_fail (container != NULL, NULL);
+
+ for (GList *l = gtk_container_get_children (container);
+ l; l = l->next) {
+ if (GTK_WIDGET_CAN_FOCUS (l->data))
+ return GTK_WIDGET (l->data);
+ else if (GTK_IS_CONTAINER (l->data)) {
+ GtkWidget *ret = findFirstFocusable (GTK_CONTAINER (l->data));
+ if (ret)
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+extern "C" {
+ static gboolean
+ frame_label_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling,
+ GtkContainer *frame_container)
+ {
+ GtkWidget *focusable = findFirstFocusable (frame_container);
+ if (focusable == NULL) {
+ g_warning ("no focusable widgets for mnemonic");
+ return FALSE;
+ } else
+ return gtk_widget_mnemonic_activate (focusable, group_cycling);
+ }
+}
+
+class YGFrame : public YFrame, public YGBaseFrame
+{
+public:
+ YGFrame (YWidget *parent, const string &label)
+ : YFrame (NULL, label),
+ YGBaseFrame (this, parent)
+ {
+ GtkWidget *label_widget = gtk_label_new_with_mnemonic ("");
+ g_signal_connect (G_OBJECT (label_widget), "mnemonic_activate",
+ G_CALLBACK (frame_label_mnemonic_activate),
+ getWidget());
+ YGUtils::setWidgetFont (GTK_WIDGET (label_widget), PANGO_STYLE_NORMAL,
+ PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM);
+ gtk_widget_show (label_widget);
+ gtk_frame_set_label_widget (GTK_FRAME (getWidget()), label_widget);
+ setLabel (label);
+ }
+
+ // YFrame
+ virtual void setLabel (const string &_str)
+ {
+ GtkWidget *label = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ string str (YGUtils::mapKBAccel (_str));
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (label), str.c_str());
+ YFrame::setLabel (_str);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YFrame)
+
+ // YGWidget
+ virtual string getDebugLabel() const
+ { return label(); }
+};
+
+
+YFrame *YGWidgetFactory::createFrame (YWidget *parent, const string &label)
+{ return new YGFrame (parent, label); }
+
+#include "YCheckBoxFrame.h"
+
+class YGCheckBoxFrame : public YCheckBoxFrame, public YGBaseFrame
+{
+public:
+ YGCheckBoxFrame (YWidget *parent, const string &label, bool checked)
+ : YCheckBoxFrame (NULL, label, checked),
+ YGBaseFrame (this, parent)
+ {
+ GtkWidget *button = gtk_check_button_new_with_mnemonic("");
+ YGUtils::setWidgetFont (gtk_bin_get_child (GTK_BIN (button)), PANGO_STYLE_NORMAL,
+ PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM);
+ gtk_widget_show_all (button);
+ gtk_frame_set_label_widget (GTK_FRAME (getWidget()), button);
+
+ setLabel (label);
+ setValue (checked);
+ connect (button, "toggled", G_CALLBACK (toggled_cb), this);
+ }
+
+ // YCheckBoxFrame
+ virtual void setLabel (const string &_str)
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ GtkLabel *label = GTK_LABEL (GTK_BIN (button)->child);
+
+ string str (YGUtils::mapKBAccel (_str));
+ gtk_label_set_text_with_mnemonic (label, str.c_str());
+ YCheckBoxFrame::setLabel (_str);
+ }
+
+ bool value()
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ }
+
+ void setValue (bool value)
+ {
+ BlockEvents (this);
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value);
+ }
+
+ // YGWidget
+ virtual void doSetEnabled (bool enabled)
+ {
+ GtkWidget *frame = getWidget();
+ if (enabled) {
+ gtk_widget_set_sensitive (frame, TRUE);
+ handleChildrenEnablement (value());
+ }
+ else {
+ gtk_widget_set_sensitive (frame, FALSE);
+ YWidget::setChildrenEnabled (false);
+ }
+ YWidget::setEnabled (enabled);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YCheckBoxFrame)
+
+private:
+ static void toggled_cb (GtkWidget *widget, YGCheckBoxFrame *pThis)
+ {
+ pThis->setEnabled (true);
+ if (pThis->notify())
+ YGUI::ui()->sendEvent (new YWidgetEvent (pThis, YEvent::ValueChanged));
+ }
+};
+
+YCheckBoxFrame *YGWidgetFactory::createCheckBoxFrame (
+ YWidget *parent, const string &label, bool checked)
+{ return new YGCheckBoxFrame (parent, label, checked); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGImage.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGImage.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGImage.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGImage.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,59 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "ygdkmngloader.h"
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "YImage.h"
+#include "ygtkimage.h"
+#include
+
+static inline bool endsWith (const std::string &str1, const char *str2)
+{
+ size_t len = strlen (str2);
+ if (str1.size() < len) return false;
+ return str1.compare (str1.size()-len, len, str2, len) == 0;
+}
+
+class YGImage : public YImage, public YGWidget
+{
+public:
+ YGImage (YWidget *parent, const string &filename, bool animated)
+ : YImage (NULL, filename, animated),
+ YGWidget (this, parent, YGTK_TYPE_IMAGE, NULL)
+ {
+ YGtkImage *image = YGTK_IMAGE (getWidget());
+ const char *stock = NULL;
+ if (endsWith (filename, "/msg_question.png"))
+ stock = GTK_STOCK_DIALOG_QUESTION;
+ else if (endsWith (filename, "/msg_info.png"))
+ stock = GTK_STOCK_DIALOG_INFO;
+ else if (endsWith (filename, "/msg_warning.png"))
+ stock = GTK_STOCK_DIALOG_WARNING;
+ else if (endsWith (filename, "/msg_error.png"))
+ stock = GTK_STOCK_DIALOG_ERROR;
+ if (stock && gtk_style_lookup_icon_set (m_widget->style, stock)) {
+ GdkPixbuf *pixbuf = gtk_widget_render_icon (m_widget, stock, GTK_ICON_SIZE_DIALOG, NULL);
+ ygtk_image_set_from_pixbuf (image, pixbuf);
+ }
+ else
+ ygtk_image_set_from_file (image, filename.c_str(), animated);
+ }
+
+ virtual void setAutoScale (bool scale)
+ {
+ YGtkImageAlign align = CENTER_IMAGE_ALIGN;
+ if (scale)
+ align = SCALE_IMAGE_ALIGN;
+ ygtk_image_set_props (YGTK_IMAGE (getWidget()), align, NULL);
+ }
+
+ YGWIDGET_IMPL_COMMON (YImage)
+};
+
+YImage *YGWidgetFactory::createImage (YWidget *parent, const string &filename, bool animated)
+{ return new YGImage (parent, filename, animated); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGInputField.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGInputField.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGInputField.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGInputField.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,338 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "YGUtils.h"
+#include "ygtkfieldentry.h"
+
+#include
+
+class YGInputField : public YInputField, public YGLabeledWidget
+{
+public:
+ YGInputField (YWidget *parent, const string &label, bool passwordMode)
+ : YInputField (NULL, label, passwordMode),
+ YGLabeledWidget (this, parent, label, YD_HORIZ,
+ YGTK_TYPE_FIELD_ENTRY, NULL)
+ {
+ gtk_widget_set_size_request (getWidget(), 0, -1); // let min size, set width
+ YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget());
+ ygtk_field_entry_add_field (field, 0);
+
+ GtkEntry *entry = ygtk_field_entry_get_field_widget (field, 0);
+ gtk_entry_set_activates_default (entry, TRUE);
+ gtk_entry_set_visibility (entry, !passwordMode);
+
+ connect (getWidget(), "field-entry-changed", G_CALLBACK (value_changed_cb), this);
+ }
+
+ // YInputField
+ virtual string value()
+ {
+ YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget());
+ return ygtk_field_entry_get_field_text (field, 0);
+ }
+
+ virtual void setValue (const string &text)
+ {
+ BlockEvents block (this);
+ YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget());
+ ygtk_field_entry_set_field_text (field, 0, text.c_str());
+ }
+
+ void updateProps()
+ {
+ YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget());
+ ygtk_field_entry_setup_field (field, 0, inputMaxLength(), validChars().c_str());
+ }
+
+ virtual void setInputMaxLength (int len)
+ {
+ YInputField::setInputMaxLength (len);
+ updateProps();
+ }
+
+ virtual void setValidChars (const string &validChars)
+ {
+ YInputField::setValidChars (validChars);
+ updateProps();
+ }
+
+ // callbacks
+ static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb, YGInputField *pThis)
+ { pThis->emitEvent (YEvent::ValueChanged); }
+
+ // YGWidget
+ virtual bool doSetKeyboardFocus()
+ {
+ YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget());
+ return ygtk_field_entry_set_focus (field);
+ }
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ { return dim == YD_HORIZ ? (shrinkable() ? 30 : 200) : 0; }
+
+ YGLABEL_WIDGET_IMPL (YInputField)
+};
+
+YInputField *YGWidgetFactory::createInputField (YWidget *parent, const string &label,
+ bool passwordMode)
+{
+ return new YGInputField (parent, label, passwordMode);
+}
+
+#include "YTimeField.h"
+
+class YGTimeField : public YTimeField, public YGLabeledWidget
+{
+public:
+ YGTimeField (YWidget *parent, const string &label)
+ : YTimeField (NULL, label),
+ YGLabeledWidget (this, parent, label, YD_HORIZ,
+ YGTK_TYPE_FIELD_ENTRY, NULL)
+ {
+ YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget());
+ ygtk_field_entry_add_field (field, ':');
+ ygtk_field_entry_add_field (field, ':');
+ ygtk_field_entry_setup_field (field, 0, 2, "0123456789");
+ ygtk_field_entry_setup_field (field, 1, 2, "0123456789");
+
+ connect (getWidget(), "field-entry-changed", G_CALLBACK (value_changed_cb), this);
+ }
+
+ // YTimeField
+ virtual void setValue (const string &time)
+ {
+ BlockEvents block (this);
+ if (time.empty()) return;
+ char hours[3], mins[3];
+ sscanf (time.c_str(), "%2s:%2s", hours, mins);
+
+ YGtkFieldEntry *entry = YGTK_FIELD_ENTRY (getWidget());
+ ygtk_field_entry_set_field_text (entry, 0, hours);
+ ygtk_field_entry_set_field_text (entry, 1, mins);
+ }
+
+ virtual string value()
+ {
+ const gchar *hours, *mins;
+ YGtkFieldEntry *entry = YGTK_FIELD_ENTRY (getWidget());
+ hours = ygtk_field_entry_get_field_text (entry, 0);
+ mins = ygtk_field_entry_get_field_text (entry, 1);
+
+ gchar *time = g_strdup_printf ("%02d:%02d:00", atoi (hours), atoi (mins));
+ string str (time);
+ g_free (time);
+ return str;
+ }
+
+ // callbacks
+ static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb,
+ YGTimeField *pThis)
+ { pThis->emitEvent (YEvent::ValueChanged); }
+
+ YGLABEL_WIDGET_IMPL (YTimeField)
+};
+
+YTimeField *YGOptionalWidgetFactory::createTimeField (YWidget *parent, const string &label)
+{ return new YGTimeField (parent, label); }
+
+#include "YDateField.h"
+#include "ygtkmenubutton.h"
+
+class YGDateField : public YDateField, public YGLabeledWidget
+{
+GtkWidget *m_calendar, *m_popup_calendar;
+
+public:
+ YGDateField (YWidget *parent, const string &label)
+ : YDateField (NULL, label),
+ YGLabeledWidget (this, parent, label, YD_HORIZ, YGTK_TYPE_FIELD_ENTRY, NULL)
+ {
+ ygtk_field_entry_add_field (getField(), '-');
+ ygtk_field_entry_add_field (getField(), '-');
+ ygtk_field_entry_add_field (getField(), '-');
+ ygtk_field_entry_setup_field (getField(), 0, 4, "0123456789");
+ ygtk_field_entry_setup_field (getField(), 1, 2, "0123456789");
+ ygtk_field_entry_setup_field (getField(), 2, 2, "0123456789");
+
+ m_calendar = gtk_calendar_new();
+ gtk_widget_show (m_calendar);
+ GtkWidget *popup = ygtk_popup_window_new (m_calendar);
+
+ GtkWidget *menu_button = ygtk_menu_button_new_with_label ("");
+ ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (menu_button), popup);
+ gtk_widget_show (menu_button);
+ gtk_box_pack_start (GTK_BOX (getWidget()), menu_button, FALSE, TRUE, 6);
+
+ connect (getWidget(), "field-entry-changed", G_CALLBACK (value_changed_cb), this);
+ connect (m_calendar, "day-selected", G_CALLBACK (calendar_changed_cb), this);
+ g_signal_connect (G_OBJECT (m_calendar), "day-selected-double-click",
+ G_CALLBACK (double_click_cb), popup);
+ }
+
+ inline GtkCalendar *getCalendar()
+ { return GTK_CALENDAR (m_calendar); }
+ inline YGtkFieldEntry *getField()
+ { return YGTK_FIELD_ENTRY (getWidget()); }
+
+ // YDateField
+ virtual void setValue (const string &date)
+ {
+ BlockEvents block (this);
+ if (date.empty()) return;
+ char year[5], month[3], day[3];
+ sscanf (date.c_str(), "%4s-%2s-%2s", year, month, day);
+
+ gtk_calendar_select_month (getCalendar(), atoi (month)-1, atoi (year));
+ gtk_calendar_select_day (getCalendar(), atoi (day));
+
+ ygtk_field_entry_set_field_text (getField(), 0, year);
+ ygtk_field_entry_set_field_text (getField(), 1, month);
+ ygtk_field_entry_set_field_text (getField(), 2, day);
+ }
+
+ virtual string value()
+ {
+ const gchar *year, *month, *day;
+ year = ygtk_field_entry_get_field_text (getField(), 0);
+ month = ygtk_field_entry_get_field_text (getField(), 1);
+ day = ygtk_field_entry_get_field_text (getField(), 2);
+
+ gchar *time = g_strdup_printf ("%04d-%02d-%02d", atoi (year),
+ atoi (month), atoi (day));
+ string str (time);
+ g_free (time);
+ return str;
+ }
+
+ // callbacks
+ static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb,
+ YGDateField *pThis)
+ {
+ int year, month, day;
+ year = atoi (ygtk_field_entry_get_field_text (pThis->getField(), 0));
+ month = atoi (ygtk_field_entry_get_field_text (pThis->getField(), 1));
+ day = atoi (ygtk_field_entry_get_field_text (pThis->getField(), 2));
+
+ if (day < 1 || day > 31 || month < 1 || month > 12)
+ return; // avoid GtkCalendar warnings
+
+ g_signal_handlers_block_by_func (pThis->getCalendar(),
+ (gpointer) calendar_changed_cb, pThis);
+
+ gtk_calendar_select_month (pThis->getCalendar(), month-1, year);
+ gtk_calendar_select_day (pThis->getCalendar(), day);
+
+ g_signal_handlers_unblock_by_func (pThis->getCalendar(),
+ (gpointer) calendar_changed_cb, pThis);
+
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void calendar_changed_cb (GtkCalendar *calendar, YGDateField *pThis)
+ {
+ guint year, month, day;
+ gtk_calendar_get_date (calendar, &year, &month, &day);
+ month += 1; // GTK calendar months go from 0 to 11
+
+ gchar *year_str, *month_str, *day_str;
+ year_str = g_strdup_printf ("%d", year);
+ month_str = g_strdup_printf ("%d", month);
+ day_str = g_strdup_printf ("%d", day);
+
+ g_signal_handlers_block_by_func (pThis->getField(),
+ (gpointer) value_changed_cb, pThis);
+
+ YGtkFieldEntry *entry = pThis->getField();
+ ygtk_field_entry_set_field_text (entry, 0, year_str);
+ ygtk_field_entry_set_field_text (entry, 1, month_str);
+ ygtk_field_entry_set_field_text (entry, 2, day_str);
+
+ g_signal_handlers_unblock_by_func (pThis->getField(),
+ (gpointer) value_changed_cb, pThis);
+
+ g_free (year_str);
+ g_free (month_str);
+ g_free (day_str);
+
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void double_click_cb (GtkCalendar *calendar, YGtkPopupWindow *popup)
+ {
+ // close popup
+ gtk_widget_hide (GTK_WIDGET (popup));
+ }
+
+ YGLABEL_WIDGET_IMPL (YDateField)
+};
+
+YDateField *YGOptionalWidgetFactory::createDateField (YWidget *parent, const string &label)
+{ return new YGDateField (parent, label); }
+
+#include "YTimezoneSelector.h"
+#include "ygtktimezonepicker.h"
+
+class YGTimezoneSelector : public YTimezoneSelector, public YGWidget
+{
+public:
+ YGTimezoneSelector (YWidget *parent, const std::string &pixmap,
+ const std::map &timezones)
+ : YTimezoneSelector (NULL, pixmap, timezones),
+ YGWidget (this, parent, YGTK_TYPE_TIME_ZONE_PICKER, NULL)
+ {
+ setStretchable (YD_HORIZ, true);
+ setStretchable (YD_VERT, true);
+ ygtk_time_zone_picker_set_map (YGTK_TIME_ZONE_PICKER (getWidget()),
+ pixmap.c_str(), convert_code_to_name, (gpointer) &timezones);
+
+ connect (getWidget(), "zone-clicked", G_CALLBACK (zone_clicked_cb), this);
+ }
+
+ // YTimezoneSelector
+ virtual std::string currentZone() const
+ {
+ YGTimezoneSelector *pThis = const_cast (this);
+ const gchar *zone = ygtk_time_zone_picker_get_current_zone (
+ YGTK_TIME_ZONE_PICKER (pThis->getWidget()));
+ if (zone)
+ return zone;
+ return std::string();
+ }
+
+ virtual void setCurrentZone (const std::string &zone, bool zoom)
+ {
+ BlockEvents block (this);
+ ygtk_time_zone_picker_set_current_zone (YGTK_TIME_ZONE_PICKER (getWidget()),
+ zone.c_str(), zoom);
+ }
+
+ // YGtkTimeZonePicker
+ static const gchar *convert_code_to_name (const gchar *code, gpointer pData)
+ {
+ const std::map *timezones =
+ (std::map *) pData;
+ std::map ::const_iterator name =
+ timezones->find (code);
+ if (name == timezones->end())
+ return NULL;
+ return name->second.c_str();
+ }
+
+ // callbacks
+ static void zone_clicked_cb (YGtkTimeZonePicker *picker, const gchar *zone,
+ YGTimezoneSelector *pThis)
+ { pThis->emitEvent (YEvent::ValueChanged); }
+
+ YGWIDGET_IMPL_COMMON (YTimezoneSelector)
+};
+
+YTimezoneSelector *YGOptionalWidgetFactory::createTimezoneSelector (YWidget *parent,
+ const std::string &pixmap, const std::map &timezones)
+{ return new YGTimezoneSelector (parent, pixmap, timezones); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGIntField.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGIntField.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGIntField.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGIntField.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,140 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+class YGSpinBox : public YGLabeledWidget
+{
+ YIntField *m_yfield;
+ GtkWidget *m_spiner, *m_slider;
+
+public:
+ YGSpinBox (YWidget *ywidget, YWidget *parent, const string &label,
+ int minValue, int maxValue, int initialValue, bool show_slider)
+ : YGLabeledWidget (ywidget, parent, label, YD_HORIZ,
+ GTK_TYPE_HBOX, "spacing", 6, NULL)
+ {
+ m_spiner = gtk_spin_button_new_with_range (minValue, maxValue, 1);
+
+ if (show_slider) {
+ m_slider = gtk_hscale_new_with_range (minValue, maxValue, 1);
+ if (maxValue - minValue < 20)
+ // GtkScale by default uses a step of 10 -- use a lower for low values
+ gtk_range_set_increments (GTK_RANGE (m_slider), 1, 2);
+ gtk_scale_set_draw_value (GTK_SCALE (m_slider), FALSE);
+ YGLabeledWidget::setBuddy (m_slider);
+ gtk_widget_set_size_request (m_slider, 100, -1);
+
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_slider, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_spiner, FALSE, TRUE, 0);
+ gtk_widget_show (m_slider);
+ }
+ else {
+ m_slider = NULL;
+ YGLabeledWidget::setBuddy (m_spiner);
+ gtk_container_add (GTK_CONTAINER (getWidget()), m_spiner);
+ }
+ gtk_widget_show (m_spiner);
+
+ doSetValue (initialValue);
+ connect (m_spiner, "value-changed", G_CALLBACK (spiner_changed_cb), this);
+ if (m_slider)
+ connect (m_slider, "value-changed", G_CALLBACK (slider_changed_cb), this);
+ }
+
+ GtkSpinButton *getSpiner()
+ { return GTK_SPIN_BUTTON (m_spiner); }
+
+ bool useSlider()
+ { return m_slider != NULL; }
+ GtkRange *getSlider()
+ { return GTK_RANGE (m_slider); }
+
+ virtual void reportValue (int value) = 0;
+
+ int doGetValue()
+ { return gtk_spin_button_get_value_as_int (getSpiner()); }
+
+ void doSetValue (int value)
+ {
+ BlockEvents block (this);
+ gtk_spin_button_set_value (getSpiner(), value);
+ if (useSlider())
+ gtk_range_set_value (getSlider(), value);
+ }
+
+ // Events callbacks
+ static void spiner_changed_cb (GtkSpinButton *widget, YGSpinBox *pThis)
+ {
+ int value = gtk_spin_button_get_value_as_int (pThis->getSpiner());
+ pThis->reportValue (value);
+ if (pThis->useSlider())
+ gtk_range_set_value (pThis->getSlider(), value);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void slider_changed_cb (GtkRange *range, YGSpinBox *pThis)
+ {
+ int value = (int) gtk_range_get_value (range);
+ gtk_spin_button_set_value (pThis->getSpiner(), value);
+ pThis->reportValue (value);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+};
+
+#define YGSPIN_BOX_IMPL(ParentClass) \
+ virtual void reportValue (int value) { \
+ ParentClass::setValue (value); \
+ } \
+ virtual int value() { \
+ return doGetValue(); \
+ } \
+ virtual void setValueInternal (int value) { \
+ doSetValue (value); \
+ }
+
+#include "YIntField.h"
+
+class YGIntField : public YIntField, public YGSpinBox
+{
+public:
+ YGIntField (YWidget *parent, const string &label, int minValue, int maxValue,
+ int initialValue)
+ : YIntField (NULL, label, minValue, maxValue)
+ , YGSpinBox (this, parent, label, minValue, maxValue, initialValue, false)
+ {}
+
+ YGLABEL_WIDGET_IMPL (YIntField)
+ YGSPIN_BOX_IMPL (YIntField)
+};
+
+YIntField *YGWidgetFactory::createIntField (YWidget *parent, const string &label,
+ int minValue, int maxValue, int initialValue)
+{ return new YGIntField (parent, label, minValue, maxValue, initialValue); }
+
+#include "YSlider.h"
+
+class YGSlider : public YSlider, public YGSpinBox
+{
+public:
+ YGSlider (YWidget *parent, const string &label, int minValue, int maxValue,
+ int initialValue)
+ : YSlider (NULL, label, minValue, maxValue)
+ , YGSpinBox (this, parent, label, minValue, maxValue, initialValue, true)
+ {}
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ { return dim == YD_HORIZ ? 200 : 0; }
+
+ YGLABEL_WIDGET_IMPL (YSlider)
+ YGSPIN_BOX_IMPL (YSlider)
+};
+
+YSlider *YGOptionalWidgetFactory::createSlider (YWidget *parent, const string &label,
+ int minValue, int maxValue, int initialValue)
+{ return new YGSlider (parent, label, minValue, maxValue, initialValue); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLabel.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLabel.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLabel.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLabel.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,55 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YLabel.h"
+
+class YGLabel : public YLabel, public YGWidget
+{
+public:
+ YGLabel (YWidget *parent, const std::string &text, bool heading, bool outputField)
+ : YLabel (NULL, text, heading, outputField),
+ YGWidget (this, parent, GTK_TYPE_LABEL, NULL)
+ {
+ gtk_misc_set_alignment (GTK_MISC (getWidget()), 0.0, 0.5);
+ if (outputField) {
+ gtk_label_set_selectable (GTK_LABEL (getWidget()), TRUE);
+ gtk_label_set_single_line_mode (GTK_LABEL (getWidget()), TRUE);
+ YGUtils::setWidgetFont (getWidget(), PANGO_STYLE_ITALIC, PANGO_WEIGHT_NORMAL,
+ PANGO_SCALE_MEDIUM);
+ }
+ if (heading)
+ YGUtils::setWidgetFont (getWidget(), PANGO_STYLE_NORMAL, PANGO_WEIGHT_BOLD,
+ PANGO_SCALE_LARGE);
+ setLabel (text);
+ }
+
+ virtual void setText (const std::string &label)
+ {
+ YLabel::setText (label);
+ gtk_label_set_label (GTK_LABEL (getWidget()), label.c_str());
+ std::string::size_type i = label.find ('\n', 0);
+ if (isOutputField()) { // must not have a breakline
+ if (i != std::string::npos) {
+ std::string l (label, 0, i);
+ gtk_label_set_label (GTK_LABEL (getWidget()), l.c_str());
+ }
+ }
+ else {
+ bool selectable = i != std::string::npos && i != label.size()-1;
+ gtk_label_set_selectable (GTK_LABEL (getWidget()), selectable);
+ }
+ }
+
+ YGWIDGET_IMPL_COMMON (YLabel)
+ YGWIDGET_IMPL_USE_BOLD (YLabel)
+};
+
+YLabel *YGWidgetFactory::createLabel (YWidget *parent,
+ const std::string &text, bool heading, bool outputField)
+{ return new YGLabel (parent, text, heading, outputField); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLayout.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLayout.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLayout.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGLayout.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,285 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGWidget.h"
+#include "YGUtils.h"
+
+/* Our layout stuff is a hybrid between GTK and libyui. We use libyui
+ for YLayoutBox and a couple of other widgets, but we do things GTK
+ friendly, so for single-child containers like GtkNotebook we don't
+ have to do any work. */
+
+#include "ygtkfixed.h"
+
+static void doMoveChild (GtkWidget *fixed, YWidget *ychild, int x, int y)
+{
+ GtkWidget *child = YGWidget::get (ychild)->getLayout();
+ ygtk_fixed_set_child_pos (YGTK_FIXED (fixed), child, x, y);
+}
+
+#define YGLAYOUT_INIT \
+ ygtk_fixed_setup (YGTK_FIXED (getWidget()), preferred_size_cb, set_size_cb, this);
+#define YGLAYOUT_PREFERRED_SIZE_IMPL(ParentClass) \
+ static void preferred_size_cb (YGtkFixed *fixed, gint *width, gint *height, \
+ gpointer pThis) { \
+ *width = ((ParentClass *) pThis)->ParentClass::preferredWidth(); \
+ *height = ((ParentClass *) pThis)->ParentClass::preferredHeight(); \
+ }
+#define YGLAYOUT_SET_SIZE_IMPL(ParentClass) \
+ static void set_size_cb (YGtkFixed *fixed, gint width, gint height, \
+ gpointer pThis) { \
+ ((ParentClass *) pThis)->ParentClass::setSize (width, height); \
+ } \
+ virtual void moveChild (YWidget *ychild, int x, int y) \
+ { doMoveChild (getWidget(), ychild, x, y); } \
+
+#include
+
+class ButtonHeightGroup
+{
+GtkSizeGroup *group;
+
+public:
+ ButtonHeightGroup() { group = NULL; }
+
+ void addWidget (YWidget *ywidget)
+ {
+ if (dynamic_cast (ywidget)) {
+ bool create_group = !group;
+ if (create_group)
+ group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+ gtk_size_group_add_widget (group, YGWidget::get (ywidget)->getLayout());
+ if (create_group)
+ g_object_unref (G_OBJECT (group));
+ }
+ }
+};
+
+#include
+
+class YGLayoutBox : public YLayoutBox, public YGWidget
+{
+// set all buttons in a HBox the same height (some may have icons)
+ButtonHeightGroup group;
+
+public:
+ YGLayoutBox (YWidget *parent, YUIDimension dim)
+ : YLayoutBox (NULL, dim),
+ YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
+ {
+ setBorder (0);
+ YGLAYOUT_INIT
+ }
+
+ virtual void doAddChild (YWidget *ychild, GtkWidget *container)
+ {
+ YGWidget::doAddChild (ychild, container);
+ if (primary() == YD_HORIZ)
+ group.addWidget (ychild);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YLayoutBox)
+ YGLAYOUT_PREFERRED_SIZE_IMPL (YLayoutBox)
+ YGLAYOUT_SET_SIZE_IMPL (YLayoutBox)
+};
+
+YLayoutBox *YGWidgetFactory::createLayoutBox (YWidget *parent, YUIDimension dimension)
+{ return new YGLayoutBox (parent, dimension); }
+
+#if YAST2_VERSION >= 2017006
+#include
+
+class YGButtonBox : public YButtonBox, public YGWidget
+{
+ButtonHeightGroup group;
+
+public:
+ YGButtonBox (YWidget *parent)
+ : YButtonBox (NULL),
+ YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
+ {
+ setBorder (0);
+ // YUI system variable test for layout policy doesn't work flawlessly
+ setLayoutPolicy (gnomeLayoutPolicy());
+ YGLAYOUT_INIT
+ }
+
+ virtual void doAddChild (YWidget *ychild, GtkWidget *container)
+ {
+ YGWidget::doAddChild (ychild, container);
+ group.addWidget (ychild);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YButtonBox)
+ YGLAYOUT_PREFERRED_SIZE_IMPL (YButtonBox)
+ YGLAYOUT_SET_SIZE_IMPL (YButtonBox)
+};
+
+YButtonBox *YGWidgetFactory::createButtonBox (YWidget *parent)
+{ return new YGButtonBox (parent); }
+
+#endif
+
+#include
+
+class YGAlignment : public YAlignment, public YGWidget
+{
+ GdkPixbuf *m_background_pixbuf;
+
+public:
+ YGAlignment (YWidget *parent, YAlignmentType halign, YAlignmentType valign)
+ : YAlignment (NULL, halign, valign),
+ YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
+ {
+ setBorder (0);
+ m_background_pixbuf = 0;
+ YGLAYOUT_INIT
+ }
+
+ virtual ~YGAlignment()
+ {
+ if (m_background_pixbuf)
+ g_object_unref (G_OBJECT (m_background_pixbuf));
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YAlignment)
+ YGLAYOUT_PREFERRED_SIZE_IMPL (YAlignment)
+ YGLAYOUT_SET_SIZE_IMPL (YAlignment)
+
+ virtual void setBackgroundPixmap (const std::string &_filename)
+ {
+ YAlignment::setBackgroundPixmap (_filename);
+ // YAlignment will prepend a path to the image
+ std::string filename (YAlignment::backgroundPixmap());
+
+ if (m_background_pixbuf)
+ g_object_unref (G_OBJECT (m_background_pixbuf));
+
+ if (filename.empty()) {
+ m_background_pixbuf = 0;
+ g_signal_handlers_disconnect_by_func (G_OBJECT (getWidget()),
+ (void*) expose_event_cb, this);
+ }
+ else {
+ GError *error = 0;
+ m_background_pixbuf = gdk_pixbuf_new_from_file (filename.c_str(), &error);
+ if (!m_background_pixbuf)
+ g_warning ("Setting YAlignment background - couldn't load image '%s' - %s",
+ filename.c_str(), error->message);
+ else
+ g_signal_connect (G_OBJECT (getWidget()), "expose-event",
+ G_CALLBACK (expose_event_cb), this);
+ }
+ }
+
+ static gboolean expose_event_cb (GtkWidget *widget, GdkEventExpose *event,
+ YGAlignment *pThis)
+ {
+ GtkAllocation *alloc = &widget->allocation;
+ cairo_t *cr = gdk_cairo_create (widget->window);
+
+ gdk_cairo_set_source_pixbuf (cr, pThis->m_background_pixbuf, 0, 0);
+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+
+ cairo_rectangle (cr, alloc->x, alloc->y, alloc->width, alloc->height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ GTK_BIN (widget)->child, event);
+ return TRUE;
+ }
+};
+
+YAlignment *YGWidgetFactory::createAlignment (YWidget *parent, YAlignmentType halign,
+ YAlignmentType valign)
+{ return new YGAlignment (parent, halign, valign); }
+
+#include
+
+// Just an empty space.
+class YGEmpty : public YEmpty, public YGWidget
+{
+public:
+ YGEmpty (YWidget *parent)
+ : YEmpty (NULL),
+ YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_COMMON (YEmpty)
+};
+
+YEmpty *YGWidgetFactory::createEmpty (YWidget *parent)
+{ return new YGEmpty (parent); }
+
+#include
+
+// Empty space, with a fixed size.
+class YGSpacing : public YSpacing, public YGWidget
+{
+public:
+ YGSpacing (YWidget *parent, YUIDimension dim, bool stretchable, YLayoutSize_t size)
+ : YSpacing (NULL, dim, stretchable, size),
+ YGWidget (this, parent, YGTK_TYPE_FIXED, NULL)
+ {
+ setBorder (0);
+ YGLAYOUT_INIT
+ }
+
+ YGWIDGET_IMPL_COMMON (YSpacing)
+ YGLAYOUT_PREFERRED_SIZE_IMPL (YSpacing)
+ static void set_size_cb (YGtkFixed *fixed, gint width, gint height,
+ gpointer pThis) {}
+};
+
+YSpacing *YGWidgetFactory::createSpacing (YWidget *parent, YUIDimension dim,
+ bool stretchable, YLayoutSize_t size)
+{
+ return new YGSpacing (parent, dim, stretchable, size);
+}
+
+#include
+
+// an empty space that will get replaced
+class YGReplacePoint : public YReplacePoint, public YGWidget
+{
+public:
+ YGReplacePoint (YWidget *parent)
+ : YReplacePoint (NULL),
+ YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YReplacePoint)
+};
+
+YReplacePoint *YGWidgetFactory::createReplacePoint (YWidget *parent)
+{ return new YGReplacePoint (parent); }
+
+#include
+
+// A-like YAlignment, YSquash messes around child settings.
+// In this case, it can remove the stretchable attribute.
+class YGSquash : public YSquash, public YGWidget
+{
+public:
+ YGSquash (YWidget *parent, bool hsquash, bool vsquash)
+ : YSquash (NULL, hsquash, vsquash),
+ YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YSquash)
+};
+
+YSquash *YGWidgetFactory::createSquash (YWidget *parent, bool hsquash, bool vsquash)
+{ return new YGSquash (parent, hsquash, vsquash); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGMenuButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGMenuButton.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGMenuButton.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGMenuButton.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,139 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YMenuButton.h"
+#include "ygtkmenubutton.h"
+
+static void selected_item_cb (GtkMenuItem *menuitem, YItem *item)
+{
+ // HACK: gtk_menu_get_active() doesn't work properly
+ GtkWidget *menu = gtk_widget_get_ancestor (GTK_WIDGET (menuitem), GTK_TYPE_MENU);
+ g_object_set_data (G_OBJECT (menu), "active", menuitem);
+
+ YGUI::ui()->sendEvent (new YMenuEvent (item));
+}
+
+static void doCreateMenu (GtkWidget *parent, YItemIterator begin, YItemIterator end)
+{
+ for (YItemIterator it = begin; it != end; it++) {
+ GtkWidget *entry, *image = 0;
+ string str = YGUtils::mapKBAccel ((*it)->label());
+
+ if ((*it)->hasIconName()) {
+ GdkPixbuf *pixbuf = YGUtils::loadPixbuf ((*it)->iconName());
+ if (pixbuf) {
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ }
+ else {
+ const char *stock = YGUtils::mapStockIcon (str);
+ if (stock)
+ image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
+ }
+
+ if (image) {
+ entry = gtk_image_menu_item_new_with_mnemonic (str.c_str());
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (entry), image);
+ }
+ else
+ entry = gtk_menu_item_new_with_mnemonic (str.c_str());
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (parent), entry);
+
+ if ((*it)->hasChildren()) {
+ GtkWidget *submenu = gtk_menu_new();
+ doCreateMenu (submenu, (*it)->childrenBegin(), (*it)->childrenEnd());
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (entry), submenu);
+ }
+ else
+ g_signal_connect (G_OBJECT (entry), "activate",
+ G_CALLBACK (selected_item_cb), *it);
+ }
+}
+
+class YGMenuButton : public YMenuButton, public YGWidget
+{
+public:
+ YGMenuButton (YWidget *parent, const string &label)
+ : YMenuButton (NULL, label),
+ YGWidget (this, parent, YGTK_TYPE_MENU_BUTTON, NULL)
+ { setLabel (label); }
+
+ // YMenuButton
+ virtual void setLabel (const std::string &label)
+ {
+ string str = YGUtils::mapKBAccel (label.c_str());
+ ygtk_menu_button_set_label (YGTK_MENU_BUTTON (getWidget()), str.c_str());
+ YMenuButton::setLabel (label);
+ }
+
+ virtual void rebuildMenuTree()
+ {
+ GtkWidget *menu = gtk_menu_new();
+ doCreateMenu (menu, itemsBegin(), itemsEnd());
+ gtk_widget_show_all (menu);
+ ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (getWidget()), menu);
+ }
+
+ YGWIDGET_IMPL_COMMON (YMenuButton)
+};
+
+YMenuButton *YGWidgetFactory::createMenuButton (YWidget *parent, const string &label)
+{ return new YGMenuButton (parent, label); }
+
+#if YAST2_VERSION > 2018003
+#include
+
+class YGContextMenu : public YContextMenu, public YGWidget
+{
+public:
+ YGContextMenu()
+ : YContextMenu(),
+ YGWidget (this, NULL, GTK_TYPE_MENU, NULL)
+ {
+ // "cancel" signal doesnt seem to work properly
+ connect (getWidget(), "deactivate", G_CALLBACK (deactivate_cb), this);
+ }
+
+ // YContextMenu
+ virtual void rebuildMenuTree()
+ {
+ GtkWidget *menu = getWidget();
+ doCreateMenu (menu, itemsBegin(), itemsEnd());
+ gtk_widget_show_all (menu);
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
+ }
+
+ // callbacks
+ static void deactivate_cb (GtkMenuShell *menu, YGContextMenu *pThis)
+ { // ugly: we need to make sure a selection was made before this callback called
+ g_idle_add_full (G_PRIORITY_LOW, cancel_cb, pThis, NULL);
+ }
+
+ static gboolean cancel_cb (gpointer data)
+ {
+ YGContextMenu *pThis = (YGContextMenu *) data;
+ if (!g_object_get_data (G_OBJECT (pThis->getWidget()), "active"))
+ YGUI::ui()->sendEvent (new YCancelEvent());
+ delete pThis;
+ return FALSE;
+ }
+
+ YGWIDGET_IMPL_COMMON (YContextMenu)
+};
+
+bool YGApplication::openContextMenu (const YItemCollection &itemCollection)
+{
+ YGContextMenu *menu = new YGContextMenu();
+ menu->addItems (itemCollection);
+ return true;
+}
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginIf.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginIf.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginIf.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginIf.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,20 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGPACKAGE_SELECTOR_PLUGIN_IF
+#define YGPACKAGE_SELECTOR_PLUGIN_IF
+
+struct YPackageSelector;
+struct YWidget;
+
+class YGPackageSelectorPluginIf
+{
+public:
+ virtual YPackageSelector *createPackageSelector (YWidget *parent, long modeFlags) = 0;
+ virtual YWidget *createPatternSelector (YWidget *parent, long modeFlags) = 0;
+ virtual YWidget *createSimplePatchSelector (YWidget *parent, long modeFlags) = 0;
+};
+
+#endif /*YGPACKAGE_SELECTOR_PLUGIN_IF*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginStub.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginStub.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginStub.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPackageSelectorPluginStub.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,89 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include "YGUI.h"
+#include "YGPackageSelectorPluginIf.h"
+
+#define PLUGIN_BASE_NAME "gtk_pkg"
+#include
+#include
+#include
+#include
+
+class YGPackageSelectorPluginStub : public YPackageSelectorPlugin
+{
+YGPackageSelectorPluginIf *impl;
+
+public:
+ YGPackageSelectorPluginStub()
+ : YPackageSelectorPlugin (PLUGIN_BASE_NAME)
+ {
+ if (success())
+ yuiMilestone() << "Loaded " << PLUGIN_BASE_NAME
+ << " plugin successfully from " << pluginLibFullPath() << endl;
+ impl = (YGPackageSelectorPluginIf *) locateSymbol ("PSP");
+ if (!impl)
+ yuiError() << "Plugin " << PLUGIN_BASE_NAME
+ << " does not provide PSP symbol" << endl;
+ }
+
+ static YGPackageSelectorPluginStub *get()
+ {
+ static YGPackageSelectorPluginStub *plugin = 0;
+ if (!plugin)
+ // deliberately keep plugin open
+ plugin = new YGPackageSelectorPluginStub();
+ return plugin;
+ }
+
+ virtual YPackageSelector *createPackageSelector (YWidget *parent, long modeFlags)
+ {
+ if (!impl)
+ YUI_THROW (YUIPluginException (PLUGIN_BASE_NAME));
+ return impl->createPackageSelector (parent, modeFlags);
+ }
+
+ virtual YWidget *createPatternSelector (YWidget *parent, long modeFlags)
+ {
+ if (!impl)
+ YUI_THROW (YUIPluginException (PLUGIN_BASE_NAME));
+ return impl->createPatternSelector (parent, modeFlags);
+ }
+
+ virtual YWidget *createSimplePatchSelector (YWidget *parent, long modeFlags)
+ {
+ if (!impl)
+ YUI_THROW (YUIPluginException (PLUGIN_BASE_NAME));
+ return impl->createSimplePatchSelector (parent, modeFlags);
+ }
+};
+
+// YWidgetFactory
+
+YPackageSelector* YGWidgetFactory::createPackageSelector (YWidget* parent, long modeFlags)
+{
+ YGPackageSelectorPluginStub *plugin = YGPackageSelectorPluginStub::get();
+ if (plugin)
+ return plugin->createPackageSelector (parent, modeFlags);
+ return NULL;
+}
+
+// YOptionalWidgetFactory
+
+YWidget* YGOptionalWidgetFactory::createPatternSelector (YWidget* parent, long modeFlags)
+{
+ YGPackageSelectorPluginStub *plugin = YGPackageSelectorPluginStub::get();
+ if (plugin)
+ return plugin->createPatternSelector (parent, modeFlags);
+ return NULL;
+}
+
+YWidget* YGOptionalWidgetFactory::createSimplePatchSelector (YWidget* parent, long modeFlags)
+{
+ YGPackageSelectorPluginStub *plugin = YGPackageSelectorPluginStub::get();
+ if (plugin)
+ return plugin->createSimplePatchSelector (parent, modeFlags);
+ return NULL;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGProgressBar.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGProgressBar.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGProgressBar.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGProgressBar.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,257 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/*
+ Textdomain "gtk"
+ */
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "YGi18n.h"
+
+std::string size_stdform (YFileSize_t size)
+{
+ long double mantissa = size;
+ int unit = 0;
+ for (; mantissa/1024 > 1; unit++)
+ mantissa /= 1024;
+
+ const char *unit_str = "";
+ switch (unit) {
+ // translator: byte shorthand
+ case 0: unit_str = _("B"); break;
+ case 1: unit_str = _("KB"); break;
+ case 2: unit_str = _("MB"); break;
+ case 3: unit_str = _("GB"); break;
+ case 4: unit_str = _("TB"); break;
+ default: mantissa = 0; break;
+ }
+
+ gchar *text = g_strdup_printf ("%.1f %s", (float) mantissa, unit_str);
+ std::string str (text);
+ g_free (text);
+ return str;
+}
+
+#include "YProgressBar.h"
+
+class YGProgressBar : public YProgressBar, public YGLabeledWidget
+{
+public:
+ YGProgressBar (YWidget *parent, const string &label, int maxValue)
+ : YProgressBar (NULL, label, maxValue)
+ // NOTE: its label widget is positionated at the vertical, because its label
+ // may change often and so will its size, which will look odd (we may want
+ // to make the label widget to only grow).
+ , YGLabeledWidget (this, parent, label, YD_VERT, GTK_TYPE_PROGRESS_BAR, NULL)
+ {}
+
+ // YProgressBar
+ virtual void setValue (int value)
+ {
+ YProgressBar::setValue (value);
+ GtkProgressBar *bar = GTK_PROGRESS_BAR (getWidget());
+ float fraction = CLAMP ((float) value / maxValue(), 0, 1);
+ gtk_progress_bar_set_fraction (bar, fraction);
+/*
+ char *text = g_strdup_printf ("%d %%", (int) (fraction*100));
+ gtk_progress_bar_set_text (bar, text);
+ g_free (text);
+*/
+ }
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ { return dim == YD_HORIZ ? 200 : 0; }
+
+ YGLABEL_WIDGET_IMPL (YProgressBar)
+};
+
+YProgressBar *YGWidgetFactory::createProgressBar (YWidget *parent, const string &label,
+ int maxValue)
+{
+ return new YGProgressBar (parent, label, maxValue);
+}
+
+#include "YDownloadProgress.h"
+
+class YGDownloadProgress : public YDownloadProgress, public YGLabeledWidget
+{
+guint timeout_id;
+
+public:
+ YGDownloadProgress (YWidget *parent, const string &label,
+ const string &filename, YFileSize_t expectedFileSize)
+ : YDownloadProgress (NULL, label, filename, expectedFileSize)
+ , YGLabeledWidget (this, parent, label, YD_HORIZ, GTK_TYPE_PROGRESS_BAR, NULL)
+ {
+ timeout_id = g_timeout_add (250, timeout_cb, this);
+ }
+
+ virtual ~YGDownloadProgress()
+ {
+ g_source_remove (timeout_id);
+ }
+
+ virtual void setExpectedSize (YFileSize_t size)
+ {
+ YDownloadProgress::setExpectedSize (size);
+ timeout_cb (this); // force an update
+ }
+
+ static gboolean timeout_cb (void *pData)
+ {
+ YGDownloadProgress *pThis = (YGDownloadProgress*) pData;
+ GtkProgressBar *bar = GTK_PROGRESS_BAR (pThis->getWidget());
+
+ gtk_progress_bar_set_fraction (bar, pThis->currentPercent() / 100.0);
+ if (pThis->expectedSize() > 0) {
+ std::string current (size_stdform (pThis->currentFileSize()));
+ std::string total (size_stdform (pThis->expectedSize()));
+ std::string text = current + " " + _("of") + " " + total;
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (bar), text.c_str());
+ }
+ return TRUE;
+ }
+
+ YGLABEL_WIDGET_IMPL (YDownloadProgress)
+};
+
+YDownloadProgress *YGOptionalWidgetFactory::createDownloadProgress (YWidget *parent,
+ const string &label, const string &filename, YFileSize_t expectedFileSize)
+{ return new YGDownloadProgress (parent, label, filename, expectedFileSize); }
+
+#include "ygtkratiobox.h"
+#include "YMultiProgressMeter.h"
+
+class YGMultiProgressMeter : public YMultiProgressMeter, public YGWidget
+{
+public:
+ YGMultiProgressMeter (YWidget *parent, YUIDimension dim, const vector <float> &maxValues)
+ : YMultiProgressMeter (NULL, dim, maxValues)
+ , YGWidget (this, parent,
+ horizontal() ? YGTK_TYPE_RATIO_HBOX : YGTK_TYPE_RATIO_VBOX, NULL)
+ {
+ ygtk_ratio_box_set_spacing (YGTK_RATIO_BOX (getWidget()), 2);
+ 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);
+ // Progress bars would ask for too much size with weight...
+ const int min_size = 5;
+ if (horizontal())
+ gtk_widget_set_size_request (bar, min_size, -1);
+ else
+ gtk_widget_set_size_request (bar, -1, min_size);
+ ygtk_ratio_box_pack (YGTK_RATIO_BOX (getWidget()), bar, getSegmentWeight (s));
+ }
+
+ ygtk_adj_size_set_max (YGTK_ADJ_SIZE (m_adj_size), horizontal() ? 200 : 0,
+ horizontal() ? 0 : 200);
+ gtk_widget_show_all (getWidget());
+ }
+
+ virtual void doUpdate()
+ {
+ GList* children = gtk_container_get_children (GTK_CONTAINER (getWidget()));
+ int s = 0;
+ for (GList *i = children; i && s < segments(); i = i->next, s++) {
+ GtkProgressBar *bar = GTK_PROGRESS_BAR (i->data);
+ 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) < 0)
+ return 0;
+ return 1.0 - (((float) currentValue (n)) / maxValue (n));
+ }
+
+ YGWIDGET_IMPL_COMMON (YMultiProgressMeter)
+};
+
+YMultiProgressMeter *YGOptionalWidgetFactory::createMultiProgressMeter (YWidget *parent,
+ YUIDimension dim, const vector <float> &maxValues)
+{ return new YGMultiProgressMeter (parent, dim, maxValues); }
+
+#include "YBusyIndicator.h"
+
+/* YBusyIndicator semantics are pretty contrived. It seems we should animate the widget
+ until timeout is reached. The application will ping setAlive(true) calls -- and we
+ reset the timeout -- as an indication that the program hasn't hang in some operation. */
+
+#define PULSE_INTERVAL 100
+#define PULSE_STEP 0.050
+
+class YGBusyIndicator : public YBusyIndicator, public YGLabeledWidget
+{
+guint pulse_timeout_id;
+int alive_timeout;
+
+public:
+ YGBusyIndicator (YWidget *parent, const string &label, int timeout)
+ : YBusyIndicator (NULL, label, timeout)
+ , YGLabeledWidget (this, parent, label, YD_VERT,
+ GTK_TYPE_PROGRESS_BAR, "pulse-step", PULSE_STEP, NULL)
+ {
+ pulse_timeout_id = 0;
+ pulse();
+ }
+
+ virtual ~YGBusyIndicator()
+ { stop(); }
+
+ void pulse()
+ {
+ alive_timeout = timeout();
+ if (!pulse_timeout_id)
+ pulse_timeout_id = g_timeout_add (PULSE_INTERVAL, pulse_timeout_cb, this);
+ }
+
+ void stop()
+ {
+ alive_timeout = 0;
+ if (pulse_timeout_id) {
+ g_source_remove (pulse_timeout_id);
+ pulse_timeout_id = 0;
+ }
+ }
+
+ // YBusyIndicator
+ virtual void setAlive (bool alive)
+ {
+ YBusyIndicator::setAlive (alive);
+ alive ? pulse() : stop();
+ }
+
+ // callbacks
+ static gboolean pulse_timeout_cb (void *pData)
+ {
+ YGBusyIndicator *pThis = (YGBusyIndicator*) pData;
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pThis->getWidget()));
+ pThis->alive_timeout -= PULSE_INTERVAL;
+ if (pThis->alive_timeout <= 0) {
+ pThis->pulse_timeout_id = 0;
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ YGLABEL_WIDGET_IMPL (YBusyIndicator)
+};
+
+YBusyIndicator *YGWidgetFactory::createBusyIndicator (YWidget *parent, const string &label, int timeout)
+{ return new YGBusyIndicator (parent, label, timeout); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPushButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPushButton.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPushButton.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGPushButton.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,222 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include
+
+#include
+
+class YGPushButton : public YPushButton, public YGWidget
+{
+bool m_customIcon, m_labelIcon;
+
+public:
+ YGPushButton (YWidget *parent, const string &label)
+ : YPushButton (NULL, label),
+ YGWidget (this, parent, GTK_TYPE_BUTTON, "can-default", TRUE, NULL)
+ {
+ m_customIcon = m_labelIcon = false;
+ gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
+ setLabel (label);
+ connect (getWidget(), "clicked", G_CALLBACK (clicked_cb), this);
+ g_signal_connect (getWidget(), "size-request", G_CALLBACK (size_request_cb), this);
+ }
+
+ void setStockIcon (const std::string &label)
+ {
+ if (!m_customIcon) {
+ const char *stock = NULL;
+ switch (functionKey()) {
+ case 1: stock = GTK_STOCK_HELP; break;
+ case 2: stock = GTK_STOCK_INFO; break; // Info
+ case 3: stock = GTK_STOCK_ADD; break;
+ case 4: stock = GTK_STOCK_EDIT; break;
+ case 5: stock = GTK_STOCK_DELETE; break;
+ case 6: stock = GTK_STOCK_EXECUTE; break; // Test
+ case 7: stock = GTK_STOCK_EDIT; break; // Expert
+ // old expert icon: GTK_STOCK_PREFERENCES
+ //case 8: stock = GTK_STOCK_GO_BACK; break;
+ case 9: stock = GTK_STOCK_CANCEL; break;
+ case 10: stock = GTK_STOCK_OK; break; // Next/Finish/OK
+ default: break;
+ }
+#if YAST2_VERSION >= 2017006
+ switch (role()) {
+ case YOKButton: stock = GTK_STOCK_OK; break;
+ case YApplyButton: stock = GTK_STOCK_APPLY; break;
+ case YCancelButton: stock = GTK_STOCK_CANCEL; break;
+ case YHelpButton: stock = GTK_STOCK_HELP; break;
+ case YCustomButton: case YMaxButtonRole: break;
+ }
+#endif
+ m_labelIcon = YGUtils::setStockIcon (getWidget(), label, stock);
+ }
+ }
+
+ // YPushButton
+ virtual void setLabel (const std::string &label)
+ {
+ YPushButton::setLabel (label);
+ string str = YGUtils::mapKBAccel (label);
+ gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
+ setStockIcon (str);
+ }
+
+#if YAST2_VERSION >= 2017006
+ virtual void setRole (YButtonRole role)
+ {
+ YPushButton::setRole (role);
+ if (!m_labelIcon && role != YCustomButton) // to avoid duplications
+ setStockIcon (label());
+ }
+#endif
+
+ virtual void setFunctionKey (int key)
+ {
+ YPushButton::setFunctionKey (key);
+ if (!m_labelIcon && hasFunctionKey())
+ setStockIcon (label());
+ }
+
+ virtual void setHelpButton (bool helpButton)
+ {
+ YPushButton::setHelpButton (helpButton);
+ if (!m_labelIcon && helpButton)
+ setStockIcon (label());
+ }
+
+ virtual void setIcon (const string &icon)
+ {
+ GtkButton *button = GTK_BUTTON (getWidget());
+ if (icon.empty()) {
+ m_customIcon = false;
+ // no need to worry about freeing the image, let it live with button
+ GtkWidget *image = gtk_button_get_image (button);
+ if (image)
+ gtk_widget_hide (image);
+ }
+ else {
+ m_customIcon = true;
+ string path (icon);
+ if (path[0] != '/')
+ path = std::string (THEMEDIR) + "/" + path;
+
+ GError *error = 0;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path.c_str(), &error);
+ if (pixbuf) {
+ GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
+ gtk_button_set_image (button, image);
+ // disregard gtk-button-images setting for explicitly set icons
+ gtk_widget_show (image);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ else
+ yuiWarning() << "YGPushButton: Couldn't load icon image: " << path << endl
+ << "Reason: " << error->message << endl;
+ }
+ }
+
+ virtual void setDefaultButton (bool isDefault)
+ {
+ struct inner {
+ static void realize_cb (GtkWidget *widget)
+ {
+ gtk_widget_grab_default (widget);
+ gtk_widget_grab_focus (widget);
+ }
+ };
+
+ YPushButton::setDefaultButton (isDefault);
+ if (isDefault) {
+ GtkWidget *button = getWidget();
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ if (GTK_WIDGET_REALIZED (button))
+ inner::realize_cb (button);
+ g_signal_connect (G_OBJECT (button), "realize",
+ G_CALLBACK (inner::realize_cb), this);
+ }
+ }
+
+ static bool hasIcon (YWidget *ywidget)
+ {
+ if (dynamic_cast (ywidget)) {
+ GtkWidget *button = YGWidget::get (ywidget)->getWidget();
+ GtkWidget *icon = gtk_button_get_image (GTK_BUTTON (button));
+ return icon && GTK_WIDGET_VISIBLE (icon);
+ }
+ return true;
+ }
+
+#if 0
+ static gboolean treat_icon_cb (GtkWidget *widget, GdkEventExpose *event,
+ YGPushButton *pThis)
+ {
+ YLayoutBox *ybox = dynamic_cast (pThis->parent());
+ if (ybox && !pThis->m_customIcon) {
+ if (ybox->primary() == YD_HORIZ) {
+ // only set stock icons if all to the left have them
+ YWidget *ylast = 0;
+ for (YWidgetListConstIterator it = ybox->childrenBegin();
+ it != ybox->childrenEnd(); it++) {
+ if ((YWidget *) pThis == *it) {
+ if (ylast && !hasIcon (ylast))
+ pThis->setIcon ("");
+ break;
+ }
+ ylast = *it;
+ if (!dynamic_cast (ylast))
+ ylast = NULL;
+ }
+ }
+ else { // YD_VERT
+ // different strategy: set icons for all or none
+ bool disableIcons = false;
+ for (YWidgetListConstIterator it = ybox->childrenBegin();
+ it != ybox->childrenEnd(); it++)
+ if (!hasIcon (*it))
+ disableIcons = true;
+ if (disableIcons)
+ for (YWidgetListConstIterator it = ybox->childrenBegin();
+ it != ybox->childrenEnd(); it++)
+ if (dynamic_cast (*it)) {
+ YGPushButton *button = (YGPushButton *)
+ YGWidget::get (*it);
+ if (!button->m_customIcon)
+ button->setIcon ("");
+ }
+ }
+ }
+ g_signal_handlers_disconnect_by_func (widget, (gpointer) treat_icon_cb, pThis);
+ return FALSE;
+ }
+#endif
+
+ // callbacks
+ static void clicked_cb (GtkButton *button, YGPushButton *pThis)
+ { pThis->emitEvent (YEvent::Activated, IGNORE_NOTIFY_EVENT); }
+
+// default values from gtkbbox.c; can vary from style to style, but no way to query those
+#define DEFAULT_CHILD_MIN_WIDTH 85
+#define DEFAULT_CHILD_MIN_HEIGHT 27
+
+ static void size_request_cb (GtkWidget *widget, GtkRequisition *req, YGPushButton *pThis)
+ { // enlarge button if parent is ButtonBox
+ YWidget *yparent = pThis->m_ywidget->parent();
+ if (yparent && !strcmp (yparent->widgetClass(), "YButtonBox")) {
+ req->width = MAX (req->width, DEFAULT_CHILD_MIN_WIDTH);
+ req->height = MAX (req->height, DEFAULT_CHILD_MIN_HEIGHT);
+ }
+ }
+
+ YGWIDGET_IMPL_COMMON (YPushButton)
+};
+
+YPushButton *YGWidgetFactory::createPushButton (YWidget *parent, const string &label)
+{ return new YGPushButton (parent, label); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGRadioButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGRadioButton.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGRadioButton.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGRadioButton.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,202 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+// Sub-class GtkRadioButton to get a widget that renders like
+// a radio-button, but behaves like a check/toggle-button.
+static GType getCheckRadioButtonType()
+{
+ static GType type = 0;
+
+ if (type)
+ return type;
+
+ static const GTypeInfo info = {
+ sizeof (GtkRadioButtonClass), NULL, NULL,
+ NULL, NULL, NULL,
+ sizeof (GtkRadioButton), 0, NULL
+ };
+ type = g_type_register_static (GTK_TYPE_RADIO_BUTTON, "YGRadioButton",
+ &info, GTypeFlags(0));
+ // save a class_init function
+ GtkButtonClass *klass_new = GTK_BUTTON_CLASS (g_type_class_ref (type));
+ GtkButtonClass *klass_sane =
+ GTK_BUTTON_CLASS (g_type_class_ref (GTK_TYPE_TOGGLE_BUTTON));
+ klass_new->clicked = klass_sane->clicked;
+ return type;
+}
+
+#include "YLayoutBox.h"
+
+static bool is_horizontal_box (YWidget *widget)
+{
+ YLayoutBox *box = dynamic_cast (widget);
+ if (box)
+ return box->primary() == YD_HORIZ;
+ return false;
+}
+
+#include "YRadioButton.h"
+#include "YRadioButtonGroup.h"
+
+class YGRadioButton : public YRadioButton, public YGWidget
+{
+public:
+ YGRadioButton (YWidget *parent, const std::string &label, bool isChecked)
+ : YRadioButton (NULL, label),
+ YGWidget (this, parent, getCheckRadioButtonType(), NULL)
+ {
+ if (!is_horizontal_box (parent))
+ setStretchable (YD_HORIZ, true);
+ setLabel (label);
+ gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (getWidget()), FALSE);
+
+ connect (getWidget(), "toggled", G_CALLBACK (toggled_cb), this);
+ }
+
+ // YRadioButton
+ virtual void setLabel (const string &text)
+ {
+ // NOTE: we can't just set a gtk_widget_modify() at the initialization
+ // because each gtk_button_set_label() creates a new label
+ string str = YGUtils::mapKBAccel(text.c_str());
+ gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
+ YRadioButton::setLabel (text);
+ }
+
+ virtual bool value()
+ { return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (getWidget())); }
+
+ virtual void setValue (bool checked)
+ {
+ BlockEvents block (this);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (getWidget()), checked);
+ if (checked) {
+ YRadioButton *yradio = static_cast (m_ywidget);
+ if (buttonGroup())
+ buttonGroup()->uncheckOtherButtons (yradio);
+ }
+ }
+
+ YGWIDGET_IMPL_COMMON (YRadioButton)
+ YGWIDGET_IMPL_USE_BOLD (YRadioButton)
+
+ // callbacks
+ static void toggled_cb (GtkButton *button, YGRadioButton *pThis)
+ {
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+ pThis->emitEvent (YEvent::ValueChanged);
+ pThis->setValue (true);
+ }
+};
+
+YRadioButton *YGWidgetFactory::createRadioButton (YWidget *parent, const string &label,
+ bool isChecked)
+{
+ YRadioButton *button = new YGRadioButton (parent, label, isChecked);
+
+ // libyui instructs us to do it here due to vfuncs craziness
+ YRadioButtonGroup *group = button->buttonGroup();
+ if (group)
+ group->addRadioButton (button);
+ button->setValue (isChecked);
+ return button;
+}
+
+class YGRadioButtonGroup : public YRadioButtonGroup, public YGWidget
+{
+public:
+ YGRadioButtonGroup(YWidget *parent)
+ : YRadioButtonGroup (NULL),
+ YGWidget (this, parent, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YRadioButtonGroup)
+};
+
+YRadioButtonGroup *YGWidgetFactory::createRadioButtonGroup (YWidget *parent)
+{
+ return new YGRadioButtonGroup (parent);
+}
+
+#include "YCheckBox.h"
+
+class YGCheckBox : public YCheckBox, public YGWidget
+{
+ bool m_isBold;
+
+public:
+ YGCheckBox(YWidget *parent, const string &label, bool isChecked)
+ : YCheckBox (NULL, label),
+ YGWidget (this, parent, GTK_TYPE_CHECK_BUTTON, NULL)
+ {
+ if (!is_horizontal_box (parent))
+ setStretchable (YD_HORIZ, true);
+ setLabel (label);
+ gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (getWidget()), isChecked);
+
+ connect (getWidget(), "toggled", G_CALLBACK (toggled_cb), this);
+ }
+
+ // YCheckButton
+ virtual void setLabel (const string &text)
+ {
+ string str = YGUtils::mapKBAccel(text);
+ gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
+ YCheckBox::setLabel (text);
+ }
+
+ virtual YCheckBoxState value()
+ {
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (getWidget());
+
+ if (gtk_toggle_button_get_inconsistent (button))
+ return YCheckBox_dont_care;
+ return gtk_toggle_button_get_active (button) ? YCheckBox_on : YCheckBox_off;
+ }
+
+ virtual void setValue (YCheckBoxState value)
+ {
+ BlockEvents block (this);
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (getWidget());
+ switch (value) {
+ case YCheckBox_dont_care:
+ gtk_toggle_button_set_inconsistent (button, TRUE);
+ break;
+ case YCheckBox_on:
+ gtk_toggle_button_set_inconsistent (button, FALSE);
+ gtk_toggle_button_set_active (button, TRUE);
+ break;
+ case YCheckBox_off:
+ gtk_toggle_button_set_inconsistent (button, FALSE);
+ gtk_toggle_button_set_active (button, FALSE);
+ break;
+ }
+ }
+
+ static void toggled_cb (GtkBox *box, YGCheckBox *pThis)
+ {
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (box);
+ if (gtk_toggle_button_get_inconsistent (button))
+ pThis->setValue (YCheckBox_on);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ YGWIDGET_IMPL_COMMON (YCheckBox)
+ YGWIDGET_IMPL_USE_BOLD (YCheckBox)
+};
+
+YCheckBox *YGWidgetFactory::createCheckBox (YWidget *parent, const string &label,
+ bool isChecked)
+{ return new YGCheckBox (parent, label, isChecked); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,181 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include
+#include
+#include
+#include "YGUtils.h"
+#include "YGSelectionStore.h"
+
+static inline int getYItemCol (GtkTreeModel *model)
+{ return gtk_tree_model_get_n_columns (model) - 2; }
+
+static inline int getRowIdCol (GtkTreeModel *model)
+{ return gtk_tree_model_get_n_columns (model) - 1; }
+
+YGSelectionStore::YGSelectionStore (bool tree)
+: isTree (tree), m_nextRowId (0)
+{}
+
+YGSelectionStore::~YGSelectionStore()
+{ g_object_unref (G_OBJECT (m_model)); }
+
+void YGSelectionStore::createStore (int cols, const GType types[])
+{
+ int _cols = cols + 2;
+ GType _types[_cols];
+ for (int i = 0; i < cols; i++)
+ _types[i] = types[i];
+ _types[cols+0] = G_TYPE_POINTER; // pointer to YItem
+ _types[cols+1] = G_TYPE_POINTER; // some unique value identifying this row
+
+ if (isTree)
+ m_model = GTK_TREE_MODEL (gtk_tree_store_newv (_cols, _types));
+ else
+ m_model = GTK_TREE_MODEL (gtk_list_store_newv (_cols, _types));
+}
+
+void YGSelectionStore::addRow (YItem *item, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ if (isTree) {
+ GtkTreeStore *store = GTK_TREE_STORE (m_model);
+ gtk_tree_store_append (store, iter, parent);
+ gtk_tree_store_set (store, iter, getYItemCol (m_model), item,
+ getRowIdCol (m_model), m_nextRowId, -1);
+ }
+ else {
+ GtkListStore *store = getListStore();
+ gtk_list_store_append (store, iter);
+ gtk_list_store_set (store, iter, getYItemCol (m_model), item,
+ getRowIdCol (m_model), m_nextRowId, -1);
+ }
+ item->setData (m_nextRowId);
+ m_nextRowId = GINT_TO_POINTER (GPOINTER_TO_INT (m_nextRowId) + 1);
+}
+
+void YGSelectionStore::setRowText (GtkTreeIter *iter, int iconCol, const std::string &icon, int labelCol, const std::string &label, const YSelectionWidget *widget)
+{
+ GdkPixbuf *pixbuf = 0;
+ if (!icon.empty()) {
+ std::string path (widget->iconFullPath (icon));
+ pixbuf = YGUtils::loadPixbuf (path);
+ }
+
+ if (isTree)
+ gtk_tree_store_set (getTreeStore(), iter, iconCol, pixbuf,
+ labelCol, label.c_str(), -1);
+ else
+ gtk_list_store_set (getListStore(), iter, iconCol, pixbuf,
+ labelCol, label.c_str(), -1);
+}
+
+void YGSelectionStore::setRowMark (GtkTreeIter *iter, int markCol, bool mark)
+{
+ if (isTree)
+ gtk_tree_store_set (getTreeStore(), iter, markCol, mark, -1);
+ else
+ gtk_list_store_set (getListStore(), iter, markCol, mark, -1);
+}
+
+void YGSelectionStore::doDeleteAllItems()
+{
+ if (isTree)
+ gtk_tree_store_clear (getTreeStore());
+ else
+ gtk_list_store_clear (getListStore());
+ m_nextRowId = 0;
+}
+
+YItem *YGSelectionStore::getYItem (GtkTreeIter *iter)
+{
+ gpointer ptr;
+ gtk_tree_model_get (m_model, iter, getYItemCol (m_model), &ptr, -1);
+ return (YItem *) ptr;
+}
+
+static GtkTreeIter *found_iter;
+
+void YGSelectionStore::getTreeIter (const YItem *item, GtkTreeIter *iter)
+{
+ struct inner {
+ static gboolean foreach_find (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer find_id)
+ {
+ gpointer id;
+ gtk_tree_model_get (model, iter, getRowIdCol (model), &id, -1);
+ if (id == find_id) {
+ found_iter = gtk_tree_iter_copy (iter);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ };
+
+ found_iter = NULL;
+ gtk_tree_model_foreach (m_model, inner::foreach_find, item->data());
+ *iter = *found_iter;
+ gtk_tree_iter_free (found_iter);
+}
+
+GtkListStore *YGSelectionStore::getListStore()
+{ return GTK_LIST_STORE (m_model); }
+
+GtkTreeStore *YGSelectionStore::getTreeStore()
+{ return GTK_TREE_STORE (m_model); }
+
+bool YGSelectionStore::isEmpty()
+{
+ GtkTreeIter iter;
+ return !gtk_tree_model_get_iter_first (m_model, &iter);
+}
+
+int YGSelectionStore::getTreeDepth()
+{
+ struct inner {
+ static gboolean foreach_max_depth (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _depth)
+ {
+ int *depth = (int *) _depth;
+ *depth = MAX (*depth, gtk_tree_path_get_depth (path));
+ return FALSE;
+ }
+ };
+
+ int depth = 0;
+ gtk_tree_model_foreach (m_model, inner::foreach_max_depth, &depth);
+ return depth;
+}
+
+#include
+static int find_col;
+
+bool YGSelectionStore::findLabel (int labelCol, const std::string &label, GtkTreeIter *iter)
+{
+ struct inner {
+ static gboolean foreach_find (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _value)
+ {
+ gchar *value = (gchar *) _value;
+ gchar *v;
+ gtk_tree_model_get (model, iter, find_col, &v, -1);
+ if (!strcmp (v, value)) {
+ found_iter = gtk_tree_iter_copy (iter);
+ return TRUE;
+ }
+ return FALSE;
+ }
+ };
+
+ find_col = labelCol;
+ found_iter = NULL;
+ gtk_tree_model_foreach (m_model, inner::foreach_find, (gpointer) label.c_str());
+ if (found_iter) {
+ *iter = *found_iter;
+ gtk_tree_iter_free (found_iter);
+ }
+ return found_iter != NULL;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGSelectionStore.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,65 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Provides a basic model common to YSelectedWidget widgets. */
+
+#ifndef YGSELECTION_STORE_H
+#define YGSELECTION_STORE_H
+
+#include
+struct YItem;
+struct YSelectionWidget;
+
+struct YGSelectionStore
+{
+ YGSelectionStore (bool tree);
+ virtual ~YGSelectionStore();
+
+ GtkTreeModel *getModel() { return m_model; }
+ void createStore (int cols, const GType types[]);
+
+ void addRow (YItem *item, GtkTreeIter *iter, GtkTreeIter *parent = 0);
+ void setRowText (GtkTreeIter *iter, int iconCol, const std::string &icon,
+ int labelCol, const std::string &label, const YSelectionWidget *widget);
+ void setRowMark (GtkTreeIter *iter, int markCol, bool mark);
+ void doDeleteAllItems();
+
+ YItem *getYItem (GtkTreeIter *iter);
+ void getTreeIter (const YItem *item, GtkTreeIter *iter);
+
+ GtkListStore *getListStore();
+ GtkTreeStore *getTreeStore();
+
+ bool isEmpty();
+ int getTreeDepth();
+
+ bool findLabel (int labelCol, const std::string &label, GtkTreeIter *iter);
+
+protected:
+ GtkTreeModel *m_model;
+ bool isTree;
+ gpointer m_nextRowId;
+};
+
+#define YGSELECTION_WIDGET_IMPL(ParentClass) \
+ virtual void addItem(YItem *item) { \
+ ParentClass::addItem (item); \
+ doAddItem (item); \
+ } \
+ virtual void deleteAllItems() { \
+ ParentClass::deleteAllItems(); \
+ blockSelected(); \
+ doDeleteAllItems(); \
+ } \
+ virtual void selectItem (YItem *item, bool select) { \
+ ParentClass::selectItem (item, select); \
+ doSelectItem (item, select); \
+ } \
+ virtual void deselectAllItems() { \
+ ParentClass::deselectAllItems(); \
+ doDeselectAllItems(); \
+ }
+
+#endif /*YGSELECTION_STORE_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGText.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGText.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGText.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGText.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,285 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include <string>
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "ygtktextview.h"
+
+class YGTextView : public YGScrolledWidget
+{
+int maxChars;
+
+public:
+ YGTextView (YWidget *ywidget, YWidget *parent, const string &label, bool editable)
+ : YGScrolledWidget (ywidget, parent, label, YD_VERT,
+ YGTK_TYPE_TEXT_VIEW, "wrap-mode", GTK_WRAP_WORD_CHAR,
+ "editable", editable, NULL)
+ {
+ setPolicy (GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ maxChars = -1;
+ connect (getBuffer(), "changed", G_CALLBACK (text_changed_cb), this);
+ }
+
+ GtkTextBuffer* getBuffer()
+ { return gtk_text_view_get_buffer (GTK_TEXT_VIEW (getWidget())); }
+
+ int getCharsNb()
+ { return gtk_text_buffer_get_char_count (getBuffer()); }
+
+ void setCharsNb (int max_chars)
+ {
+ maxChars = max_chars;
+ if (maxChars != -1 && getCharsNb() > maxChars)
+ truncateText (maxChars);
+ }
+
+ void truncateText(int pos)
+ {
+ BlockEvents block (this);
+ GtkTextIter start_it, end_it;
+ gtk_text_buffer_get_iter_at_offset (getBuffer(), &start_it, pos);
+ gtk_text_buffer_get_end_iter (getBuffer(), &end_it);
+ gtk_text_buffer_delete (getBuffer(), &start_it, &end_it);
+ }
+
+ void setText (const std::string &text)
+ {
+ BlockEvents block (this);
+ gtk_text_buffer_set_text (getBuffer(), text.c_str(), -1);
+ }
+
+ void appendText (const std::string &text)
+ {
+ GtkTextIter end_it;
+ gtk_text_buffer_get_end_iter (getBuffer(), &end_it);
+ gtk_text_buffer_insert (getBuffer(), &end_it, text.c_str(), -1);
+ }
+
+ std::string getText()
+ {
+ GtkTextIter start_it, end_it;
+ gtk_text_buffer_get_bounds (getBuffer(), &start_it, &end_it);
+
+ gchar* text = gtk_text_buffer_get_text (getBuffer(), &start_it, &end_it, FALSE);
+ std::string str (text);
+ g_free (text);
+ return str;
+ }
+
+ void scrollToBottom()
+ {
+#if 1
+ YGUtils::scrollWidget (GTK_TEXT_VIEW (getWidget())->vadjustment, false);
+#else
+ GtkTextBuffer *buffer = getBuffer();
+ GtkTextIter iter;
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+ gtk_text_iter_set_line_offset (&iter, 0);
+
+ GtkTextMark *mark = gtk_text_buffer_get_mark (buffer, "scroll");
+ if (mark)
+ gtk_text_buffer_move_mark (buffer, mark, &iter);
+ else
+ mark = gtk_text_buffer_create_mark (buffer, "scroll", &iter, TRUE);
+
+ GtkTextView *view = GTK_TEXT_VIEW (getWidget());
+ gtk_text_view_scroll_mark_onscreen (view, mark);
+#endif
+ }
+
+ // Event callbacks
+ static void text_changed_cb (GtkTextBuffer *buffer, YGTextView *pThis)
+ {
+ if (pThis->maxChars != -1 && pThis->getCharsNb() > pThis->maxChars) {
+ pThis->truncateText (pThis->maxChars);
+ gtk_widget_error_bell (pThis->getWidget());
+ }
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+};
+
+#include "YMultiLineEdit.h"
+
+class YGMultiLineEdit : public YMultiLineEdit, public YGTextView
+{
+public:
+ YGMultiLineEdit (YWidget *parent, const string &label)
+ : YMultiLineEdit (NULL, label)
+ , YGTextView (this, parent, label, true)
+ {}
+
+ // YMultiLineEdit
+ virtual void setValue (const string &text)
+ { YGTextView::setText (text); }
+
+ virtual string value()
+ { return YGTextView::getText(); }
+
+ virtual void setInputMaxLength (int nb)
+ {
+ YGTextView::setCharsNb (nb);
+ YMultiLineEdit::setInputMaxLength (nb);
+ }
+
+ // YGWidget
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ {
+ if (dim == YD_VERT) {
+ int height = YGUtils::getCharsHeight (getWidget(), defaultVisibleLines());
+ return MAX (10, height);
+ }
+ return 30;
+ }
+
+ YGLABEL_WIDGET_IMPL (YMultiLineEdit)
+};
+
+YMultiLineEdit *YGWidgetFactory::createMultiLineEdit (YWidget *parent, const string &label)
+{
+ return new YGMultiLineEdit (parent, label);
+}
+
+#include "YLogView.h"
+
+class YGLogView : public YLogView, public YGTextView
+{
+std::string m_text;
+
+public:
+ YGLogView (YWidget *parent, const string &label, int visibleLines, int maxLines)
+ : YLogView (NULL, label, visibleLines, maxLines)
+ , YGTextView (this, parent, label, false)
+ {}
+
+ // YLogView
+ virtual void displayLogText (const std::string &text)
+ {
+ // libyui calls clearText before setting it: let's ignore it
+ if (text.empty()) return;
+
+ if (text.compare (0, m_text.size(), m_text) == 0) {
+ if (text.size() == m_text.size()) return;
+
+ // appending text: avoid flickering and allow user to scroll freely
+ GtkAdjustment *vadj = GTK_TEXT_VIEW (getWidget())->vadjustment;
+ bool autoScroll = vadj->value >= vadj->upper - vadj->page_size;
+
+ std::string diff (text.substr (m_text.size()));
+ YGTextView::appendText (diff);
+ if (autoScroll)
+ YGTextView::scrollToBottom();
+
+ }
+ else {
+ YGTextView::setText (text);
+ YGTextView::scrollToBottom();
+ }
+ m_text = text;
+ }
+
+ // YGWidget
+ virtual unsigned int getMinSize (YUIDimension dim)
+ {
+ if (dim == YD_VERT) {
+ int height = YGUtils::getCharsHeight (getWidget(), visibleLines());
+ return MAX (80, height);
+ }
+ return 50;
+ }
+
+ YGLABEL_WIDGET_IMPL (YLogView)
+};
+
+YLogView *YGWidgetFactory::createLogView (YWidget *parent, const string &label,
+ int visibleLines, int maxLines)
+{
+ return new YGLogView (parent, label, visibleLines, maxLines);
+}
+
+#include "YRichText.h"
+#include "ygtkhtmlwrap.h"
+
+class YGRichText : public YRichText, YGScrolledWidget
+{
+public:
+ YGRichText (YWidget *parent, const string &text, bool plainText)
+ : YRichText (NULL, text, plainText)
+ , YGScrolledWidget (this, parent, ygtk_html_wrap_get_type(), NULL)
+ {
+ ygtk_html_wrap_init (getWidget());
+ ygtk_html_wrap_connect_link_clicked (getWidget(), link_clicked_cb, this);
+ setText (text, plainText);
+ }
+
+ void setPlainText (const string &text)
+ {
+ ygtk_html_wrap_set_text (getWidget(), text.c_str(), TRUE);
+ }
+
+ void setRichText (const string &text)
+ {
+#if 0 // current done at the XHTML treatment level, we may want to enable
+ // this code so that we replace the entity for all widgets
+ string text (_text);
+ std::string productName = YUI::app()->productName();
+ YGUtils::replace (text, "&product;", 9, productName.c_str());
+#endif
+ ygtk_html_wrap_set_text (getWidget(), text.c_str(), FALSE);
+ }
+
+ void scrollToBottom()
+ {
+ ygtk_html_wrap_scroll (getWidget(), FALSE);
+ }
+
+ void setText (const string &text, bool plain_mode)
+ {
+ plain_mode ? setPlainText (text) : setRichText (text);
+ if (autoScrollDown())
+ scrollToBottom();
+ }
+
+ // YRichText
+ virtual void setValue (const string &text)
+ {
+ YRichText::setValue (text);
+ setText (text, plainTextMode());
+ }
+
+ virtual void setAutoScrollDown (bool on)
+ {
+ YRichText::setAutoScrollDown (on);
+ if (on) scrollToBottom();
+ }
+
+ virtual void setPlainTextMode (bool plain_mode)
+ {
+ YRichText::setPlainTextMode (plain_mode);
+ if (plain_mode != plainTextMode())
+ setText (value(), plain_mode);
+ }
+
+ // callbacks
+ static void link_clicked_cb (GtkWidget *widget, const char *url, gpointer data)
+ { YGUI::ui()->sendEvent (new YMenuEvent (url)); }
+
+ // YGWidget
+ virtual unsigned int getMinSize (YUIDimension dim)
+ { return shrinkable() ? 10 : 100; }
+
+ YGWIDGET_IMPL_COMMON (YRichText)
+};
+
+
+YRichText *YGWidgetFactory::createRichText (YWidget *parent, const string &text,
+ bool plainTextMode)
+{
+ return new YGRichText (parent, text, plainTextMode);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGTreeView.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGTreeView.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGTreeView.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGTreeView.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,870 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YSelectionWidget.h"
+#include "YGSelectionStore.h"
+#include "ygtktreeview.h"
+#include
+
+/* A generic widget for table related widgets. */
+
+class YGTreeView : public YGScrolledWidget, public YGSelectionStore
+{
+protected:
+ guint m_blockTimeout;
+ int markColumn;
+ GtkWidget *m_count;
+
+public:
+ YGTreeView (YWidget *ywidget, YWidget *parent, const string &label, bool tree)
+ : YGScrolledWidget (ywidget, parent, label, YD_VERT, YGTK_TYPE_TREE_VIEW, NULL),
+ YGSelectionStore (tree)
+ {
+ gtk_tree_view_set_headers_visible (getView(), FALSE);
+
+ /* Yast tools expect the user to be unable to un-select the row. They
+ generally don't check to see if the returned value is -1. So, just
+ disallow un-selection. */
+ gtk_tree_selection_set_mode (getSelection(), GTK_SELECTION_BROWSE);
+
+ connect (getSelection(), "changed", G_CALLBACK (selection_changed_cb), this);
+ connect (getWidget(), "row-activated", G_CALLBACK (activated_cb), this);
+ connect (getWidget(), "right-click", G_CALLBACK (right_click_cb), this);
+
+ m_blockTimeout = 0; // GtkTreeSelection idiotically fires when showing widget
+ markColumn = -1; m_count = NULL;
+ blockSelected();
+ g_signal_connect (getWidget(), "map", G_CALLBACK (block_init_cb), this);
+ }
+
+ virtual ~YGTreeView()
+ { if (m_blockTimeout) g_source_remove (m_blockTimeout); }
+
+ inline GtkTreeView *getView()
+ { return GTK_TREE_VIEW (getWidget()); }
+ inline GtkTreeSelection *getSelection()
+ { return gtk_tree_view_get_selection (getView()); }
+
+ void addTextColumn (int iconCol, int textCol)
+ { addTextColumn ("", YAlignUnchanged, iconCol, textCol); }
+
+ void addTextColumn (const std::string &header, YAlignmentType align, int icon_col, int text_col)
+ {
+ gfloat xalign = -1;
+ switch (align) {
+ case YAlignBegin: xalign = 0.0; break;
+ case YAlignCenter: xalign = 0.5; break;
+ case YAlignEnd: xalign = 1.0; break;
+ case YAlignUnchanged: break;
+ }
+
+ GtkTreeViewColumn *column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column, header.c_str());
+
+ GtkCellRenderer *renderer;
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", icon_col, NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer, "text", text_col, NULL);
+ if (xalign != -1)
+ g_object_set (renderer, "xalign", xalign, NULL);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (getView(), column);
+ if (gtk_tree_view_get_search_column (getView()) == -1)
+ gtk_tree_view_set_search_column (getView(), text_col);
+ }
+
+ void addCheckColumn (int check_col)
+ {
+ GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
+ g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (check_col));
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "active", check_col, NULL);
+ gtk_tree_view_column_set_cell_data_func (column, renderer, inconsistent_mark_cb, this, NULL);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (toggled_cb), this);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (getView(), column);
+ if (markColumn == -1)
+ markColumn = check_col;
+ }
+
+ void readModel()
+ { gtk_tree_view_set_model (getView(), getModel()); }
+
+ void addCountWidget (YWidget *yparent)
+ {
+ bool mainWidget = !yparent || !strcmp (yparent->widgetClass(), "YVBox") || !strcmp (yparent->widgetClass(), "YReplacePoint");
+ if (mainWidget) {
+ m_count = gtk_label_new ("0");
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 4);
+ GtkWidget *label = gtk_label_new (_("Total selected:"));
+ //gtk_box_pack_start (GTK_BOX (hbox), gtk_event_box_new(), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), m_count, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (YGWidget::getWidget()), hbox, FALSE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ }
+ }
+
+ void syncCount()
+ {
+ if (!m_count) return;
+
+ struct inner {
+ static gboolean foreach (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTreeView *pThis = (YGTreeView *) _pThis;
+ gboolean mark;
+ gtk_tree_model_get (model, iter, pThis->markColumn, &mark, -1);
+ if (mark) {
+ int count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), "count"));
+ g_object_set_data (G_OBJECT (model), "count", GINT_TO_POINTER (count+1));
+ }
+ return FALSE;
+ }
+ };
+
+ GtkTreeModel *model = getModel();
+ g_object_set_data (G_OBJECT (model), "count", 0);
+ gtk_tree_model_foreach (model, inner::foreach, this);
+
+ int count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), "count"));
+ gchar *str = g_strdup_printf ("%d", count);
+ gtk_label_set_text (GTK_LABEL (m_count), str);
+ g_free (str);
+ }
+
+ void focusItem (YItem *item, bool select)
+ {
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ blockSelected();
+
+ if (select) {
+ GtkTreePath *path = gtk_tree_model_get_path (getModel(), &iter);
+ gtk_tree_view_expand_to_path (getView(), path);
+
+ if (gtk_tree_selection_get_mode (getSelection()) != GTK_SELECTION_MULTIPLE)
+ gtk_tree_view_scroll_to_cell (getView(), path, NULL, TRUE, 0.5, 0);
+ gtk_tree_path_free (path);
+
+ gtk_tree_selection_select_iter (getSelection(), &iter);
+ }
+ else
+ gtk_tree_selection_unselect_iter (getSelection(), &iter);
+ }
+
+ void unfocusAllItems()
+ {
+ blockSelected();
+ gtk_tree_selection_unselect_all (getSelection());
+ }
+
+ void unmarkAll()
+ {
+ struct inner {
+ static gboolean foreach_unmark (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTreeView *pThis = (YGTreeView *) _pThis;
+ pThis->setRowMark (iter, pThis->markColumn, FALSE);
+ return FALSE;
+ }
+ };
+
+ gtk_tree_model_foreach (getModel(), inner::foreach_unmark, this);
+ }
+
+ YItem *getFocusItem()
+ {
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (getSelection(), NULL, &iter))
+ return getYItem (&iter);
+ return NULL;
+ }
+
+ virtual bool _immediateMode() { return true; }
+ virtual bool _shrinkable() { return false; }
+ virtual bool _recursiveSelection() { return false; }
+
+ void setMark (GtkTreeIter *iter, YItem *yitem, gint column, bool state, bool recursive)
+ {
+ setRowMark (iter, column, state);
+ yitem->setSelected (state);
+
+ if (recursive)
+ for (YItemConstIterator it = yitem->childrenBegin();
+ it != yitem->childrenEnd(); it++) {
+ GtkTreeIter _iter;
+ getTreeIter (*it, &_iter);
+ setMark (&_iter, *it, column, state, true);
+ }
+ }
+
+ void toggleMark (GtkTreePath *path, gint column)
+ {
+ GtkTreeIter iter;
+ if (!gtk_tree_model_get_iter (getModel(), &iter, path))
+ return;
+ gboolean state;
+ gtk_tree_model_get (getModel(), &iter, column, &state, -1);
+ state = !state;
+
+ YItem *yitem = getYItem (&iter);
+ setMark (&iter, yitem, column, state, _recursiveSelection());
+ syncCount();
+ emitEvent (YEvent::ValueChanged);
+ }
+
+ // YGWidget
+
+ virtual unsigned int getMinSize (YUIDimension dim)
+ {
+ if (dim == YD_VERT)
+ return YGUtils::getCharsHeight (getWidget(), _shrinkable() ? 2 : 5);
+ return 80;
+ }
+
+protected:
+ static gboolean block_selected_timeout_cb (gpointer data)
+ {
+ YGTreeView *pThis = (YGTreeView *) data;
+ pThis->m_blockTimeout = 0;
+ return FALSE;
+ }
+
+ void blockSelected()
+ { // GtkTreeSelection only fires when idle; so set a timeout
+ if (m_blockTimeout) g_source_remove (m_blockTimeout);
+ m_blockTimeout = g_timeout_add_full (G_PRIORITY_LOW, 50, block_selected_timeout_cb, this, NULL);
+ }
+
+ static void block_init_cb (GtkWidget *widget, YGTreeView *pThis)
+ { pThis->blockSelected(); }
+
+ // callbacks
+
+ static bool all_marked (GtkTreeModel *model, GtkTreeIter *iter, int mark_col)
+ {
+ gboolean marked;
+ GtkTreeIter child_iter;
+ if (gtk_tree_model_iter_children (model, &child_iter, iter))
+ do {
+ gtk_tree_model_get (model, &child_iter, mark_col, &marked, -1);
+ if (!marked) return false;
+ all_marked (model, &child_iter, mark_col);
+ } while (gtk_tree_model_iter_next (model, &child_iter));
+ return true;
+ }
+
+ static void inconsistent_mark_cb (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+ { // used for trees -- show inconsistent if one node is check but another isn't
+ YGTreeView *pThis = (YGTreeView *) data;
+ gboolean marked;
+ gtk_tree_model_get (model, iter, pThis->markColumn, &marked, -1);
+ gboolean consistent = !marked || all_marked (model, iter, pThis->markColumn);
+ g_object_set (G_OBJECT (cell), "inconsistent", !consistent, NULL);
+ }
+
+ static void selection_changed_cb (GtkTreeSelection *selection, YGTreeView *pThis)
+ {
+ struct inner {
+ static gboolean foreach_sync_select (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTreeView *pThis = (YGTreeView *) _pThis;
+ GtkTreeSelection *selection = pThis->getSelection();
+ bool sel = gtk_tree_selection_iter_is_selected (selection, iter);
+ pThis->getYItem (iter)->setSelected (sel);
+ return FALSE;
+ }
+ };
+
+ if (pThis->m_blockTimeout) return;
+ if (pThis->markColumn == -1)
+ gtk_tree_model_foreach (pThis->getModel(), inner::foreach_sync_select, pThis);
+ if (pThis->_immediateMode())
+ pThis->emitEvent (YEvent::SelectionChanged, IF_NOT_PENDING_EVENT);
+ }
+
+ static void activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
+ GtkTreeViewColumn *column, YGTreeView* pThis)
+ {
+ if (pThis->markColumn >= 0)
+ pThis->toggleMark (path, pThis->markColumn);
+ else {
+ // for tree - expand/collpase double-clicked rows
+ if (gtk_tree_view_row_expanded (tree_view, path))
+ gtk_tree_view_collapse_row (tree_view, path);
+ else
+ gtk_tree_view_expand_row (tree_view, path, FALSE);
+
+ pThis->emitEvent (YEvent::Activated);
+ }
+ }
+
+ static void toggled_cb (GtkCellRendererToggle *renderer, gchar *path_str,
+ YGTreeView *pThis)
+ {
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer), "column"));
+ pThis->toggleMark (path, column);
+ gtk_tree_path_free (path);
+
+ // un/marking a sub-node can cause changes of "inconsistency"
+ if (gtk_tree_path_get_depth (path) >= 2)
+ gtk_widget_queue_draw (pThis->getWidget());
+ }
+
+ static void right_click_cb (YGtkTreeView *view, gboolean outreach, YGTreeView *pThis)
+ { pThis->emitEvent (YEvent::ContextMenuActivated); }
+};
+
+#include "YTable.h"
+#include "YGDialog.h"
+#include
+#include
+
+class YGTable : public YTable, public YGTreeView
+{
+public:
+ YGTable (YWidget *parent, YTableHeader *headers, bool multiSelection)
+ : YTable (NULL, headers, multiSelection),
+ YGTreeView (this, parent, std::string(), false)
+ {
+ gtk_tree_view_set_headers_visible (getView(), TRUE);
+ gtk_tree_view_set_rules_hint (getView(), columns() > 1);
+ ygtk_tree_view_set_empty_text (YGTK_TREE_VIEW (getView()), _("No entries."));
+ if (multiSelection)
+ gtk_tree_selection_set_mode (getSelection(), GTK_SELECTION_MULTIPLE);
+
+ GType types [columns()*2];
+ for (int i = 0; i < columns(); i++) {
+ int t = i*2;
+ types[t+0] = GDK_TYPE_PIXBUF;
+ types[t+1] = G_TYPE_STRING;
+ addTextColumn (header(i), alignment (i), t, t+1);
+ }
+ createStore (columns()*2, types);
+ readModel();
+ if (!keepSorting())
+ setSortable (true);
+
+ // if last col is aligned: add some dummy so that it doesn't expand.
+ YAlignmentType lastAlign = alignment (columns()-1);
+ if (lastAlign == YAlignCenter || lastAlign == YAlignEnd)
+ gtk_tree_view_append_column (getView(), gtk_tree_view_column_new());
+
+ g_signal_connect (getWidget(), "key-press-event", G_CALLBACK (key_press_event_cb), this);
+ }
+
+ void setSortable (bool sortable)
+ {
+ if (!sortable && !GTK_WIDGET_REALIZED (getWidget()))
+ return;
+ int n = 0;
+ GList *columns = gtk_tree_view_get_columns (getView());
+ for (GList *i = columns; i; i = i->next, n++) {
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data;
+ if (n >= YGTable::columns())
+ break;
+ if (sortable) {
+ int index = (n*2)+1;
+ if (!sortable)
+ index = -1;
+ gtk_tree_sortable_set_sort_func (
+ GTK_TREE_SORTABLE (getModel()), index, tree_sort_cb,
+ GINT_TO_POINTER (index), NULL);
+ gtk_tree_view_column_set_sort_column_id (column, index);
+ }
+ else
+ gtk_tree_view_column_set_sort_column_id (column, -1);
+ }
+ g_list_free (columns);
+ }
+
+ void setCell (GtkTreeIter *iter, int column, const YTableCell *cell)
+ {
+ if (!cell) return;
+ std::string label (cell->label());
+ if (label == "X")
+ label = YUI::app()->glyph (YUIGlyph_CheckMark);
+
+ int index = column * 2;
+ setRowText (iter, index, cell->iconName(), index+1, label, this);
+ }
+
+ // YGTreeView
+
+ virtual bool _immediateMode() { return immediateMode(); }
+
+ // YTable
+
+ virtual void setKeepSorting (bool keepSorting)
+ {
+ YTable::setKeepSorting (keepSorting);
+ setSortable (!keepSorting);
+ if (!keepSorting) {
+ GtkTreeViewColumn *column = gtk_tree_view_get_column (getView(), 0);
+ if (column)
+ gtk_tree_view_column_clicked (column);
+ }
+ }
+
+ virtual void cellChanged (const YTableCell *cell)
+ {
+ GtkTreeIter iter;
+ getTreeIter (cell->parent(), &iter);
+ setCell (&iter, cell->column(), cell);
+ }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *_item)
+ {
+ YTableItem *item = dynamic_cast (_item);
+ if (item) {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ int i = 0;
+ for (YTableCellIterator it = item->cellsBegin();
+ it != item->cellsEnd(); it++)
+ setCell (&iter, i++, *it);
+ if (item->selected())
+ focusItem (item, true);
+ }
+ else
+ yuiError() << "Can only add YTableItems to a YTable.\n";
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ { focusItem (item, select); }
+
+ void doDeselectAllItems()
+ { unfocusAllItems(); }
+
+ // callbacks
+
+ static void activateButton (YWidget *button)
+ {
+ YWidgetEvent *event = new YWidgetEvent (button, YEvent::Activated);
+ YGUI::ui()->sendEvent (event);
+ }
+
+ static void hack_right_click_cb (YGtkTreeView *view, gboolean outreach, YGTable *pThis)
+ {
+ if (pThis->notifyContextMenu())
+ return YGTreeView::right_click_cb (view, outreach, pThis);
+
+ // If no context menu is specified, hack one ;-)
+
+ struct inner {
+ static void key_activate_cb (GtkMenuItem *item, YWidget *button)
+ { activateButton (button); }
+ static void appendItem (GtkWidget *menu, const gchar *stock, int key)
+ {
+ YWidget *button = YGDialog::currentDialog()->getFunctionWidget (key);
+ if (button) {
+ GtkWidget *item;
+ item = gtk_image_menu_item_new_from_stock (stock, NULL);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (key_activate_cb), button);
+ }
+ }
+ };
+
+ GtkWidget *menu = gtk_menu_new();
+ YGDialog *dialog = YGDialog::currentDialog();
+ if (dialog->getClassWidgets ("YTable").size() == 1) {
+ // if more than one table exists, function keys would be ambiguous
+ if (outreach) {
+ if (dialog->getFunctionWidget(3))
+ inner::appendItem (menu, GTK_STOCK_ADD, 3);
+ }
+ else {
+ if (dialog->getFunctionWidget(4))
+ inner::appendItem (menu, GTK_STOCK_EDIT, 4);
+ if (dialog->getFunctionWidget(5))
+ inner::appendItem (menu, GTK_STOCK_DELETE, 5);
+ }
+ }
+
+ menu = ygtk_tree_view_append_show_columns_item (YGTK_TREE_VIEW (view), menu);
+ ygtk_tree_view_popup_menu (view, menu);
+ }
+
+ static gboolean key_press_event_cb (GtkWidget *widget, GdkEventKey *event, YGTable *pThis)
+ {
+ if (event->keyval == GDK_Delete) {
+ YWidget *button = YGDialog::currentDialog()->getFunctionWidget (5);
+ if (button)
+ activateButton (button);
+ else
+ gtk_widget_error_bell (widget);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ static gint tree_sort_cb (
+ GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer _index)
+ {
+ int index = GPOINTER_TO_INT (_index);
+ gchar *str_a, *str_b;
+ gtk_tree_model_get (model, a, index, &str_a, -1);
+ gtk_tree_model_get (model, b, index, &str_b, -1);
+ if (!str_a) str_a = g_strdup ("");
+ if (!str_b) str_b = g_strdup ("");
+ int ret = strcmp (str_a, str_b);
+ g_free (str_a); g_free (str_b);
+ return ret;
+ }
+
+ YGLABEL_WIDGET_IMPL (YTable)
+ YGSELECTION_WIDGET_IMPL (YTable)
+};
+
+YTable *YGWidgetFactory::createTable (YWidget *parent, YTableHeader *headers,
+ bool multiSelection)
+{
+ return new YGTable (parent, headers, multiSelection);
+}
+
+#include "YSelectionBox.h"
+
+class YGSelectionBox : public YSelectionBox, public YGTreeView
+{
+public:
+ YGSelectionBox (YWidget *parent, const string &label)
+ : YSelectionBox (NULL, label),
+ YGTreeView (this, parent, label, false)
+ {
+ GType types [2] = { GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ addTextColumn (0, 1);
+ createStore (2, types);
+ readModel();
+ }
+
+ // YGTreeView
+
+ virtual bool _shrinkable() { return shrinkable(); }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *item)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ setRowText (&iter, 0, item->iconName(), 1, item->label(), this);
+ if (item->selected())
+ focusItem (item, true);
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ { focusItem (item, select); }
+
+ void doDeselectAllItems()
+ { unfocusAllItems(); }
+
+ YGLABEL_WIDGET_IMPL (YSelectionBox)
+ YGSELECTION_WIDGET_IMPL (YSelectionBox)
+};
+
+YSelectionBox *YGWidgetFactory::createSelectionBox (YWidget *parent, const string &label)
+{ return new YGSelectionBox (parent, label); }
+
+#include "YMultiSelectionBox.h"
+
+class YGMultiSelectionBox : public YMultiSelectionBox, public YGTreeView
+{
+public:
+ YGMultiSelectionBox (YWidget *parent, const string &label)
+ : YMultiSelectionBox (NULL, label),
+ YGTreeView (this, parent, label, false)
+ {
+ GType types [3] = { G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ addCheckColumn (0);
+ addTextColumn (1, 2);
+ createStore (3, types);
+ readModel();
+ addCountWidget (parent);
+ }
+
+ // YGTreeView
+
+ virtual bool _shrinkable() { return shrinkable(); }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *item)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter);
+ setRowMark (&iter, 0, item->selected());
+ setRowText (&iter, 1, item->iconName(), 2, item->label(), this);
+ syncCount();
+ }
+
+ void doSelectItem (YItem *item, bool select)
+ {
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ setRowMark (&iter, 0, select);
+ syncCount();
+ }
+
+ void doDeselectAllItems()
+ { unmarkAll(); syncCount(); }
+
+ // YMultiSelectionBox
+
+ virtual YItem *currentItem()
+ { return getFocusItem(); }
+
+ virtual void setCurrentItem (YItem *item)
+ { focusItem (item, true); }
+
+ YGLABEL_WIDGET_IMPL (YMultiSelectionBox)
+ YGSELECTION_WIDGET_IMPL (YMultiSelectionBox)
+};
+
+YMultiSelectionBox *YGWidgetFactory::createMultiSelectionBox (YWidget *parent, const string &label)
+{ return new YGMultiSelectionBox (parent, label); }
+
+#include "YTree.h"
+#include "YTreeItem.h"
+
+class YGTree : public YTree, public YGTreeView
+{
+public:
+#if YAST2_VERSION >= 2020003
+ YGTree (YWidget *parent, const string &label, bool multiselection, bool recursiveSelection)
+ : YTree (NULL, label, multiselection, recursiveSelection),
+#else
+#if YAST2_VERSION >= 2019002
+ YGTree (YWidget *parent, const string &label, bool multiselection)
+ : YTree (NULL, label, multiselection),
+#else
+ YGTree (YWidget *parent, const string &label)
+ : YTree (NULL, label),
+#endif
+#endif
+ YGTreeView (this, parent, label, true)
+ {
+#if YAST2_VERSION >= 2019002
+ if (multiselection) {
+ GType types [3] = { GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_BOOLEAN };
+ addCheckColumn (2);
+ addTextColumn (0, 1);
+ createStore (3, types);
+ addCountWidget (parent);
+ }
+ else
+#endif
+ {
+ GType types [2] = { GDK_TYPE_PIXBUF, G_TYPE_STRING };
+ addTextColumn (0, 1);
+ createStore (2, types);
+ }
+ readModel();
+
+ g_signal_connect (getWidget(), "row-collapsed", G_CALLBACK (row_collapsed_cb), this);
+ g_signal_connect (getWidget(), "row-expanded", G_CALLBACK (row_expanded_cb), this);
+ }
+
+#if YAST2_VERSION >= 2020003
+ virtual bool _recursiveSelection() { return recursiveSelection(); }
+#endif
+
+ void addNode (YItem *item, GtkTreeIter *parent)
+ {
+ GtkTreeIter iter;
+ addRow (item, &iter, parent);
+ setRowText (&iter, 0, item->iconName(), 1, item->label(), this);
+#if 0 // yast2-qt ignores `selected flag
+ if (item->selected()) {
+#if YAST2_VERSION >= 2019002
+ if (hasMultiSelection())
+ setRowMark (&iter, 2, item->selected());
+ else
+#endif
+ focusItem (item, true);
+ }
+#endif
+#if 0
+ if (((YTreeItem *) item)->isOpen())
+ expand (&iter);
+#endif
+ for (YItemConstIterator it = item->childrenBegin();
+ it != item->childrenEnd(); it++)
+ addNode (*it, &iter);
+ }
+
+#if 0
+ void expand (GtkTreeIter *iter)
+ {
+ GtkTreePath *path = gtk_tree_model_get_path (getModel(), iter);
+ gtk_tree_view_expand_row (getView(), path, FALSE);
+ gtk_tree_path_free (path);
+ }
+
+ bool isReallyOpen (YTreeItem *item) // are parents open as well?
+ {
+ for (YTreeItem *i = item; i; i = i->parent())
+ if (!i->isOpen())
+ return false;
+ return true;
+ }
+#endif
+
+ // YTree
+
+ virtual void rebuildTree()
+ {
+ blockSelected();
+
+ doDeleteAllItems();
+ for (YItemConstIterator it = YTree::itemsBegin(); it != YTree::itemsEnd(); it++)
+ addNode (*it, NULL);
+
+ int depth = getTreeDepth();
+ gtk_tree_view_set_show_expanders (getView(), depth > 1);
+ gtk_tree_view_set_enable_tree_lines (getView(), depth > 3);
+
+ // for whatever reason, we need to expand nodes only after the model
+ // is fully initialized
+ struct inner {
+ static gboolean foreach_sync_open (
+ GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer _pThis)
+ {
+ YGTree *pThis = (YGTree *) _pThis;
+ YTreeItem *item = (YTreeItem *) pThis->getYItem (iter);
+ if (item->isOpen())
+ gtk_tree_view_expand_row (pThis->getView(), path, FALSE);
+ return FALSE;
+ }
+ };
+
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) row_expanded_cb, this);
+ gtk_tree_model_foreach (getModel(), inner::foreach_sync_open, this);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) row_expanded_cb, this);
+
+ syncCount();
+ }
+
+ virtual YTreeItem *currentItem()
+ { return (YTreeItem *) getFocusItem(); }
+
+ void _markItem (YItem *item, bool select, bool recursive) {
+ GtkTreeIter iter;
+ getTreeIter (item, &iter);
+ setRowMark (&iter, 2, select);
+
+ if (recursive) {
+ YTreeItem *_item = (YTreeItem *) item;
+ for (YItemConstIterator it = _item->childrenBegin();
+ it != _item->childrenEnd(); it++)
+ _markItem (*it, select, true);
+ }
+ }
+
+ // YGSelectionStore
+
+ void doAddItem (YItem *item) {} // rebuild will be called anyway
+
+ void doSelectItem (YItem *item, bool select)
+ {
+#if YAST2_VERSION >= 2019002
+ if (hasMultiSelection()) {
+#if YAST2_VERSION >= 2020003
+ _markItem (item, select, recursiveSelection());
+#else
+ _markItem (item, select, false);
+#endif
+ syncCount();
+ }
+ else
+#endif
+ focusItem (item, select);
+ }
+
+ void doDeselectAllItems()
+ {
+#if YAST2_VERSION >= 2019002
+ if (hasMultiSelection()) {
+ unmarkAll();
+ syncCount();
+ }
+ else
+#endif
+ unfocusAllItems();
+ }
+
+ // callbacks
+
+ void reportRowOpen (GtkTreeIter *iter, bool open)
+ {
+ YTreeItem *item = static_cast (getYItem (iter));
+ item->setOpen (open);
+ }
+
+ static void row_collapsed_cb (GtkTreeView *view, GtkTreeIter *iter,
+ GtkTreePath *path, YGTree *pThis)
+ { pThis->reportRowOpen (iter, false); }
+
+ static void row_expanded_cb (GtkTreeView *view, GtkTreeIter *iter,
+ GtkTreePath *path, YGTree *pThis)
+ { pThis->reportRowOpen (iter, true); }
+
+#if 0
+ // we do a bit of a work-around here to mimic -qt behavior... A node can
+ // be initialized as open, yet its parent, or some grand-parent, be closed.
+ // We thus honor the open state when its parent gets open.
+ YTreeItem *item = static_cast (pThis->getYItem (iter));
+ for (YItemConstIterator it = item->childrenBegin();
+ it != item->childrenEnd(); it++) {
+ const YTreeItem *child = static_cast (*it);
+ if (child->isOpen()) {
+ GtkTreeIter iter;
+ if (pThis->getIter (child, &iter))
+ pThis->expand (&iter);
+ }
+ }
+#endif
+
+ YGLABEL_WIDGET_IMPL (YTree)
+ YGSELECTION_WIDGET_IMPL (YTree)
+};
+
+#if YAST2_VERSION >= 2020003
+YTree *YGWidgetFactory::createTree (YWidget *parent, const string &label, bool multiselection, bool recursiveSelection)
+{ return new YGTree (parent, label, multiselection, recursiveSelection); }
+#else
+#if YAST2_VERSION >= 2019002
+YTree *YGWidgetFactory::createTree (YWidget *parent, const string &label, bool multiselection)
+{ return new YGTree (parent, label, multiselection); }
+#else
+YTree *YGWidgetFactory::createTree (YWidget *parent, const string &label)
+{ return new YGTree (parent, label); }
+#endif
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,652 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/*
+ Textdomain "gtk"
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "YGUI.h"
+#include "YGi18n.h"
+#include "YGUtils.h"
+#include "YGDialog.h"
+#include
+
+static std::string askForFileOrDirectory (GtkFileChooserAction action,
+ const std::string &path, const std::string &filter, const std::string &title);
+
+static void errorMsg (const char *msg)
+{
+ GtkWidget* dialog = gtk_message_dialog_new (NULL,
+ GtkDialogFlags (0), GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), msg);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+#define DEFAULT_MACRO_FILE_NAME "macro.ycp"
+#define BUSY_CURSOR_TIMEOUT 250
+
+YUI *createUI( bool withThreads )
+{
+ static YGUI *ui = 0;
+ if (!ui)
+ ui = new YGUI (withThreads);
+ return ui;
+}
+
+YGUI::YGUI (bool with_threads)
+ : YUI (with_threads), m_done_init (false), busy_timeout (0)
+{
+ m_no_border = m_fullscreen = m_swsingle = false;
+
+ YGUI::setTextdomain( TEXTDOMAIN );
+
+ // If we're running without threads, initialize Gtk stuff
+ // This enables standalone libyui use Gtk interface
+ if (!with_threads)
+ checkInit();
+
+ // without this none of the (default) threading action works ...
+ topmostConstructorHasFinished();
+}
+
+void YGUI::setTextdomain( const char * domain )
+{
+ bindtextdomain( domain, LOCALEDIR );
+ bind_textdomain_codeset( domain, "utf8" );
+ textdomain( domain );
+
+ // Make change known.
+ {
+ extern int _nl_msg_cat_cntr;
+ ++_nl_msg_cat_cntr;
+ }
+}
+
+static void print_log (const gchar *domain, GLogLevelFlags level, const gchar *message, void *pData)
+{
+ YUILogLevel_t ylevel = YUI_LOG_MILESTONE;
+ switch (level) {
+ case G_LOG_LEVEL_ERROR:
+ case G_LOG_LEVEL_CRITICAL:
+ ylevel = YUI_LOG_ERROR;
+ break;
+ case G_LOG_LEVEL_WARNING:
+ ylevel = YUI_LOG_WARNING;
+ break;
+ case G_LOG_LEVEL_DEBUG:
+ ylevel = YUI_LOG_DEBUG;
+ break;
+ case G_LOG_LEVEL_MESSAGE:
+ case G_LOG_LEVEL_INFO:
+ default:
+ break;
+ }
+ // YUILog.cc assumes 'logComponent' (etc.) are static strings, that it
+ // can just keep lying around for ever, and use later, so we have to
+ // intern the domain - that can be allocated (or belong to a transient
+ // plugin's address space).
+ const char *component = domain ? g_intern_string (domain) : "yast2-gtk";
+ YUILog::instance()->log (ylevel, component, "yast2-gtk", 0, "") << message << std::endl;
+#if 0 // uncomment to put a stop to gdb
+ static int bugStop = 0;
+ if (bugStop-- <= 0)
+ abort();
+#endif
+}
+
+void YGUI::checkInit()
+{
+ if (m_done_init)
+ return;
+ m_done_init = true;
+
+ // retrieve command line args from /proc/<pid>/cmdline
+ YCommandLine cmdLine;
+ int argc = cmdLine.argc();
+ char **argv = cmdLine.argv();
+ for (int i = 1; i < argc; i++) {
+ const char *argp = argv[i];
+ if (argp[0] != '-') {
+ if (!strcmp (argp, "sw_single") || !strcmp (argp, "online_update"))
+ m_swsingle = true;
+ continue;
+ }
+ argp++;
+ if (argp[0] == '-') argp++;
+
+ if (!strcmp (argp, "fullscreen"))
+ m_fullscreen = true;
+ else if (!strcmp (argp, "noborder"))
+ m_no_border = true;
+ else if (!strcmp (argp, "help")) {
+ printf (
+ _("Command line options for the YaST2 UI (GTK plugin):\n\n"
+ "--noborder no window manager border for main dialogs\n"
+ "--fullscreen use full screen for main dialogs\n"
+ "--nothreads run without additional UI threads\n"
+ "--help prints this help text\n"
+ "\n"
+ ));
+ exit (0);
+ }
+ }
+
+ gtk_init (&argc, &argv);
+
+ g_log_set_default_handler (print_log, NULL); // send gtk logs to libyui system
+#if 0 // to crash right away in order to get a stack trace
+ g_log_set_always_fatal (GLogLevelFlags (G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|
+ G_LOG_LEVEL_WARNING| G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG));
+#endif
+
+ GdkPixbuf *pixbuf = YGUtils::loadPixbuf (THEMEDIR "/icons/32x32/apps/yast.png");
+ if (pixbuf) { // default window icon
+ gtk_window_set_default_icon (pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+}
+
+static gboolean ycp_wakeup_fn (GIOChannel *source, GIOCondition condition,
+ gpointer data)
+{
+ *(int *)data = TRUE;
+ return TRUE;
+}
+
+void YGUI::idleLoop (int fd_ycp)
+{
+ // The rational for this is that we need somewhere to run
+ // the magic 'main' thread, that can process thread unsafe
+ // incoming CORBA messages for us
+ checkInit();
+
+ GIOChannel *wakeup;
+ wakeup = g_io_channel_unix_new (fd_ycp);
+ g_io_channel_set_encoding (wakeup, NULL, NULL);
+ g_io_channel_set_buffered (wakeup, FALSE);
+
+ int woken = FALSE;
+ guint watch_tag = g_io_add_watch (wakeup, (GIOCondition)(G_IO_IN | G_IO_PRI),
+ ycp_wakeup_fn, &woken);
+ while (!woken)
+ g_main_context_iteration (NULL, TRUE);
+
+ g_source_remove (watch_tag);
+ g_io_channel_unref (wakeup);
+}
+
+static gboolean user_input_timeout_cb (YGUI *pThis)
+{
+ if (!pThis->pendingEvent())
+ pThis->sendEvent (new YTimeoutEvent());
+ return FALSE;
+}
+
+// utility that implements both userInput() and pollInput()
+YEvent *YGUI::waitInput (unsigned long timeout_ms, bool block)
+{
+ checkInit();
+ if (!YDialog::currentDialog (false))
+ return NULL;
+
+ if (block)
+ normalCursor(); // waiting for input, so no more busy
+
+ guint timeout = 0;
+
+ if (timeout_ms > 0)
+ timeout = g_timeout_add (timeout_ms,
+ (GSourceFunc) user_input_timeout_cb, this);
+
+ if (block) {
+ while (!pendingEvent())
+ g_main_context_iteration (NULL, TRUE);
+ }
+ else
+ while (g_main_context_iteration (NULL, FALSE)) ;
+
+ YEvent *event = NULL;
+ if (pendingEvent())
+ event = m_event_handler.consumePendingEvent();
+
+ if (timeout)
+ g_source_remove (timeout);
+
+ if (block) { // if YCP keeps working for more than X time, set busy cursor
+ if (busy_timeout)
+ g_source_remove (busy_timeout);
+ busy_timeout = g_timeout_add (BUSY_CURSOR_TIMEOUT, busy_timeout_cb, this);
+ }
+ return event;
+}
+
+void YGUI::sendEvent (YEvent *event)
+{
+ m_event_handler.sendEvent (event);
+ g_main_context_wakeup (NULL);
+}
+
+gboolean YGUI::busy_timeout_cb (gpointer data)
+{
+ YGUI *pThis = (YGUI *) data;
+ pThis->busyCursor();
+ pThis->busy_timeout = 0;
+ return FALSE;
+}
+
+void YGUI::busyCursor()
+{
+ YGDialog *dialog = YGDialog::currentDialog();
+ if (dialog)
+ dialog->busyCursor();
+}
+
+void YGUI::normalCursor()
+{
+ if (busy_timeout) {
+ g_source_remove (busy_timeout);
+ busy_timeout = 0;
+ }
+
+ YGDialog *dialog = YGDialog::currentDialog();
+ if (dialog)
+ dialog->normalCursor();
+}
+
+void YGUI::makeScreenShot()
+{ ((YGApplication *) app())->makeScreenShot (""); }
+
+YEvent *YGUI::runPkgSelection (YWidget *packageSelector)
+{
+ yuiMilestone() << "Running package selection...\n";
+ YEvent *event = 0;
+
+ try {
+ event = packageSelector->findDialog()->waitForEvent();
+ } catch (const std::exception &e) {
+ yuiError() << "UI::RunPkgSelection() error: " << e.what() << endl;
+ yuiError() << "This is a libzypp problem. Do not file a bug against the UI!\n";
+ } catch (...) {
+ yuiError() << "UI::RunPkgSelection() error (unspecified)\n";
+ yuiError() << "This is a libzypp problem. Do not file a bug against the UI!\n";
+ }
+ return event;
+}
+
+void YGUI::askPlayMacro()
+{
+ string filename = askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_OPEN,
+ DEFAULT_MACRO_FILE_NAME, "*.ycp", _("Open Macro file"));
+ if (!filename.empty()) {
+ busyCursor();
+ YMacro::play (filename);
+ sendEvent (new YEvent()); // flush
+ }
+}
+
+void YGUI::toggleRecordMacro()
+{
+ if (YMacro::recording()) {
+ YMacro::endRecording();
+ normalCursor();
+
+ GtkWidget* dialog = gtk_message_dialog_new (NULL,
+ GtkDialogFlags (0), GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
+ _("Macro recording done."));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+ else {
+ string filename = askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE,
+ DEFAULT_MACRO_FILE_NAME, "*.ycp", _("Save Macro"));
+ if (!filename.empty())
+ YMacro::record (filename);
+ }
+}
+
+void YGUI::askSaveLogs()
+{
+ string filename = askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE,
+ "/tmp/y2logs.tgz", "*.tgz *.tar.gz", _("Save y2logs"));
+ if (!filename.empty()) {
+ std::string command = "/sbin/save_y2logs";
+ command += " '" + filename + "'";
+ yuiMilestone() << "Saving y2logs: " << command << endl;
+ int ret = system (command.c_str());
+ if (ret == 0)
+ yuiMilestone() << "y2logs saved to " << filename << endl;
+ else {
+ char *error = g_strdup_printf (
+ _("Could not run: '%s' (exit value: %d)"),
+ command.c_str(), ret);
+ yuiError() << error << endl;
+ errorMsg (error);
+ g_free (error);
+ }
+ }
+}
+
+//** YGApplication
+
+#define ICONDIR THEMEDIR "/icons/22x22/apps/"
+
+YGApplication::YGApplication()
+{
+ setIconBasePath (ICONDIR);
+}
+
+void YGApplication::makeScreenShot (const std::string &_filename)
+{
+ std::string filename (_filename);
+ bool interactive = filename.empty();
+
+ GtkWidget *widget = GTK_WIDGET (YGDialog::currentWindow());
+ if (!widget) {
+ if (interactive)
+ errorMsg (_("No dialog to take screenshot of."));
+ return;
+ }
+
+ GError *error = 0;
+ GdkPixbuf *shot =
+ gdk_pixbuf_get_from_drawable (NULL, GDK_DRAWABLE (widget->window),
+ gdk_colormap_get_system(), 0, 0, 0, 0, widget->allocation.width,
+ widget->allocation.height);
+
+ if (!shot) {
+ if (interactive)
+ errorMsg (_("Could not take screenshot."));
+ return;
+ }
+
+ if (interactive) {
+ //** ask user for filename
+ // calculate a default directory...
+ if (screenShotNameTemplate.empty()) {
+ string dir;
+ const char *homedir = getenv("HOME");
+ const char *ssdir = getenv("Y2SCREENSHOTS");
+ if (!homedir || !strcmp (homedir, "/")) {
+ // no homedir defined (installer)
+ dir = "/tmp/" + (ssdir ? (string(ssdir)) : (string("")));
+ if (mkdir (dir.c_str(), 0700) == -1)
+ dir = "";
+ }
+ else {
+ dir = homedir + (ssdir ? ("/" + string(ssdir)) : (string("")));
+ mkdir (dir.c_str(), 0750); // create a dir for what to put the pics
+ }
+
+ screenShotNameTemplate = dir + "/%s-%03d.png";
+ }
+
+ // calculate a default filename...
+ const char *baseName = "yast2-";
+
+ int nb;
+ map ::iterator it = screenShotNb.find (baseName);
+ if (it == screenShotNb.end())
+ nb = 0;
+
+ {
+ char *tmp_name = g_strdup_printf (screenShotNameTemplate.c_str(), baseName, nb);
+ filename = tmp_name;
+ g_free (tmp_name);
+ }
+ yuiDebug() << "screenshot: " << filename << endl;
+
+ filename = askForFileOrDirectory (
+ GTK_FILE_CHOOSER_ACTION_SAVE, "", "*.png", _("Save screenshot"));
+ if (filename.empty()) { // user dismissed the dialog
+ yuiDebug() << "Save screen shot canceled by user\n";
+ goto makeScreenShot_ret;
+ }
+
+ screenShotNb.erase (baseName);
+ screenShotNb[baseName] = nb + 1;
+ }
+
+ yuiDebug() << "Saving screen shot to " << filename << endl;
+ if (!gdk_pixbuf_save (shot, filename.c_str(), "png", &error, NULL)) {
+ string msg = _("Could not save to:");
+ msg += " "; msg += filename;
+ if (error) {
+ msg += "\n"; msg += "\n";
+ msg += error->message;
+ }
+ yuiError() << msg << endl;
+ if (interactive)
+ errorMsg (msg.c_str());
+ goto makeScreenShot_ret;
+ }
+
+ makeScreenShot_ret:
+ g_object_unref (G_OBJECT (shot));
+}
+
+void YGApplication::beep()
+{
+ GtkWindow *window = YGDialog::currentWindow();
+ if (window) {
+ gtk_window_present (window);
+ gtk_widget_error_bell (GTK_WIDGET (window));
+ }
+ else
+ gdk_beep();
+}
+
+// File/directory dialogs
+#include <sstream>
+
+std::string askForFileOrDirectory (GtkFileChooserAction action,
+ const std::string &path, const std::string &filter, const std::string &title)
+{
+ GtkWindow *parent = YGDialog::currentWindow();
+ const char *button;
+ switch (action) {
+ case GTK_FILE_CHOOSER_ACTION_SAVE:
+ button = GTK_STOCK_SAVE; break;
+ case GTK_FILE_CHOOSER_ACTION_OPEN:
+ button = GTK_STOCK_OPEN; break;
+ case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
+ case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ button = _("Select"); break;
+ }
+ GtkWidget *dialog;
+ dialog = gtk_file_chooser_dialog_new (title.c_str(),
+ parent, action, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ button, GTK_RESPONSE_ACCEPT, NULL);
+ GtkFileChooser *fileChooser = GTK_FILE_CHOOSER (dialog);
+ gtk_file_chooser_set_local_only (fileChooser, TRUE);
+ gtk_file_chooser_set_do_overwrite_confirmation (fileChooser, TRUE);
+
+ // filepath can be a dir or a file path, split that up
+ string dirname, filename;
+ if (!path.empty()) {
+ if (path[0] != '/')
+ yuiWarning() << "FileDialog: Relative paths are not supported: '" << path << "'\n";
+ else if (!g_file_test (path.c_str(), G_FILE_TEST_EXISTS))
+ yuiWarning() << "FileDialog: Path doesn't exist: '" << path << "'\n";
+ else if (g_file_test (path.c_str(), G_FILE_TEST_IS_DIR))
+ dirname = path;
+ else { // its a file
+ string::size_type i = path.find_last_of ("/");
+ if (i != string::npos) {
+ dirname = path.substr (0, i+1);
+ filename = path.substr (i+1);
+ }
+ }
+ }
+
+ if (!dirname.empty())
+ gtk_file_chooser_set_current_folder (fileChooser, dirname.c_str());
+ if (!filename.empty())
+ gtk_file_chooser_set_current_name (fileChooser, filename.c_str());
+
+ if (!filter.empty() && filter != "*") {
+ GtkFileFilter *gtk_filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (gtk_filter, filter.c_str());
+ // cut filter_pattern into chuncks like GTK likes
+ std::istringstream stream (filter);
+ while (!stream.eof()) {
+ string str;
+ stream >> str;
+ if (!str.empty() && str [str.size()-1] == ',')
+ str.erase (str.size()-1);
+ gtk_file_filter_add_pattern (gtk_filter, str.c_str());
+ }
+ gtk_file_chooser_add_filter (fileChooser, gtk_filter);
+ }
+
+ // bug 335492: because "/" gets hidden as a an arrow at the top, make sure
+ // there is a root shortcut at the side pane (will not add if already exists)
+ gtk_file_chooser_add_shortcut_folder (fileChooser, "/", NULL);
+
+ std::string ret;
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+ gchar *filename = gtk_file_chooser_get_filename (fileChooser);
+ if (filename) {
+ ret = filename;
+ g_free (filename);
+ }
+ }
+ gtk_widget_destroy (dialog);
+ return ret;
+}
+
+std::string YGApplication::askForExistingDirectory (
+ const std::string &path, const std::string &title)
+{ return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, path, "", title); }
+
+std::string YGApplication::askForExistingFile (
+ const std::string &path, const std::string &filter, const std::string &title)
+{ return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_OPEN, path, filter, title); }
+
+std::string YGApplication::askForSaveFileName (
+ const std::string &path, const std::string &filter, const std::string &title)
+{ return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE, path, filter, title); }
+
+std::string YGApplication::glyph (const std::string &sym)
+{
+ bool reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
+ if (sym == YUIGlyph_ArrowLeft)
+ return reverse ? "\u25b6" : "\u25c0";
+ if (sym == YUIGlyph_ArrowRight)
+ return reverse ? "\u25c0" : "\u25b6";
+ if (sym == YUIGlyph_ArrowUp)
+ return "\u25b2";
+ if (sym == YUIGlyph_ArrowDown)
+ return "\u25bc";
+ if (sym == YUIGlyph_CheckMark)
+ return "\u2714";
+ if (sym == YUIGlyph_BulletArrowRight)
+ return reverse ? "\u21e6" : "\u279c";
+ if (sym == YUIGlyph_BulletCircle)
+ return "\u26ab";
+ if (sym == YUIGlyph_BulletSquare)
+ return "\u25fe";
+ return "";
+}
+
+// YWidget layout units -> pixels conversion. Same as yast-qt's.
+int YGApplication::deviceUnits (YUIDimension dim, float size)
+{
+ if (dim == YD_HORIZ)
+ size *= 640.0 / 80;
+ else
+ size *= 480.0 / 25;
+ return size + 0.5;
+}
+
+float YGApplication::layoutUnits (YUIDimension dim, int units)
+{
+ float size = (float) units;
+ if (dim == YD_HORIZ) return size * (80/640.0);
+ else return size * (25/480.0);
+}
+
+static inline GdkScreen *getScreen ()
+{ return gdk_display_get_default_screen (gdk_display_get_default()); }
+// GTK doesn't seem to have some desktopWidth/Height like Qt, so we to report
+// a reduced display size to compensate for the panel, or the window frame
+int YGApplication::displayWidth()
+{ return gdk_screen_get_width (getScreen()) - 80; }
+int YGApplication::displayHeight()
+{ return gdk_screen_get_height (getScreen()) - 80; }
+
+int YGApplication::displayDepth()
+{ return gdk_visual_get_best_depth(); }
+
+long YGApplication::displayColors()
+{ return 1L << displayDepth(); /*from yast-qt*/ }
+
+// YCP uses defaultWidth/Height() to use their smaller YWizard impl; we
+// want to use a smaller default size than qt though, so assume a bigger size
+int YGApplication::defaultWidth() { return MIN (displayWidth(), 1024); }
+int YGApplication::defaultHeight() { return MIN (displayHeight(), 768); }
+
+YWidgetFactory *YGUI::createWidgetFactory()
+{ return new YGWidgetFactory; }
+YOptionalWidgetFactory *YGUI::createOptionalWidgetFactory()
+{ return new YGOptionalWidgetFactory; }
+YApplication *YGUI::createApplication()
+{ return new YGApplication(); }
+
+#include
+#include "ygtktextview.h"
+
+void dumpYastHtml (YWidget *widget)
+{
+ struct inner {
+ static void dumpYastHtml (YWidget *widget, GtkBox *box)
+ {
+ YGWidget *ygwidget;
+ if (!widget || !(ygwidget = YGWidget::get (widget)))
+ return;
+
+ YRichText *rtext = dynamic_cast (widget);
+ if (rtext) {
+ std::string text = rtext->text();
+
+ GtkWidget *view = ygtk_text_view_new (FALSE);
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ gtk_text_buffer_set_text (buffer, text.c_str(), -1);
+
+ GtkWidget *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_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (scroll), view);
+ gtk_box_pack_start (box, scroll, TRUE, TRUE, 6);
+ }
+
+ for (YWidgetListConstIterator it = widget->childrenBegin();
+ it != widget->childrenEnd(); it++)
+ dumpYastHtml (*it, box);
+ }
+ static void destroy_dialog (GtkDialog *dialog, gint arg)
+ { gtk_widget_destroy (GTK_WIDGET (dialog)); }
+ };
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons ("YWidgets HTML", NULL,
+ GtkDialogFlags (GTK_DIALOG_NO_SEPARATOR), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300);
+
+ inner::dumpYastHtml (widget, GTK_BOX (GTK_DIALOG (dialog)->vbox));
+
+ gtk_widget_show_all (dialog);
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (inner::destroy_dialog), 0);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUI.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,240 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGUI_H
+#define YGUI_H
+
+#include "config.h"
+#include
+#define YUILogComponent "gtk"
+#include
+#include
+#include <map>
+#include
+
+/* Comment the following line to disable debug messages */
+#define RET(a) { return (a); }
+
+class YGUI: public YUI
+{
+public:
+ YGUI (bool with_threads);
+ void checkInit(); // called 1st time when execution thread kicks in
+
+ static YGUI *ui() { return (YGUI *) YUI::ui(); }
+
+protected:
+ virtual YWidgetFactory *createWidgetFactory();
+ virtual YOptionalWidgetFactory *createOptionalWidgetFactory();
+ virtual YApplication *createApplication();
+
+public:
+ static void setTextdomain (const char *domain);
+
+ virtual void idleLoop (int fd_ycp);
+ // called by YDialog::waitInput() / pollEvent()...
+ YEvent *waitInput (unsigned long timeout_ms, bool block);
+
+ virtual YEvent *runPkgSelection (YWidget *packageSelector);
+
+ // used internally: for public use, see YApplication
+ void busyCursor();
+ void normalCursor();
+ void makeScreenShot();
+
+ // Plays a macro, opening a dialog first to ask for the filename
+ // activated by Ctrl-Shift-Alt-P
+ void askPlayMacro();
+ void toggleRecordMacro();
+
+ // On Shift-F8, run save_logs
+ void askSaveLogs();
+
+ YSimpleEventHandler m_event_handler;
+ void sendEvent (YEvent *event);
+ YEvent *pendingEvent() const { return m_event_handler.pendingEvent(); }
+ bool eventPendingFor (YWidget *widget) const
+ { return m_event_handler.eventPendingFor (widget); }
+
+private:
+ bool m_done_init;
+ guint busy_timeout; // for busy cursor
+ static gboolean busy_timeout_cb (gpointer data);
+
+ // window-related arguments
+ bool m_no_border, m_fullscreen, m_swsingle;
+
+public:
+ // Helpers for internal use [ visibility hidden ]
+ bool setFullscreen() const { return m_fullscreen; }
+ bool unsetBorder() const { return m_no_border; }
+ bool isSwsingle() const { return m_swsingle; }
+};
+
+// debug helpers.
+void dumpTree (YWidget *widget);
+void dumpYastHtml (YWidget *widget);
+
+#include
+
+class YGWidgetFactory : public YWidgetFactory
+{
+ virtual YDialog *createDialog (YDialogType dialogType, YDialogColorMode colorMode);
+
+ virtual YPushButton *createPushButton (YWidget *parent, const string &label);
+ virtual YLabel *createLabel (YWidget *parent, const string &text, bool isHeading, bool isOutputField);
+ virtual YInputField *createInputField (YWidget *parent, const string &label, bool passwordMode);
+ virtual YCheckBox *createCheckBox (YWidget *parent, const string &label, bool isChecked);
+ virtual YRadioButton *createRadioButton (YWidget *parent, const string &label, bool isChecked);
+ virtual YComboBox *createComboBox (YWidget *parent, const string & label, bool editable);
+ virtual YSelectionBox *createSelectionBox (YWidget *parent, const string &label);
+#if YAST2_VERSION >= 2020003
+ virtual YTree *createTree (YWidget *parent, const string &label, bool multiselection, bool recursiveSelection);
+#else
+#if YAST2_VERSION >= 2019002
+ virtual YTree *createTree (YWidget *parent, const string &label, bool multiselection);
+#else
+ virtual YTree *createTree (YWidget *parent, const string &label);
+#endif
+#endif
+ virtual YTable *createTable (YWidget *parent, YTableHeader *headers, bool multiSelection);
+ virtual YProgressBar *createProgressBar (YWidget *parent, const string &label, int maxValue);
+ virtual YBusyIndicator *createBusyIndicator (YWidget *parent, const string &label, int timeout);
+ virtual YRichText *createRichText (YWidget *parent, const string &text, bool plainTextMode);
+
+ virtual YIntField *createIntField (YWidget *parent, const string &label, int minVal, int maxVal, int initialVal);
+ virtual YMenuButton *createMenuButton (YWidget *parent, const string &label);
+ virtual YMultiLineEdit *createMultiLineEdit (YWidget *parent, const string &label);
+ virtual YImage *createImage (YWidget *parent, const string &imageFileName, bool animated);
+ virtual YLogView *createLogView (YWidget *parent, const string &label, int visibleLines, int storedLines);
+ virtual YMultiSelectionBox *createMultiSelectionBox (YWidget *parent, const string &label);
+
+ virtual YPackageSelector *createPackageSelector (YWidget * parent, long ModeFlags);
+ virtual YWidget *createPkgSpecial (YWidget * parent, const string & subwidgetName) RET (NULL) // for ncurses
+
+ virtual YLayoutBox *createLayoutBox (YWidget *parent, YUIDimension dimension);
+ virtual YButtonBox *createButtonBox (YWidget *parent);
+
+ virtual YSpacing *createSpacing (YWidget *parent, YUIDimension dim, bool stretchable, YLayoutSize_t size);
+ virtual YEmpty *createEmpty (YWidget *parent);
+ virtual YAlignment *createAlignment (YWidget *parent, YAlignmentType horAlignment, YAlignmentType vertAlignment);
+ virtual YSquash *createSquash (YWidget *parent, bool horSquash, bool vertSquash);
+
+ virtual YFrame *createFrame (YWidget *parent, const string &label);
+ virtual YCheckBoxFrame *createCheckBoxFrame (YWidget *parent, const string &label, bool checked);
+
+ virtual YRadioButtonGroup *createRadioButtonGroup (YWidget *parent);
+ virtual YReplacePoint *createReplacePoint (YWidget *parent);
+};
+
+#include
+
+class YGOptionalWidgetFactory : public YOptionalWidgetFactory
+{
+public:
+ virtual bool hasWizard() RET (true)
+ virtual YWizard *createWizard (YWidget *parent, const string &backButtonLabel,
+ const string &abortButtonLabel, const string &nextButtonLabel,
+ YWizardMode wizardMode);
+
+ virtual bool hasDumbTab() RET (true)
+ virtual YDumbTab *createDumbTab (YWidget *parent);
+
+ virtual bool hasSlider() RET (true)
+ virtual YSlider *createSlider (YWidget *parent, const string &label, int minVal,
+ int maxVal, int initialVal);
+
+ virtual bool hasDateField() RET (true)
+ virtual YDateField *createDateField (YWidget *parent, const string &label);
+
+ virtual bool hasTimeField() RET (true)
+ virtual YTimeField *createTimeField (YWidget *parent, const string &label);
+
+ virtual bool hasTimezoneSelector() RET (true)
+ virtual YTimezoneSelector *createTimezoneSelector (YWidget *parent,
+ const string &pixmap, const map &timezones);
+
+ virtual bool hasBarGraph() RET (true)
+ virtual YBarGraph *createBarGraph (YWidget *parent);
+
+ virtual bool hasMultiProgressMeter() RET (true)
+ virtual YMultiProgressMeter *createMultiProgressMeter (YWidget *parent,
+ YUIDimension dim, const vector<float> &maxValues);
+
+ virtual bool hasPartitionSplitter() RET (true)
+ virtual YPartitionSplitter *createPartitionSplitter (YWidget *parent,
+ int usedSize, int totalFreeSize, int newPartSize, int minNewPartSize,
+ int minFreeSize, const string &usedLabel, const string &freeLabel,
+ const string &newPartLabel, const string &freeFieldLabel,
+ const string &newPartFieldLabel);
+
+ virtual bool hasDownloadProgress() RET (true)
+ virtual YDownloadProgress *createDownloadProgress (YWidget *parent,
+ const string &label, const string & filename, YFileSize_t expectedFileSize);
+
+ virtual bool hasContextMenu() RET (true)
+
+ virtual bool hasSimplePatchSelector() RET (true)
+ virtual YWidget *createSimplePatchSelector (YWidget *parent, long modeFlags);
+ virtual bool hasPatternSelector() RET (true)
+ virtual YWidget *createPatternSelector (YWidget *parent, long modeFlags);
+};
+
+#include
+
+class YGApplication : public YApplication
+{
+public:
+ YGApplication();
+
+ virtual std::string glyph (const std::string &symbolName);
+
+ virtual std::string askForExistingDirectory (const std::string &startDir,
+ const std::string &headline);
+ virtual std::string askForExistingFile (const std::string &startWith,
+ const std::string &filter, const std::string &headline);
+ virtual std::string askForSaveFileName (const std::string &startWith,
+ const std::string &filter, const std::string &headline);
+
+ virtual void busyCursor() { YGUI::ui()->busyCursor(); }
+ virtual void normalCursor() { YGUI::ui()->normalCursor(); }
+
+ virtual void makeScreenShot (const std::string &filename);
+ virtual void beep();
+
+ virtual int deviceUnits (YUIDimension dim, float layout_units);
+ virtual float layoutUnits (YUIDimension dim, int device_units);
+
+ virtual int displayWidth();
+ virtual int displayHeight();
+ virtual int displayDepth();
+ virtual long displayColors();
+ virtual int defaultWidth(); // internally, use _defaultWidth / Height()
+ virtual int defaultHeight();
+
+ virtual bool isTextMode() RET (false)
+ virtual bool leftHandedMouse() RET (false)
+ virtual bool hasImageSupport() RET (true)
+ virtual bool hasLocalImageSupport() RET (true)
+ virtual bool hasAnimationSupport() RET (true)
+ virtual bool hasIconSupport() RET (true)
+ virtual bool hasFullUtf8Support() RET (true)
+#ifdef USE_WEBKIT
+ virtual bool richTextSupportsTable() RET (true)
+#else
+ virtual bool richTextSupportsTable() RET (false)
+#endif
+
+ virtual bool openContextMenu (const YItemCollection &itemCollection);
+
+private:
+ // for screenshots:
+ std::map screenShotNb;
+ std::string screenShotNameTemplate;
+};
+
+#undef RET
+
+#endif /*YGUI_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,869 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/*
+ Textdomain "gtk"
+ */
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include
+#include "YGUtils.h"
+#include "YGUI.h"
+#include "YGi18n.h"
+
+static inline void skipSpace (const char *instr, int *i)
+{ while (g_ascii_isspace (instr[*i])) (*i)++; }
+
+typedef struct {
+ GString *tag;
+ int tag_len : 31;
+ unsigned int early_closer : 1;
+} TagEntry;
+
+static TagEntry *
+tag_entry_new (GString *tag, int tag_len)
+{
+ static const char *early_closers[] = { "p", "li" };
+ TagEntry *entry = g_new (TagEntry, 1);
+ entry->tag = tag;
+ entry->tag_len = tag_len;
+ entry->early_closer = FALSE;
+
+ unsigned int i;
+ for (i = 0; i < G_N_ELEMENTS (early_closers); i++)
+ if (!g_ascii_strncasecmp (tag->str, early_closers[i], tag_len))
+ entry->early_closer = TRUE;
+ return entry;
+}
+
+static void
+tag_entry_free (TagEntry *entry)
+{
+ if (entry && entry->tag)
+ g_string_free (entry->tag, TRUE);
+ g_free (entry);
+}
+
+static void
+emit_unclosed_tags_for (GString *outp, GQueue *tag_queue, const char *tag_str, int tag_len)
+{
+ gboolean matched = FALSE;
+
+ // top-level tag ...
+ if (g_queue_is_empty (tag_queue))
+ return;
+
+ do {
+ TagEntry *last_entry = (TagEntry *)g_queue_pop_tail (tag_queue);
+ if (!last_entry)
+ break;
+
+ if (last_entry->tag_len != tag_len ||
+ g_ascii_strncasecmp (last_entry->tag->str, tag_str, tag_len)) {
+ /* different tag - emit a close ... */
+ g_string_append (outp, "");
+ g_string_append_len (outp, last_entry->tag->str, last_entry->tag_len);
+ g_string_append_c (outp, '>');
+ } else
+ matched = TRUE;
+
+ tag_entry_free (last_entry);
+ } while (!matched);
+}
+
+static gboolean
+check_early_close (GString *outp, GQueue *tag_queue, TagEntry *entry)
+{
+ TagEntry *last_tag;
+
+ // Early closers:
+ if (!entry->early_closer)
+ return FALSE;
+
+ last_tag = (TagEntry *) g_queue_peek_tail (tag_queue);
+ if (!last_tag || !last_tag->early_closer)
+ return FALSE;
+
+ if (entry->tag_len != last_tag->tag_len ||
+ g_ascii_strncasecmp (last_tag->tag->str, entry->tag->str, entry->tag_len))
+ return FALSE;
+
+ // Emit close & leave last tag on the stack
+
+ g_string_append (outp, "");
+ g_string_append_len (outp, entry->tag->str, entry->tag_len);
+ g_string_append_c (outp, '>');
+
+ return TRUE;
+}
+
+/* Some entities are translated by the xhtml parser, but not all... */
+typedef struct EntityMap {
+ const gchar *html, *text;
+} EntityMap;
+
+static const EntityMap entities[] = {
+ { "nbsp", " " },
+ { "product", 0 }, // dynamic
+};
+
+static const EntityMap *lookup_entity (const char *html)
+{
+ unsigned int i;
+ for (i = 0; i < sizeof (entities) / sizeof (EntityMap); i++)
+ if (!g_ascii_strncasecmp (html+1, entities[i].html, strlen (entities[i].html)))
+ return entities+i;
+ return NULL;
+}
+
+// We have to:
+// + rewrite <br> and <hr> tags
+// + deal with <a attrib=noquotes>
+gchar *ygutils_convert_to_xhtml (const char *instr)
+{
+ GString *outp = g_string_new ("");
+ GQueue *tag_queue = g_queue_new();
+ int i = 0;
+
+ gboolean allow_space = FALSE, pre_mode = FALSE;
+ skipSpace (instr, &i);
+
+ // we must add an outer tag to make GMarkup happy
+ g_string_append (outp, "<body>");
+
+ for (; instr[i] != '\0'; i++)
+ {
+ // Tag foo
+ if (instr[i] == '<') {
+ // ignore comments
+ if (strncmp (&instr[i], "<!--", 4) == 0) {
+ for (i += 3; instr[i] != '\0'; i++)
+ if (strncmp (&instr[i], "-->", 3) == 0) {
+ i += 2;
+ break;
+ }
+ continue;
+ }
+
+ gint j;
+ gboolean is_close = FALSE;
+ gboolean in_tag;
+ int tag_len;
+ GString *tag = g_string_sized_new (20);
+
+ i++;
+ skipSpace (instr, &i);
+
+ if (instr[i] == '/') {
+ i++;
+ is_close = TRUE;
+ }
+
+ skipSpace (instr, &i);
+
+ // find the tag name piece
+ in_tag = TRUE;
+ tag_len = 0;
+ for (; instr[i] != '>' && instr[i]; i++) {
+ if (in_tag) {
+ if (!g_ascii_isalnum(instr[i]))
+ in_tag = FALSE;
+ else
+ tag_len++;
+ }
+ g_string_append_c (tag, instr[i]);
+ }
+
+ // Unmatched tags
+ if (!is_close && tag_len == 2 &&
+ (!g_ascii_strncasecmp (tag->str, "hr", 2) ||
+ !g_ascii_strncasecmp (tag->str, "br", 2)) &&
+ tag->str[tag->len - 1] != '/')
+ g_string_append_c (tag, '/');
+
+ if (!g_ascii_strncasecmp (tag->str, "pre", 3))
+ pre_mode = !is_close;
+
+ // Add quoting for un-quoted attributes
+ unsigned int k;
+ for (k = 0; k < tag->len; k++) {
+ if (tag->str[k] == '=') {
+ gboolean unquote = tag->str[k+1] != '"';
+ if (unquote)
+ g_string_insert_c (tag, k+1, '"');
+ else
+ k++;
+ for (k++; tag->str[k]; k++) {
+ if (unquote && g_ascii_isspace (tag->str[k]))
+ break;
+ else if (!unquote && tag->str[k] == '"')
+ break;
+ }
+ if (unquote)
+ g_string_insert_c (tag, k, '"');
+ }
+ else
+ tag->str[k] = g_ascii_tolower (tag->str[k]);
+ }
+
+ // Is it an open or close ?
+ j = tag->len - 1;
+
+ while (j > 0 && g_ascii_isspace (tag->str[j])) j--;
+
+ gboolean is_open_close = (tag->str[j] == '/');
+ if (is_open_close)
+ ; // ignore it
+ else if (is_close)
+ emit_unclosed_tags_for (outp, tag_queue, tag->str, tag_len);
+ else {
+ TagEntry *entry = tag_entry_new (tag, tag_len);
+
+ entry->tag = tag;
+ entry->tag_len = tag_len;
+
+ if (!check_early_close (outp, tag_queue, entry))
+ g_queue_push_tail (tag_queue, entry);
+ else {
+ entry->tag = NULL;
+ tag_entry_free (entry);
+ }
+ }
+
+ g_string_append_c (outp, '<');
+ if (is_close)
+ g_string_append_c (outp, '/');
+ g_string_append_len (outp, tag->str, tag->len);
+ g_string_append_c (outp, '>');
+
+ if (is_close || is_open_close)
+ g_string_free (tag, TRUE);
+
+ allow_space = is_close; // don't allow space after opening a tag
+ }
+
+ else if (instr[i] == '&') { // Entity
+ const EntityMap *entity = lookup_entity (instr+i);
+ if (entity) {
+ if (!strcmp (entity->html, "product"))
+ g_string_append (outp, YUI::app()->productName().c_str());
+ else
+ g_string_append (outp, entity->text);
+ i += strlen (entity->html);
+ if (instr[i+1] == ';') i++;
+ }
+ else {
+ int j;
+ // check it is a valid entity - not a floating '&' in a <pre> tag eg.
+ for (j = i + 1; instr[j] != '\0'; j++) {
+ if (!g_ascii_isalnum (instr[j]) && instr[j] != '#')
+ break;
+ }
+ if (instr[j] != ';') // entity terminator
+ g_string_append (outp, "&");
+ else
+ g_string_append_c (outp, instr[i]);
+ }
+ allow_space = TRUE;
+ }
+
+ else { // Normal text
+ if (!pre_mode && g_ascii_isspace (instr[i])) {
+ if (allow_space)
+ g_string_append_c (outp, ' ');
+ allow_space = FALSE; // one space is enough
+ }
+ else {
+ allow_space = TRUE;
+ g_string_append_c (outp, instr[i]);
+ }
+ }
+ }
+
+ emit_unclosed_tags_for (outp, tag_queue, "", 0);
+ g_queue_free (tag_queue);
+ g_string_append (outp, "</body>");
+
+ gchar *ret = g_string_free (outp, FALSE);
+ return ret;
+}
+
+std::string YGUtils::mapKBAccel (const std::string &src)
+{
+ // conversion pairs: ('_', '__') ('&&', '&') ('&', '_')
+ std::string::size_type length = src.length(), i;
+ string str;
+ str.reserve (length);
+ for (i = 0; i < length; i++) {
+ if (src[i] == '_')
+ str += "__";
+ else if (src[i] == '&') {
+ if (i+1 < length && src[i+1] == '&') {
+ str += '&'; // escaping
+ i++;
+ }
+ else
+ str += '_';
+ }
+ else
+ str += src[i];
+ }
+ return str;
+}
+
+char *ygutils_mapKBAccel (const char *src)
+{
+ std::string ret (YGUtils::mapKBAccel (src));
+ return strdup (ret.c_str());
+}
+
+void YGUtils::setFilter (GtkEntry *entry, const string &validChars)
+{
+ struct inner {
+ static void insert_text_cb (GtkEditable *editable, const gchar *new_text,
+ gint new_text_length, gint *pos)
+ {
+ const gchar *valid_chars = (gchar *) g_object_get_data (G_OBJECT (editable),
+ "valid-chars");
+ if (valid_chars) {
+ const gchar *i, *j;
+ for (i = new_text; *i; i++) {
+ for (j = valid_chars; *j; j++) {
+ if (*i == *j)
+ break;
+ }
+ if (!*j) {
+ // not valid text
+ g_signal_stop_emission_by_name (editable, "insert_text");
+ gtk_widget_error_bell (GTK_WIDGET (editable));
+ return;
+ }
+ }
+ }
+ }
+ };
+
+ if (g_object_get_data (G_OBJECT (entry), "insert-text-set"))
+ g_object_disconnect (G_OBJECT (entry), "insert-text",
+ G_CALLBACK (inner::insert_text_cb), NULL);
+
+ if (!validChars.empty()) {
+ gchar *chars = g_strdup (validChars.c_str());
+ g_object_set_data_full (G_OBJECT (entry), "valid-chars", chars, g_free);
+ g_signal_connect (G_OBJECT (entry), "insert-text",
+ G_CALLBACK (inner::insert_text_cb), NULL);
+ g_object_set_data (G_OBJECT (entry), "insert-text-set", GINT_TO_POINTER (1));
+ }
+ else
+ g_object_set_data (G_OBJECT (entry), "insert-text-set", GINT_TO_POINTER (0));
+}
+
+void ygutils_setFilter (GtkEntry *entry, const char *validChars)
+{ YGUtils::setFilter (entry, validChars); }
+
+void YGUtils::replace (string &str, const char *mouth, int mouth_len, const char *food)
+{
+ if (mouth_len < 0)
+ mouth_len = strlen (mouth);
+ std::string::size_type i = 0;
+ while ((i = str.find (mouth, i)) != string::npos) {
+ str.erase (i, mouth_len);
+ str.insert (i, food);
+ }
+}
+
+std::string YGUtils::truncate (const std::string &str, int length, int pos)
+{
+ std::string ret (str);
+ const char *pstr = ret.c_str(); char *pi;
+ int size = g_utf8_strlen (pstr, -1);
+ if (size > length) {
+ if (pos > 0) {
+ pi = g_utf8_offset_to_pointer (pstr, length-3);
+ ret.erase (pi-pstr);
+ ret.append ("...");
+ }
+ else if (pos < 0) {
+ pi = g_utf8_offset_to_pointer (pstr, size-(length-3));
+ ret.erase (0, pi-pstr);
+ ret.insert (0, "...");
+ }
+ else /* (pos == 0) */ {
+ pi = g_utf8_offset_to_pointer (pstr, size/2);
+ int delta = size - (length-3);
+ gchar *pn = pi, *pp = pi;
+ for (int i = 0;;) {
+ if (i++ == delta) break;
+ pn = g_utf8_next_char (pn);
+ if (i++ == delta) break;
+ pp = g_utf8_prev_char (pp);
+ }
+ g_assert (pp != NULL && pn != NULL);
+
+ ret.erase (pp-pstr, pn-pp);
+ ret.insert (pp-pstr, "...");
+ }
+ }
+ return ret;
+}
+
+static gboolean scroll_down_cb (void *pData)
+{
+ GtkAdjustment *vadj = (GtkAdjustment *) pData;
+ gtk_adjustment_set_value (vadj, vadj->upper - vadj->page_size);
+ return FALSE;
+}
+
+void YGUtils::scrollWidget (GtkAdjustment *vadj, bool top)
+{
+ if (top)
+ gtk_adjustment_set_value (vadj, vadj->lower);
+ else
+ // since we usually want to call this together with a text change, we
+ // must wait till that gets in effect
+ g_idle_add_full (G_PRIORITY_LOW, scroll_down_cb, vadj, NULL);
+}
+
+void ygutils_scrollAdj (GtkAdjustment *vadj, gboolean top)
+{ YGUtils::scrollWidget (vadj, top); }
+
+std::string YGUtils::escapeMarkup (const std::string &ori)
+{
+ std::string::size_type length = ori.length(), i;
+ std::string ret;
+ ret.reserve (length * 1.5);
+ for (i = 0; i < length; i++)
+ switch (ori[i]) {
+ case '<':
+ ret += "<";
+ break;
+ case '>':
+ ret += ">";
+ break;
+ case '&':
+ ret += "&";
+ break;
+ default:
+ ret += ori[i];
+ break;
+ }
+ return ret;
+}
+
+bool YGUtils::endsWith (const std::string &str, const std::string &key)
+{
+ if (str.size() < key.size())
+ return false;
+ return str.compare (str.size()-key.size(), key.size(), key) == 0;
+}
+
+int YGUtils::getCharsWidth (GtkWidget *widget, int chars_nb)
+{
+ PangoContext *context = gtk_widget_get_pango_context (widget);
+ PangoFontMetrics *metrics = pango_context_get_metrics (context,
+ widget->style->font_desc, NULL);
+
+ int width = pango_font_metrics_get_approximate_char_width (metrics);
+ pango_font_metrics_unref (metrics);
+
+ return PANGO_PIXELS (width) * chars_nb;
+}
+
+int YGUtils::getCharsHeight (GtkWidget *widget, int chars_nb)
+{
+ PangoContext *context = gtk_widget_get_pango_context (widget);
+ PangoFontMetrics *metrics = pango_context_get_metrics (context,
+ widget->style->font_desc, NULL);
+
+ int height = pango_font_metrics_get_ascent (metrics) +
+ pango_font_metrics_get_descent (metrics);
+ pango_font_metrics_unref (metrics);
+
+ return PANGO_PIXELS (height) * chars_nb;
+}
+
+void YGUtils::setWidgetFont (GtkWidget *widget, PangoStyle style, PangoWeight weight,
+ double scale)
+{
+ PangoFontDescription *font_desc = widget->style->font_desc;
+ int size = pango_font_description_get_size (font_desc);
+ PangoFontDescription* font = pango_font_description_new();
+ pango_font_description_set_weight (font, weight);
+ pango_font_description_set_size (font, (int)(size * scale));
+ pango_font_description_set_style (font, style);
+ gtk_widget_modify_font (widget, font);
+ pango_font_description_free (font);
+}
+
+void ygutils_setWidgetFont (GtkWidget *widget, PangoStyle style, PangoWeight weight, double scale)
+{ YGUtils::setWidgetFont (widget, style, weight, scale); }
+
+static void paned_allocate_cb (GtkWidget *paned, GtkAllocation *alloc, gpointer _rel)
+{
+ if (!g_object_get_data (G_OBJECT (paned), "init")) { // only once
+ gdouble rel = GPOINTER_TO_INT (_rel) / 100.;
+ gint parent_size;
+ if (gtk_orientable_get_orientation (GTK_ORIENTABLE (paned)) == GTK_ORIENTATION_HORIZONTAL)
+ parent_size = paned->allocation.width;
+ else
+ parent_size = paned->allocation.height;
+ int pos = parent_size * rel;
+ gtk_paned_set_position (GTK_PANED (paned), pos);
+ g_object_set_data (G_OBJECT (paned), "init", GINT_TO_POINTER (1));
+ }
+}
+
+void YGUtils::setPaneRelPosition (GtkWidget *paned, gdouble rel)
+{
+ gint _rel = rel * 100;
+ g_signal_connect_after (G_OBJECT (paned), "size-allocate",
+ G_CALLBACK (paned_allocate_cb), GINT_TO_POINTER (_rel));
+}
+
+void ygutils_setPaneRelPosition (GtkWidget *paned, gdouble rel)
+{ YGUtils::setPaneRelPosition (paned, rel); }
+
+GdkPixbuf *YGUtils::loadPixbuf (const string &filename)
+{
+ GdkPixbuf *pixbuf = NULL;
+ if (!filename.empty()) {
+ GError *error = 0;
+ pixbuf = gdk_pixbuf_new_from_file (filename.c_str(), &error);
+ if (!pixbuf)
+ yuiWarning() << "Could not load icon: " << filename << "\n"
+ "Reason: " << error->message << "\n";
+ }
+ return pixbuf;
+}
+
+// Code from Banshee: shades a pixbuf a bit, used e.g. for hover effects
+static inline guchar pixel_clamp (int val)
+{ return MAX (0, MIN (255, val)); }
+GdkPixbuf *YGUtils::setOpacity (const GdkPixbuf *src, int opacity, bool touchAlpha)
+{
+ if (!src) return NULL;
+ int shift = 255 - ((opacity * 255) / 100);
+ int rgb_shift = 0, alpha_shift = 0;
+ if (touchAlpha)
+ alpha_shift = shift;
+ else
+ rgb_shift = shift;
+
+ int width = gdk_pixbuf_get_width (src), height = gdk_pixbuf_get_height (src);
+ gboolean has_alpha = gdk_pixbuf_get_has_alpha (src);
+
+ GdkPixbuf *dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
+ has_alpha, gdk_pixbuf_get_bits_per_sample (src), width, height);
+
+ guchar *src_pixels_orig = gdk_pixbuf_get_pixels (src);
+ guchar *dest_pixels_orig = gdk_pixbuf_get_pixels (dest);
+
+ int src_rowstride = gdk_pixbuf_get_rowstride (src);
+ int dest_rowstride = gdk_pixbuf_get_rowstride (dest);
+ int i, j;
+ for (i = 0; i < height; i++) {
+ guchar *src_pixels = src_pixels_orig + (i * src_rowstride);
+ guchar *dest_pixels = dest_pixels_orig + (i * dest_rowstride);
+ for (j = 0; j < width; j++) {
+ *(dest_pixels++) = pixel_clamp (*(src_pixels++) + rgb_shift);
+ *(dest_pixels++) = pixel_clamp (*(src_pixels++) + rgb_shift);
+ *(dest_pixels++) = pixel_clamp (*(src_pixels++) + rgb_shift);
+ if (has_alpha)
+ *(dest_pixels++) = pixel_clamp (*(src_pixels++) - alpha_shift);
+ }
+ }
+ return dest;
+}
+
+GdkPixbuf *YGUtils::setGray (const GdkPixbuf *src)
+{
+ int width = gdk_pixbuf_get_width (src), height = gdk_pixbuf_get_height (src);
+ gboolean has_alpha = gdk_pixbuf_get_has_alpha (src);
+
+ GdkPixbuf *dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
+ has_alpha, gdk_pixbuf_get_bits_per_sample (src), width, height);
+
+ guchar *src_pixels_orig = gdk_pixbuf_get_pixels (src);
+ guchar *dest_pixels_orig = gdk_pixbuf_get_pixels (dest);
+
+ int src_rowstride = gdk_pixbuf_get_rowstride (src);
+ int dest_rowstride = gdk_pixbuf_get_rowstride (dest);
+ int i, j;
+ for (i = 0; i < height; i++) {
+ guchar *src_pixels = src_pixels_orig + (i * src_rowstride);
+ guchar *dest_pixels = dest_pixels_orig + (i * dest_rowstride);
+ for (j = 0; j < width; j++) {
+ int clr = (src_pixels[0] + src_pixels[1] + src_pixels[2]) / 3;
+ *(dest_pixels++) = clr;
+ *(dest_pixels++) = clr;
+ *(dest_pixels++) = clr;
+ src_pixels += 3;
+ if (has_alpha)
+ *(dest_pixels++) = *(src_pixels++);
+ }
+ }
+ return dest;
+}
+
+GdkPixbuf *ygutils_setOpacity (const GdkPixbuf *src, int opacity, gboolean useAlpha)
+{ return YGUtils::setOpacity (src, opacity, useAlpha); }
+
+static std::string cutUnderline (const std::string &str)
+{
+ std::string ret (str);
+ std::string::size_type i = 0;
+ if ((i = ret.find ('_', i)) != std::string::npos)
+ ret.erase (i, 1);
+ return ret;
+}
+
+static void stripStart (std::string &str, char ch)
+{
+ while (!str.empty() && str[0] == ch)
+ str.erase (0, 1);
+}
+static void stripEnd (std::string &str, char ch)
+{
+ while (!str.empty() && str[str.size()-1] == ch)
+ str.erase (str.size()-1, 1);
+}
+
+struct StockMap {
+ const char *english, *locale, *stock;
+};
+static const StockMap stock_map[] = {
+ { "Apply", _("Apply"), GTK_STOCK_APPLY },
+ { "Accept", _("Accept"), GTK_STOCK_APPLY },
+ { "Install", _("Install"), GTK_STOCK_APPLY },
+ { "OK", _("OK"), GTK_STOCK_OK },
+ { "Cancel", _("Cancel"), GTK_STOCK_CANCEL },
+ { "Abort", _("Abort"), GTK_STOCK_CANCEL },
+ { "Close", _("Close"), GTK_STOCK_CLOSE },
+ { "Yes", _("Yes"), GTK_STOCK_YES },
+ { "No", _("No"), GTK_STOCK_NO },
+ { "Add", _("Add"), GTK_STOCK_ADD },
+ { "Edit", _("Edit"), GTK_STOCK_EDIT },
+ { "Delete", _("Delete"), GTK_STOCK_DELETE },
+ { "Up", _("Up"), GTK_STOCK_GO_UP },
+ { "Down", _("Down"), GTK_STOCK_GO_DOWN },
+ { "Enable", _("Enable"), GTK_STOCK_YES },
+ { "Disable", _("Disable"), GTK_STOCK_NO },
+ { "Exit", _("Exit"), GTK_STOCK_QUIT },
+};
+#define stock_map_length (sizeof (stock_map) / sizeof (StockMap))
+
+const char *YGUtils::mapStockIcon (const std::string &label)
+{
+ static bool firstTime = true; static std::map stockMap;
+ if (firstTime) {
+ firstTime = false;
+
+ // match GTK stock labels to yast ones
+ GSList *list = gtk_stock_list_ids();
+ for (GSList *i = list; i; i = i->next) {
+ gchar *id = (gchar *) i->data;
+ GtkStockItem item;
+ if (gtk_stock_lookup (id, &item)) {
+ const gchar *_id = id;
+ if (!strcmp (id, GTK_STOCK_MEDIA_NEXT) || !strcmp (id, GTK_STOCK_MEDIA_FORWARD))
+ _id = GTK_STOCK_GO_FORWARD;
+ else if (!strcmp (id, GTK_STOCK_MEDIA_PREVIOUS) || !strcmp (id, GTK_STOCK_MEDIA_REWIND))
+ _id = GTK_STOCK_GO_BACK;
+ else if (!strcmp (id, GTK_STOCK_MEDIA_RECORD))
+ _id = GTK_STOCK_SAVE;
+ else if (!strcmp (id, GTK_STOCK_CLEAR))
+ _id = GTK_STOCK_DELETE;
+ else if (!strcmp (id, GTK_STOCK_QUIT))
+ _id = GTK_STOCK_APPLY;
+ else if (!strcmp (id, GTK_STOCK_JUMP_TO))
+ _id = GTK_STOCK_OK;
+ else if (!strncmp (id, "gtk-dialog-", 11))
+ _id = 0;
+
+ if (_id)
+ stockMap[cutUnderline (item.label)] = _id;
+ }
+ // some may not have a stock item because they can't be set on a label
+ // e.g.: gtk-directory, gtk-missing-image, gtk-dnd
+ g_free (id);
+ }
+ g_slist_free (list);
+
+ for (unsigned int j = 0; j < 2; j++) // add both current locale & english terms
+ for (unsigned int i = 0; i < stock_map_length; i++)
+ stockMap [stock_map[i].english+j] = stock_map[i].stock;
+ }
+
+ std::string id = cutUnderline (label);
+ stripStart (id, ' ');
+ stripEnd (id, ' ');
+ stripEnd (id, '.');
+
+ std::map ::const_iterator it;
+ it = stockMap.find (id);
+ if (it != stockMap.end())
+ return it->second.c_str();
+ return NULL;
+}
+
+const char *YGUtils::setStockIcon (GtkWidget *button, const std::string &label,
+ const char *fallbackIcon)
+{
+ const char *icon = mapStockIcon (label);
+ if (!icon && label.size() < 22)
+ icon = fallbackIcon;
+ if (icon) {
+ if (gtk_style_lookup_icon_set (button->style, icon)) {
+ // we want to use GtkImage stock mode so it honors sensitive
+ GtkWidget *image = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ }
+ }
+ else {
+ GtkWidget *image = gtk_button_get_image (GTK_BUTTON (button));
+ if (image)
+ gtk_widget_hide (image);
+ }
+ return icon;
+}
+
+void YGUtils::shrinkWidget (GtkWidget *widget)
+{
+ static bool first_time = true;
+ if (first_time) {
+ first_time = false;
+ gtk_rc_parse_string (
+ "style \"small-widget-style\"\n"
+ "{\n"
+ " GtkWidget::focus-padding = 0\n"
+ " GtkWidget::focus-line-width = 0\n"
+ " xthickness = 0\n"
+ " ythickness = 0\n"
+ "}\n"
+ "widget \"*.small-widget\" style \"small-widget-style\"");
+ }
+ gtk_widget_set_name (widget, "small-widget");
+}
+
+/*
+ * construct a help string by dropping the title, and mentioning
+ * the first sentence for a dialog sub-title
+ */
+gchar *
+ygutils_headerize_help (const char *help_text, gboolean *cut)
+{
+ char *text = ygutils_convert_to_xhtml (help_text);
+
+ GString *str = g_string_new ("");
+ int i;
+ gboolean copy_word = FALSE;
+ for (i = 0; text[i]; i++) {
+ if (text[i] == '<') {
+ int a = i;
+ for (; text[i]; i++)
+ if (text[i] == '>')
+ break;
+
+ if (!strncasecmp (text+a, "len && !strncasecmp (text+a, "<b>", 3))) {
+ for (i++; text[i]; i++) {
+ if (text[i] == '<')
+ a = i;
+ if (text[i] == '>') {
+ if (!strncasecmp (text+a, "')
+ markup = FALSE;
+ }
+ else {
+ if (text[i] == '<')
+ markup = TRUE;
+ else if (!g_ascii_isspace (text[i])) {
+ *cut = TRUE;
+ break;
+ }
+ }
+ }
+ g_free (text);
+ return g_string_free (str, FALSE);
+}
+
+const char *ygutils_mapStockIcon (const char *label)
+{ return YGUtils::mapStockIcon (label); }
+
+const char *ygutils_setStockIcon (GtkWidget *button, const char *label, const char *fallback)
+{ return YGUtils::setStockIcon (button, label, fallback); }
+
+/* interactive busy cursor */
+// half cursor, half clock cursor is not a Xlib theme icon, but there is
+// a hack to load it like: (if we ever want to use it...)
+#if 0
+__LEFT_PTR_WATCH = None
+def set_busy_cursor (window):
+ global __LEFT_PTR_WATCH
+ if __LEFT_PTR_WATCH is None:
+ os.environ['XCURSOR_DISCOVER'] = '1' #Turn on logging in Xlib
+ # Busy cursor code from Padraig Brady
+ # cursor_data hash is 08e8e1c95fe2fc01f976f1e063a24ccd
+ cursor_data = "\
+\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\
+\x0c\x00\x00\x00\x1c\x00\x00\x00\x3c\x00\x00\x00\
+\x7c\x00\x00\x00\xfc\x00\x00\x00\xfc\x01\x00\x00\
+\xfc\x3b\x00\x00\x7c\x38\x00\x00\x6c\x54\x00\x00\
+\xc4\xdc\x00\x00\xc0\x44\x00\x00\x80\x39\x00\x00\
+\x80\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00"
+
+ try:
+ pix = gtk.gdk.bitmap_create_from_data(None, cursor_data, 32, 32)
+ color = gtk.gdk.Color()
+ __LEFT_PTR_WATCH = gtk.gdk.Cursor(pix, pix, color, color, 2, 2)
+ except TypeError:
+ # old bug http://bugzilla.gnome.org/show_bug.cgi?id=103616
+ # default "WATCH" cursor
+ __LEFT_PTR_WATCH = gtk.gdk.Cursor(gtk.gdk.WATCH)
+ window.set_cursor (__LEFT_PTR_WATCH)
+#endif
+
+
+gboolean YGUtils::empty_row_is_separator_cb (
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer _text_col)
+{
+ int text_col = GPOINTER_TO_INT (_text_col);
+ gchar *str;
+ gtk_tree_model_get (model, iter, text_col, &str, -1);
+ bool ret = !str || !(*str);
+ g_free (str);
+ return ret;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGUtils.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,96 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGUTILS_H
+#define YGUTILS_H
+
+#include <string>
+#include <list>
+#include
+#include
+
+/* YGUtils.h/cc have some functionality that is shared between different parts
+ of the code. */
+
+namespace YGUtils
+{
+ /* Replaces Yast's '&' accelerator by Gnome's '_' (and proper escaping). */
+ std::string mapKBAccel (const std::string &src);
+
+ /* Adds filter support to a GtkEntry. */
+ void setFilter (GtkEntry *entry, const std::string &validChars);
+
+ /* Replaces every 'mouth' by 'food' in 'str'. */
+ void replace (std::string &str, const char *mouth, int mouth_len, const char *food);
+
+ /* Truncates the text with "..." past the given length.
+ pos: -1 = start, 0 = middle, 1 = end. Honors utf-8 characters. */
+ std::string truncate (const std::string &str, int length, int pos);
+
+ /* Escapes markup text (eg. changes '<' by '\<'). */
+ std::string escapeMarkup (const std::string &str);
+
+ /* Check if 'str' ends with 'suffix'. */
+ bool endsWith (const std::string &str, const std::string &suffix);
+
+ /* Adds functionality to scroll widgets to top or bottom. */
+ void scrollWidget (GtkAdjustment *vadj, bool top);
+
+ /* Returns the average width of the given number of characters in pixels. */
+ int getCharsWidth (GtkWidget *widget, int chars_nb);
+ int getCharsHeight (GtkWidget *widget, int chars_nb);
+
+ /* Sets some widget font proprities. */
+ void setWidgetFont (GtkWidget *widget, PangoStyle style, PangoWeight weight, double scale);
+
+ /* Instead of setting GtkPaned::position in pixels, do so in percents. */
+ void setPaneRelPosition (GtkWidget *paned, gdouble rel);
+
+ /* Saves some code and standardizes the error. Returns NULL if failed.
+ Don't forget to g_object_unref it! */
+ GdkPixbuf *loadPixbuf (const std::string &fileneme);
+
+ /* Shifts colors in a GdkPixbuf. */
+ GdkPixbuf *setOpacity (const GdkPixbuf *src, int opacity, bool touchAlpha);
+
+ /* Gray out some pixbuf. */
+ GdkPixbuf *setGray (const GdkPixbuf *src);
+
+ /* Tries to make sense out of the string, applying some stock icon to the button. */
+ const char *mapStockIcon (const std::string &label);
+ const char *setStockIcon (GtkWidget *button, const std::string &label,
+ const char *fallbackIcon);
+
+ /* For empty model rows, render a separator (can be used for GtkTreeView and GtkComboBox */
+ gboolean empty_row_is_separator_cb (
+ GtkTreeModel *model, GtkTreeIter *iter, gpointer text_col);
+
+ /* Shrink widget inner-border (thickness) */
+ void shrinkWidget (GtkWidget *widget);
+};
+
+extern "C" {
+ char *ygutils_mapKBAccel (const char *src);
+
+ void ygutils_setWidgetFont (GtkWidget *widget, PangoStyle style, PangoWeight weight, double scale);
+ void ygutils_setPaneRelPosition (GtkWidget *paned, gdouble rel);
+
+ void ygutils_setFilter (GtkEntry *entry, const char *validChars);
+
+ void ygutils_scrollAdj (GtkAdjustment *vadj, gboolean top);
+
+ const char *ygutils_mapStockIcon (const char *label);
+ const char *ygutils_setStockIcon (GtkWidget *button, const char *label,
+ const char *fallbackIcon);
+
+ GdkPixbuf *ygutils_setOpacity (const GdkPixbuf *src, int opacity, gboolean useAlpha);
+
+ gchar *ygutils_headerize_help (const char *help_text, gboolean *cut);
+
+ // convert liberal html to xhtml
+ gchar *ygutils_convert_to_xhtml (const char *instr);
+};
+
+#endif // YGUTILS_H
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,339 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include
+#include "YGWidget.h"
+#include "YGUtils.h"
+#include "ygtkratiobox.h"
+
+// default widgets border -- may be overlapped with a setBorder(..)
+#define DEFAULT_BORDER 6
+#define LABEL_WIDGET_SPACING 4
+
+/* Utilities */
+
+struct YGWidget::Signals
+{
+ typedef std::pair Handler;
+ std::list <Handler> m_handlers;
+ void connectSignal (GObject *object, const char *name,
+ GCallback callback, gpointer data, bool after)
+ {
+ gulong handler;
+ if (after)
+ handler = g_signal_connect_after (object, name, callback, data);
+ else
+ handler = g_signal_connect (object, name, callback, data);
+
+ Handler h (object, handler);
+ m_handlers.push_back (h);
+ }
+ void block()
+ {
+ for (std::list <Handler>::const_iterator it = m_handlers.begin();
+ it != m_handlers.end(); it++) {
+ const Handler &h = *it;
+ g_signal_handler_block (h.first, h.second);
+ }
+ }
+ void unblock()
+ {
+ for (std::list <Handler>::const_iterator it = m_handlers.begin();
+ it != m_handlers.end(); it++) {
+ const Handler &h = *it;
+ g_signal_handler_unblock (h.first, h.second);
+ }
+ }
+};
+
+/* YGWidget follows */
+
+static void min_size_cb (guint *min_width, guint *min_height, gpointer pData);
+
+YGWidget::YGWidget(YWidget *ywidget, YWidget *yparent,
+ GtkType type, const char *property_name, ...)
+ : m_ywidget (ywidget)
+{
+ va_list args;
+ va_start (args, property_name);
+ construct (ywidget, yparent, type, property_name, args);
+ va_end (args);
+}
+
+void YGWidget::construct (YWidget *ywidget, YWidget *yparent,
+ GType type, const char *property_name, va_list args)
+{
+ m_widget = GTK_WIDGET (g_object_new_valist (type, property_name, args));
+
+ if (type == GTK_TYPE_WINDOW || type == GTK_TYPE_MENU)
+ m_adj_size = m_widget;
+ else {
+ m_adj_size = ygtk_adj_size_new();
+ g_object_ref_sink (G_OBJECT (m_adj_size));
+ gtk_widget_show (m_adj_size);
+ gtk_container_add (GTK_CONTAINER (m_adj_size), m_widget);
+ }
+ gtk_widget_show (m_widget);
+
+ // Split by two so that with another widget it will have full border...
+ setBorder (DEFAULT_BORDER / 2);
+ ygtk_adj_size_set_min_cb (YGTK_ADJ_SIZE (m_adj_size), min_size_cb, this);
+
+ ywidget->setWidgetRep ((void *) this);
+ if (yparent) {
+ ywidget->setParent (yparent);
+ yparent->addChild (ywidget);
+ }
+ m_signals = NULL;
+}
+
+YGWidget::~YGWidget()
+{
+ delete m_signals;
+ m_signals = 0;
+ if (YGUI::ui()->eventPendingFor (m_ywidget))
+ YGUI::ui()->m_event_handler.consumePendingEvent();
+ // remove children if container?
+#if 0
+ struct inner {
+ static void foreach_child_cb (GtkWidget *child, GtkContainer *container)
+ { gtk_container_remove (container, child); }
+ };
+ if (GTK_IS_CONTAINER (m_widget))
+ gtk_container_foreach (GTK_CONTAINER (m_widget),
+ (GtkCallback) inner::foreach_child_cb, m_widget);
+#endif
+ gtk_widget_destroy (m_adj_size);
+ g_object_unref (G_OBJECT (m_adj_size));
+}
+
+YGWidget *YGWidget::get (YWidget *ywidget)
+{
+ //g_assert (ywidget->widgetRep() != NULL);
+ return (YGWidget *) ywidget->widgetRep();
+}
+
+bool YGWidget::doSetKeyboardFocus()
+{
+ gtk_widget_grab_focus (getWidget());
+ return gtk_widget_is_focus (getWidget());
+}
+
+void YGWidget::doSetEnabled (bool enabled)
+{
+ gtk_widget_set_sensitive (getLayout(), enabled);
+}
+
+void YGWidget::doSetUseBoldFont (bool useBold)
+{
+ PangoWeight weight = useBold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
+ YGUtils::setWidgetFont (getWidget(), PANGO_STYLE_NORMAL, weight, PANGO_SCALE_MEDIUM);
+}
+
+void YGWidget::doAddChild (YWidget *ychild, GtkWidget *container)
+{
+ GtkWidget *child = YGWidget::get (ychild)->getLayout();
+ gtk_container_add (GTK_CONTAINER (container), child);
+}
+
+void YGWidget::doRemoveChild (YWidget *ychild, GtkWidget *container)
+{
+ /* Note: removeChild() is generally a result of a widget being removed as it
+ will remove itself from the parent. But YGWidget deconstructor would run
+ before the YWidget one, as that's the order we have been using, so we
+ can't use it, we can't retrieve the GTK widget then. However, this is a
+ non-issue, as ~YGWidget will destroy the widget, and GTK will remove it
+ from the parent. */
+ if (!ychild->beingDestroyed()) {
+ GtkWidget *child = YGWidget::get (ychild)->getLayout();
+ gtk_container_remove (GTK_CONTAINER (container), child);
+ }
+}
+
+int YGWidget::doPreferredSize (YUIDimension dimension)
+{
+ // We might want to do some caching here..
+ GtkRequisition req;
+ gtk_widget_size_request (m_adj_size, &req);
+ return dimension == YD_HORIZ ? req.width : req.height;
+}
+
+void min_size_cb (guint *min_width, guint *min_height, gpointer pData)
+{
+ YGWidget *pThis = (YGWidget *) pData;
+ *min_width = pThis->getMinSize (YD_HORIZ);
+ *min_height = pThis->getMinSize (YD_VERT);
+}
+
+#include "ygtkfixed.h"
+
+void YGWidget::doSetSize (int width, int height)
+{
+ GtkWidget *parent = 0;
+ if (m_ywidget->parent())
+ parent = YGWidget::get (m_ywidget->parent())->getWidget();
+
+ if (parent && YGTK_IS_FIXED (parent))
+ ygtk_fixed_set_child_size (YGTK_FIXED (parent), m_adj_size, width, height);
+}
+
+void YGWidget::emitEvent (YEvent::EventReason reason, EventFlags flags)
+{
+ struct inner
+ {
+ static gboolean dispatchEvent (gpointer data)
+ {
+ YWidgetEvent *event = (YWidgetEvent *) data;
+ if (!YGUI::ui()->eventPendingFor (event->widget()))
+ YGUI::ui()->sendEvent (event);
+ return FALSE;
+ }
+ };
+
+#if YAST2_VERSION > 2018003
+ if (reason == YEvent::ContextMenuActivated && !m_ywidget->notifyContextMenu())
+ ; // cancel
+#endif
+ if (flags & IGNORE_NOTIFY_EVENT || m_ywidget->notify()) {
+ YWidgetEvent *event = new YWidgetEvent (m_ywidget, reason);
+ if (flags & DELAY_EVENT)
+ g_timeout_add (250, inner::dispatchEvent, event);
+ else if (!(flags & IF_NOT_PENDING_EVENT) || !YGUI::ui()->eventPendingFor (m_ywidget))
+ YGUI::ui()->sendEvent (event);
+ }
+}
+
+void YGWidget::connect (gpointer object, const char *name, GCallback callback, gpointer data,
+ bool after)
+{
+ if (!m_signals)
+ m_signals = new YGWidget::Signals();
+ m_signals->connectSignal (G_OBJECT (object), name, callback, data, after);
+}
+
+void YGWidget::blockSignals()
+{ if (m_signals) m_signals->block(); }
+void YGWidget::unblockSignals()
+{ if (m_signals) m_signals->unblock(); }
+
+void YGWidget::setBorder (unsigned int border)
+{ gtk_container_set_border_width (GTK_CONTAINER (m_adj_size), border); }
+
+/* YGLabeledWidget follows */
+
+YGLabeledWidget::YGLabeledWidget (YWidget *ywidget, YWidget *parent,
+ const std::string &label_text, YUIDimension label_ori,
+ GType type, const char *property_name, ...)
+ : YGWidget (ywidget, parent,
+// label_ori == YD_VERT ? GTK_TYPE_VBOX : GTK_TYPE_HBOX,
+ GTK_TYPE_VBOX, "spacing", LABEL_WIDGET_SPACING, NULL)
+{
+ // Create the field widget
+ va_list args;
+ va_start (args, property_name);
+ m_field = GTK_WIDGET (g_object_new_valist (type, property_name, args));
+ va_end (args);
+
+ // Create the label
+ m_label = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (m_label), 0.0, 0.5);
+/* if (label_ori == YD_HORIZ)
+ gtk_label_set_line_wrap (GTK_LABEL (m_label), TRUE);*/
+ gtk_widget_show (m_label);
+ gtk_widget_show (m_field);
+
+ setBuddy (m_field);
+ doSetLabel (label_text);
+
+ // Set the container and show widgets
+ gtk_box_pack_start (GTK_BOX (m_widget), m_label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (m_widget), m_field, TRUE, TRUE, 0);
+ m_orientation = label_ori;
+}
+
+void YGLabeledWidget::setLabelVisible (bool show)
+{
+ if (show)
+ gtk_widget_show (m_label);
+ else
+ gtk_widget_hide (m_label);
+}
+
+void YGLabeledWidget::setBuddy (GtkWidget *widget)
+{
+ gtk_label_set_mnemonic_widget (GTK_LABEL (m_label), widget);
+}
+
+void YGLabeledWidget::doSetLabel (const std::string &label)
+{
+ if (!label.empty()) {
+ string str (YGUtils::mapKBAccel (label));
+
+ // add a ':' at the end of the label, if not set
+ if (!str.empty()) {
+ const gchar *last = g_utf8_find_prev_char (str.c_str(), str.c_str() + str.length());
+ gunichar last_char = g_utf8_get_char (last);
+ if (g_unichar_isalpha (last_char)) { // append
+ bool reverse = false;
+ if (gtk_widget_get_direction (m_label) == GTK_TEXT_DIR_RTL &&
+ pango_find_base_dir (str.c_str(), -1) == PANGO_DIRECTION_LTR)
+ reverse = true;
+
+ int i = reverse ? 0 : str.length();
+ str.insert (i, 1, ':');
+ }
+ }
+
+ gtk_label_set_text (GTK_LABEL (m_label), str.c_str());
+ gtk_label_set_use_underline (GTK_LABEL (m_label), TRUE);
+ }
+ setLabelVisible (!label.empty());
+}
+
+/* YGScrolledWidget follows */
+#define MAX_SCROLL_WIDTH 120
+
+YGScrolledWidget::YGScrolledWidget (YWidget *ywidget, YWidget *parent,
+ GType type, const char *property_name, ...)
+ : YGLabeledWidget (ywidget, parent, string(), YD_VERT,
+ GTK_TYPE_SCROLLED_WINDOW, "shadow-type", GTK_SHADOW_IN, NULL)
+{
+ va_list args;
+ va_start (args, property_name);
+ construct(type, property_name, args);
+ va_end (args);
+ setLabelVisible (false);
+}
+
+YGScrolledWidget::YGScrolledWidget (YWidget *ywidget, YWidget *parent,
+ const std::string &label_text, YUIDimension label_ori,
+ GType type, const char *property_name, ...)
+ : YGLabeledWidget (ywidget, parent, label_text, label_ori,
+ GTK_TYPE_SCROLLED_WINDOW, "shadow-type", GTK_SHADOW_IN, NULL)
+{
+ va_list args;
+ va_start (args, property_name);
+ construct(type, property_name, args);
+ va_end (args);
+}
+
+void YGScrolledWidget::construct (GType type, const char *property_name,
+ va_list args)
+{
+ m_widget = GTK_WIDGET (g_object_new_valist (type, property_name, args));
+ setBuddy (m_widget);
+
+ setPolicy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (YGLabeledWidget::getWidget()), m_widget);
+ gtk_widget_show (m_widget);
+}
+
+void YGScrolledWidget::setPolicy (GtkPolicyType hpolicy, GtkPolicyType vpolicy)
+{
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (YGLabeledWidget::getWidget()),
+ hpolicy, vpolicy);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWidget.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,169 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGWIDGET_H
+#define YGWIDGET_H
+
+#include
+#include
+#include "YGUI.h"
+#include "YEvent.h"
+
+class YGWidget
+{
+public:
+ YGWidget (YWidget *ywidget, YWidget *yparent,
+ GType type, const char *property_name, ...);
+ virtual ~YGWidget();
+
+ // get the YGWidget associated with a YWidget
+ static YGWidget *get (YWidget *y_widget);
+
+ virtual inline GtkWidget *getWidget() { return m_widget; }
+ GtkWidget *getLayout() { return m_adj_size; } // add this to a container
+ virtual GtkWidget *getContainer() { return m_widget; } // add children here
+
+ // overload YWidget methods with these ones
+ virtual bool doSetKeyboardFocus();
+ virtual void doSetEnabled (bool enabled);
+ virtual void doSetUseBoldFont (bool useBold);
+ virtual void doAddChild (YWidget *child, GtkWidget *container);
+ virtual void doRemoveChild (YWidget *child, GtkWidget *container);
+
+ // layout
+ virtual int doPreferredSize (YUIDimension dimension);
+ virtual void doSetSize (int width, int height);
+
+ // debug
+ const char *getWidgetName() const { return m_ywidget->widgetClass(); }
+ virtual string getDebugLabel() const // let YWidget::debugLabel() be overloaded
+ { if (m_ywidget->hasChildren()) return string(); return m_ywidget->debugLabel(); }
+
+ // aesthetics
+ void setBorder (unsigned int border); // in pixels
+ virtual unsigned int getMinSize (YUIDimension dim) { return 0; }
+
+protected:
+ // event emission
+ enum EventFlags
+ { DELAY_EVENT = 2, IGNORE_NOTIFY_EVENT = 4, IF_NOT_PENDING_EVENT = 8 };
+ void emitEvent (YEvent::EventReason reason, EventFlags flags = (EventFlags) 0);
+
+ // signal registration; use "BlockEvents (this)" to temp-ly block all signals
+ friend struct BlockEvents;
+ void connect (gpointer object, const char *name,
+ GCallback callback, gpointer data, bool after = true);
+ void blockSignals();
+ void unblockSignals();
+ struct Signals;
+ friend struct Signals;
+ Signals *m_signals;
+
+ void construct (YWidget *ywidget, YWidget *yparent,
+ GType type, const char *property_name, va_list args);
+
+ // data
+ GtkWidget *m_widget, *m_adj_size; // associated GtkWidget, and adjustment for borders
+ YWidget *m_ywidget; // associated YWidget
+};
+
+struct BlockEvents
+{
+ BlockEvents (YGWidget *widget) : m_widget (widget)
+ { m_widget->blockSignals(); }
+ ~BlockEvents()
+ { m_widget->unblockSignals(); }
+
+ private: YGWidget *m_widget;
+};
+
+/*
+ * Macros to help implement proxies between common YWidget virtual
+ * methods and the (multiply inherited) YGWidget base implementation
+ * for GTK+.
+ */
+#define YGWIDGET_IMPL_COMMON(ParentClass) \
+ virtual bool setKeyboardFocus() { \
+ return doSetKeyboardFocus(); } \
+ virtual void setEnabled (bool enabled) { \
+ ParentClass::setEnabled (enabled); \
+ doSetEnabled (enabled); \
+ } \
+ virtual int preferredWidth() { return doPreferredSize (YD_HORIZ); } \
+ virtual int preferredHeight() { return doPreferredSize (YD_VERT); } \
+ virtual void setSize (int width, int height) { doSetSize (width, height); }
+
+#define YGWIDGET_IMPL_USE_BOLD(ParentClass) \
+ virtual void setUseBoldFont (bool useBold) { \
+ ParentClass::setUseBoldFont (useBold); \
+ doSetUseBoldFont (useBold); \
+ }
+
+#define YGWIDGET_IMPL_CONTAINER(ParentClass) \
+ YGWIDGET_IMPL_COMMON (ParentClass) \
+ virtual void addChild (YWidget *ychild) { \
+ ParentClass::addChild (ychild); \
+ doAddChild (ychild, getContainer()); \
+ } \
+ virtual void removeChild (YWidget *ychild) { \
+ ParentClass::removeChild (ychild); \
+ doRemoveChild (ychild, getContainer()); \
+ }
+
+/* This is a convenience class that allows for a label next to the
+ intended widget. It should be used, in case you have the need for
+ such, as it gives an uniform API. */
+class YGLabeledWidget : public YGWidget
+{
+ public:
+ YGLabeledWidget(YWidget *ywidget, YWidget *yparent,
+ const std::string &label_text, YUIDimension label_ori,
+ GType type, const char *property_name, ...);
+ virtual ~YGLabeledWidget () {}
+
+ virtual inline GtkWidget* getWidget() { return m_field; }
+
+ void setLabelVisible (bool show);
+ void setBuddy (GtkWidget *widget);
+ virtual void doSetLabel (const std::string &label);
+
+ YUIDimension orientation() { return m_orientation; }
+ GtkWidget *getLabelWidget() { return m_label; }
+
+ protected:
+ GtkWidget *m_label, *m_field;
+ YUIDimension m_orientation;
+};
+
+#define YGLABEL_WIDGET_IMPL(ParentClass) \
+ YGWIDGET_IMPL_COMMON (ParentClass) \
+ virtual void setLabel (const std::string &label) { \
+ ParentClass::setLabel (label); \
+ doSetLabel (label); \
+ }
+
+/* This is a convenience class for widgets that need scrollbars. */
+class YGScrolledWidget : public YGLabeledWidget
+{
+ public:
+ YGScrolledWidget(YWidget *ywidget, YWidget *yparent,
+ GType type, const char *property_name, ...);
+ // if you want a label, use:
+ YGScrolledWidget(YWidget *ywidget, YWidget *yparent,
+ const std::string &label_text, YUIDimension label_ori,
+ GType type, const char *property_name, ...);
+ virtual ~YGScrolledWidget () {}
+
+ virtual inline GtkWidget *getWidget() { return m_widget; }
+
+ // you should use this method, not gtk_scrolled_window_set...
+ void setPolicy (GtkPolicyType hpolicy, GtkPolicyType vpolicy);
+
+ protected:
+ void construct(GType type, const char *property_name, va_list args);
+ GtkWidget *m_widget;
+};
+
+#endif /*YGWIDGET_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWizard.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWizard.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWizard.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGWizard.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,305 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGUI.h"
+#include "YGWidget.h"
+#include "YGUtils.h"
+#include "ygtkwizard.h"
+#include "YWizard.h"
+#include "YPushButton.h"
+#include "YAlignment.h"
+#include "YReplacePoint.h"
+#include "YGDialog.h"
+
+class YGWizard : public YWizard, public YGWidget
+{
+ YReplacePoint *m_replacePoint;
+
+ /* YCP requires us to allow people to use YPushButton API on the wizard buttons.
+ Wizard already has handlers for them; this seems like bad design.
+
+ We could support wrapping right in our framework. One way, would be to subclass
+ YWidgetOpt to have a wrapping field where we would set a GtkWidget*. Then,
+ classes should pass opt to YGWidget and it would create a shallow instance
+ around it. However, this isn't really doable. The problem is that, like
+ in this case, the API isn't really exact; events must be sent as YWizard events.
+ */
+ struct YGWButton : public YPushButton {
+ /* Thin class; just changes the associated button label and keeps track
+ of id change. */
+ YGWButton (YGWizard *parent, GtkWidget *widget, const std::string &label)
+ : YPushButton (parent, label), m_widget (widget), m_wizard (parent)
+ {
+ setWidgetRep (NULL);
+ setLabel (label);
+ ygtk_wizard_set_button_ptr_id (getWizard(), widget, this);
+ }
+
+ virtual void setLabel (const string &label)
+ {
+ YPushButton::setLabel (label);
+
+ // notice: we can't use functionKey() to deduce the icon because yast
+ // tools code differ from the text-mode to the GUIs when setting buttons
+ // up, and the opt_f10 and so on will not be set in the GUI code
+ YGtkWizard *wizard = getWizard();
+ std::string _label = YGUtils::mapKBAccel (label);
+ ygtk_wizard_set_button_label (wizard, getWidget(), _label.c_str(), NULL);
+ }
+
+ virtual void setEnabled (bool enable)
+ {
+ YWidget::setEnabled (enable);
+ ygtk_wizard_enable_button (getWizard(), getWidget(), enable);
+ }
+
+ virtual bool setKeyboardFocus()
+ {
+ gtk_widget_grab_focus (getWidget());
+ return gtk_widget_is_focus (getWidget());
+ }
+
+ virtual int preferredWidth() { return 0; }
+ virtual int preferredHeight() { return 0; }
+ virtual void setSize (int w, int h) {}
+
+ inline GtkWidget *getWidget() { return m_widget; }
+ inline YGtkWizard *getWizard() { return YGTK_WIZARD (m_wizard->getWidget()); }
+
+ private:
+ GtkWidget *m_widget;
+ YGWizard *m_wizard;
+ };
+
+ YGWButton *m_back_button, *m_abort_button, *m_next_button, *m_notes_button;
+ // release notes button would be a little more hassle to support; yast-qt
+ // doesn't support it too anyway.
+
+public:
+ YGWizard (YWidget *parent, const string &backButtonLabel,
+ const string &abortButtonLabel, const string &nextButtonLabel,
+ YWizardMode wizardMode)
+ : YWizard (NULL, backButtonLabel, abortButtonLabel, nextButtonLabel, wizardMode)
+ , YGWidget (this, parent, YGTK_TYPE_WIZARD, NULL)
+ {
+ setBorder (0);
+ YGtkWizard *wizard = getWizard();
+
+ //** Application area
+ {
+ YAlignment *align = YUI::widgetFactory()->createAlignment (this,
+ YAlignCenter, YAlignCenter);
+ align->setStretchable (YD_HORIZ, true);
+ align->setStretchable (YD_VERT, true);
+
+ m_replacePoint = YUI::widgetFactory()->createReplacePoint ((YWidget *) align);
+ YUI::widgetFactory()->createEmpty ((YWidget *) m_replacePoint);
+ m_replacePoint->showChild();
+ }
+
+ //** Steps/tree pane
+ bool steps_enabled = wizardMode == YWizardMode_Steps;
+ bool tree_enabled = wizardMode == YWizardMode_Tree;
+ if (steps_enabled && tree_enabled) {
+ yuiError() << "YGWizard doesn't support both steps and tree enabled at the "
+ "same time.\nDisabling the steps...\n";
+ steps_enabled = false;
+ }
+ if (steps_enabled)
+ ygtk_wizard_enable_steps (wizard);
+ if (tree_enabled)
+ ygtk_wizard_enable_tree (wizard);
+
+ //** Setting the bottom buttons
+ m_back_button = new YGWButton (this, wizard->back_button, backButtonLabel);
+ m_abort_button = new YGWButton (this, wizard->abort_button, abortButtonLabel);
+ m_next_button = new YGWButton (this, wizard->next_button, nextButtonLabel);
+ m_notes_button = new YGWButton (this, wizard->release_notes_button, string());
+ ygtk_wizard_set_default_button (wizard, wizard->next_button);
+
+ //** All event are sent through this signal together with an id
+ g_signal_connect (G_OBJECT (getWidget()), "action-triggered",
+ G_CALLBACK (action_triggered_cb), this);
+ }
+
+ virtual ~YGWizard()
+ {
+ // m_back/abort/next_button are added as children and
+ // so will be freed by ~YContainerWidget
+ }
+
+ inline YGtkWizard *getWizard()
+ { return YGTK_WIZARD (getWidget()); }
+
+ virtual YReplacePoint *contentsReplacePoint() const
+ { return m_replacePoint; }
+
+ virtual YPushButton *backButton() const
+ { return m_back_button; }
+ virtual YPushButton *abortButton() const
+ { return m_abort_button; }
+ virtual YPushButton *nextButton() const
+ { return m_next_button; }
+
+ virtual void setButtonLabel (YPushButton *button, const string &label)
+ {
+ button->setLabel (label);
+ }
+
+ virtual void setHelpText (const string &_text)
+ {
+ std::string productName = YUI::app()->productName();
+ std::string text(_text);
+ YGUtils::replace (text, "&product;", 9, productName.c_str());
+ ygtk_wizard_set_help_text (getWizard(), text.c_str());
+ }
+
+ virtual void setDialogIcon (const string &icon)
+ {
+ if (!ygtk_wizard_set_header_icon (getWizard(), icon.c_str()))
+ yuiWarning() << "YGWizard: could not load image: " << icon << endl;
+ YGDialog::currentDialog()->setIcon (icon);
+ }
+
+ virtual void setDialogHeading (const string &heading)
+ {
+ ygtk_wizard_set_header_text (getWizard(), heading.c_str());
+ YGDialog::currentDialog()->setTitle (heading, false);
+ }
+
+ virtual void setDialogTitle (const string &title)
+ {
+ YGDialog::currentDialog()->setTitle (title, true);
+ }
+
+ virtual void addStepHeading (const string &text)
+ {
+ ygtk_wizard_add_step_header (getWizard(), text.c_str());
+ }
+
+ virtual void addStep (const string &text, const string &id)
+ {
+ ygtk_wizard_add_step (getWizard(), text.c_str(), id.c_str());
+ }
+
+ virtual void setCurrentStep (const string &id)
+ {
+ if (!ygtk_wizard_set_current_step (getWizard(), id.c_str()))
+ yuiError() << "YGWizard: there is no step with id " << id << endl;
+ }
+
+ virtual void deleteSteps()
+ {
+ ygtk_wizard_clear_steps (getWizard());
+ }
+
+ virtual void updateSteps()
+ {}
+
+ virtual void addTreeItem (const string &parentID, const string &text,
+ const string &id)
+ {
+ if (!ygtk_wizard_add_tree_item (getWizard(), parentID.c_str(),
+ text.c_str(), id.c_str()))
+ yuiError() << "YGWizard: there is no tree item with id " << parentID << endl;
+ }
+
+ virtual void selectTreeItem (const string &id)
+ {
+ if (!ygtk_wizard_select_tree_item (getWizard(), id.c_str()))
+ yuiError() << "YGWizard: there is no tree item with id " << id << endl;
+ }
+
+ virtual string currentTreeSelection()
+ {
+ const char *selected = ygtk_wizard_get_tree_selection (getWizard());
+ if (selected)
+ return selected;
+ return string();
+ }
+
+ virtual void deleteTreeItems()
+ {
+ ygtk_wizard_clear_tree (getWizard());
+ }
+
+ virtual void addMenu (const string &text, const string &id)
+ {
+ string str = YGUtils::mapKBAccel (text);
+ ygtk_wizard_add_menu (getWizard(), str.c_str(), id.c_str());
+ }
+
+ virtual void addSubMenu (const string &parentID, const string &text,
+ const string &id)
+ {
+ string str = YGUtils::mapKBAccel(text);
+ if (!ygtk_wizard_add_sub_menu (getWizard(), parentID.c_str(), str.c_str(),
+ id.c_str()))
+ yuiError() << "YGWizard: there is no menu item with id " << parentID << endl;
+ }
+
+ virtual void addMenuEntry (const string &parentID, const string &text,
+ const string &id)
+ {
+ string str = YGUtils::mapKBAccel (text);
+ if (!ygtk_wizard_add_menu_entry (getWizard(), parentID.c_str(),
+ str.c_str(), id.c_str()))
+ yuiError() << "YGWizard: there is no menu item with id " << parentID << endl;
+ }
+
+ virtual void addMenuSeparator (const string & parentID)
+ {
+ if (!ygtk_wizard_add_menu_separator (getWizard(), parentID.c_str()))
+ yuiError() << "YGWizard: there is no menu item with id " << parentID << endl;
+ }
+
+ virtual void deleteMenus()
+ {
+ ygtk_wizard_clear_menu (getWizard());
+ }
+
+ virtual void showReleaseNotesButton (const string &label, const string &id)
+ {
+ string str = YGUtils::mapKBAccel (label.c_str());
+ ygtk_wizard_set_button_label (getWizard(), m_notes_button->getWidget(), str.c_str(), NULL);
+ ygtk_wizard_set_button_str_id (getWizard(), m_notes_button->getWidget(), id.c_str());
+ }
+
+ virtual void hideReleaseNotesButton()
+ {
+ ygtk_wizard_set_button_label (getWizard(), m_notes_button->getWidget(), NULL, NULL);
+ }
+
+ virtual void retranslateInternalButtons()
+ {}
+
+ static void action_triggered_cb (YGtkWizard *wizard, gpointer id,
+ gint id_type, YGWizard *pThis)
+ {
+ if ((GType) id_type == G_TYPE_STRING)
+ YGUI::ui()->sendEvent (new YMenuEvent ((char *) id));
+ else
+ YGUI::ui()->sendEvent (new YWidgetEvent ((YWidget *) id, YEvent::Activated));
+ }
+
+ // YGWidget
+ virtual void doAddChild (YWidget *ychild, GtkWidget *container)
+ {
+ if (ychild->widgetRep()) // don't actually add the button wrappers
+ ygtk_wizard_set_child (getWizard(), YGWidget::get (ychild)->getLayout());
+ }
+
+ YGWIDGET_IMPL_CONTAINER (YWizard)
+};
+
+YWizard *YGOptionalWidgetFactory::createWizard (YWidget *parent,
+ const string &backButtonLabel, const string &abortButtonLabel,
+ const string &nextButtonLabel, YWizardMode wizardMode)
+{
+ return new YGWizard (parent, backButtonLabel, abortButtonLabel, nextButtonLabel,
+ wizardMode);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/YGi18n.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/YGi18n.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/YGi18n.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/YGi18n.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,20 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGi18n_h
+#define YGi18n_h
+
+#include
+#define TEXTDOMAIN "gtk"
+
+static inline const char *_(const char *msgid)
+{ return dgettext (TEXTDOMAIN, msgid); }
+
+#ifndef YGI18N_C
+static inline const char * _(const char * msgid1, const char *msgid2, unsigned long int n)
+{ return dngettext(TEXTDOMAIN, msgid1, msgid2, n); }
+#endif
+
+#endif /*YGi18n_h*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/dummy.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/dummy.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/dummy.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/dummy.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,13 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include
+#include
+
+int main (int argc, char **argv)
+{
+ YGUI(false);
+ return 0;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/hr.xpm
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/hr.xpm?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/hr.xpm (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/hr.xpm Mon Aug 1 09:44:45 2011
@@ -0,0 +1,173 @@
+/* XPM */
+static const char * hr_xpm[] = {
+"200 1 169 2",
+" c None",
+". c #F0F8F0",
+"+ c #EEF8EF",
+"@ c #EEF7ED",
+"# c #EDF6EC",
+"$ c #EBF6EB",
+"% c #E9F4E9",
+"& c #E9F4E8",
+"* c #E7F3E7",
+"= c #E6F3E6",
+"- c #E4F2E4",
+"; c #E2F1E3",
+"> c #E1F1E1",
+", c #E0F0E0",
+"' c #DFEFDF",
+") c #DDEFDE",
+"! c #DCEEDD",
+"~ c #DBEEDB",
+"{ c #DAEDDA",
+"] c #D8EDD8",
+"^ c #D7ECD7",
+"/ c #D5EBD5",
+"( c #D4EBD4",
+"_ c #D3EAD3",
+": c #D2EAD2",
+"< c #D0E9D0",
+"[ c #CFE8CF",
+"} c #CEE8CE",
+"| c #CCE7CC",
+"1 c #CBE6CB",
+"2 c #CAE5CA",
+"3 c #C9E5C9",
+"4 c #C7E4C7",
+"5 c #C6E4C6",
+"6 c #C4E3C4",
+"7 c #C3E2C3",
+"8 c #C2E2C2",
+"9 c #C1E1C0",
+"0 c #BFE1C0",
+"a c #BEE0BE",
+"b c #BDE0BC",
+"c c #BBDFBB",
+"d c #BADEBA",
+"e c #B8DEB8",
+"f c #B7DDB7",
+"g c #B6DCB6",
+"h c #B5DBB5",
+"i c #B3DBB3",
+"j c #B2DAB2",
+"k c #B1DAB1",
+"l c #AFD9AF",
+"m c #AED8AE",
+"n c #ADD8AD",
+"o c #ABD7AC",
+"p c #AAD6AA",
+"q c #A8D6A9",
+"r c #A7D5A7",
+"s c #A6D5A6",
+"t c #A4D4A4",
+"u c #A3D3A3",
+"v c #A2D3A2",
+"w c #A0D2A0",
+"x c #A0D1A0",
+"y c #9ED19E",
+"z c #9CD19D",
+"A c #9BCF9B",
+"B c #9ACF9A",
+"C c #99CF99",
+"D c #98CE97",
+"E c #96CD97",
+"F c #95CC94",
+"G c #94CC94",
+"H c #92CB92",
+"I c #91CA91",
+"J c #90CA8F",
+"K c #8EC98E",
+"L c #8DC88D",
+"M c #8BC88C",
+"N c #8AC88B",
+"O c #89C689",
+"P c #87C788",
+"Q c #86C586",
+"R c #85C585",
+"S c #84C484",
+"T c #82C483",
+"U c #81C380",
+"V c #7FC37F",
+"W c #7EC27E",
+"X c #7DC17D",
+"Y c #7BC17C",
+"Z c #7ABF7B",
+"` c #79BF79",
+" . c #78BF78",
+".. c #76BE76",
+"+. c #75BE75",
+"@. c #74BD73",
+"#. c #73BC72",
+"$. c #71BB71",
+"%. c #70BA70",
+"&. c #6FBA6E",
+"*. c #6EBA6E",
+"=. c #EFF7EF",
+"-. c #EEF7EE",
+";. c #ECF6EC",
+">. c #EAF5EA",
+",. c #E9F5E9",
+"'. c #E8F4E8",
+"). c #E4F3E4",
+"!. c #E3F1E3",
+"~. c #E2F1E2",
+"{. c #DFF0DF",
+"]. c #DEEFDD",
+"^. c #DCEFDC",
+"/. c #DAEED9",
+"(. c #D8ECD8",
+"_. c #D7ECD6",
+":. c #D6ECD6",
+"<. c #D4EAD4",
+"[. c #D2EAD1",
+"}. c #D1E9D1",
+"|. c #CDE7CD",
+"1. c #CBE7CB",
+"2. c #CAE6CA",
+"3. c #C8E5C9",
+"4. c #C7E5C7",
+"5. c #C6E4C5",
+"6. c #C5E3C4",
+"7. c #C0E1C1",
+"8. c #BFE1BF",
+"9. c #BDE0BE",
+"0. c #BDDFBC",
+"a. c #BCDEBB",
+"b. c #B4DBB5",
+"c. c #B2DAB1",
+"d. c #B0DAB0",
+"e. c #B0D9B0",
+"f. c #AED9AE",
+"g. c #ACD8AC",
+"h. c #ACD8AB",
+"i. c #AAD6A9",
+"j. c #A7D6A8",
+"k. c #A6D4A6",
+"l. c #A5D4A5",
+"m. c #A3D3A4",
+"n. c #A1D2A1",
+"o. c #9FD29F",
+"p. c #9CD09C",
+"q. c #9BD09C",
+"r. c #98CE99",
+"s. c #97CE98",
+"t. c #96CD96",
+"u. c #95CD95",
+"v. c #93CC93",
+"w. c #8FCA8F",
+"x. c #8DC88C",
+"y. c #8CC88B",
+"z. c #8AC78A",
+"A. c #88C687",
+"B. c #86C587",
+"C. c #84C585",
+"D. c #82C382",
+"E. c #80C381",
+"F. c #80C280",
+"G. c #7EC27F",
+"H. c #7CC07B",
+"I. c #7AC07B",
+"J. c #75BD75",
+"K. c #74BD74",
+"L. c #6EBB6E",
+". =.-.;.>.,.'.* = ).!.~., {.].^.~ /.(._.:.<._ [.}.[ |.| 1.2.3.4.5.6.7 8 7.8.9.0.a.d e f g b.i c.d.e.f.g.h.i.q j.k.l.m.v n.o.y p.q.B r.s.t.u.v.H I w.K x.y.z.O A.B.C.S D.E.F.G.X H.I.` ...J.K.#.$.%.L.*.*.L.%.$.#.K.J... .` I.H.X G.F.E.D.S C.B.A.O z.y.x.K w.I H v.u.t.s.r.B q.p.y o.n.v m.l.k.j.q i.h.g.f.e.d.c.i b.g f e d a.0.9.8.7.8 7 6.5.4.3.2.1.| |.[ }.[._ <.:._.(./.~ ^.].{., ~.!.).= * '.,.>.;.-.=.. "};
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/CMakeLists.txt
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/CMakeLists.txt?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/CMakeLists.txt (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/CMakeLists.txt Mon Aug 1 09:44:45 2011
@@ -0,0 +1,55 @@
+## Makefile.am
+
+set (gtk_pkg_yast_plugin_SRCS
+ pkg-selector-help.cc
+ YGPackageSelector.cc
+ YGPackageSelectorPluginImpl.cc
+ ygtkpkgdetailview.cc
+ ygtkpkghistorydialog.cc
+ ygtkpkglistview.cc
+ ygtkpkgfilterview.cc
+ ygtkpkglanguageview.cc
+ ygtkpkgmenubar.cc
+ ygtkpkgpatternview.cc
+ ygtkpkgproductdialog.cc
+ ygtkpkgquerycombo.cc
+ ygtkpkgrpmgroupsview.cc
+ ygtkpkgsearchentry.cc
+ ygtkpkgstatusbar.cc
+ ygtkpkgundolist.cc
+ yzypptags.cc
+ yzyppwrapper.cc
+ #ygtkpkgvestigialdialog.cc
+
+ ygtkcellrendererbutton.c
+ ygtkcellrenderersidebutton.c
+ ygtkcellrenderertext.c
+ ygtktreemodel.cc
+ )
+
+## includes:
+
+include_directories (${ZYPP_INCLUDE_DIR})
+# we want libpy2gtk_pkg.so to link to libpy2gtk.so before install
+# and then to find it when it is installed and on its own
+link_directories (${CMAKE_BINARY_DIR}/src)
+link_directories (${UI_PLUGIN_DIR})
+
+## target:
+
+add_library (py2gtk_pkg SHARED ${gtk_pkg_yast_plugin_SRCS})
+add_dependencies (py2gtk_pkg py2gtk)
+
+## libraries:
+
+target_link_libraries (py2gtk_pkg libpy2gtk.so)
+target_link_libraries (py2gtk_pkg ${GTK2_LIBRARIES})
+target_link_libraries (py2gtk_pkg ${LIBYUI_LIBRARY})
+target_link_libraries (py2gtk_pkg ${ZYPP_LIBRARY})
+set_target_properties (py2gtk_pkg PROPERTIES SOVERSION 2)
+set_target_properties (py2gtk_pkg PROPERTIES LINK_FLAGS "--no-undefined -Wl,-rpath -Wl,${UI_PLUGIN_DIR}")
+
+## install:
+
+install (TARGETS py2gtk_pkg LIBRARY DESTINATION ${UI_PLUGIN_DIR})
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,841 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include
+#include "YGUtils.h"
+#include "YGDialog.h"
+#include "YGUI.h"
+#include "YGPackageSelector.h"
+#include "yzyppwrapper.h"
+#include "ygtkwizard.h"
+#include "ygtkhtmlwrap.h"
+#include "ygtkpkglistview.h"
+#include "ygtkpkgsearchentry.h"
+#include "ygtkpkgfilterview.h"
+#include "ygtkpkgrpmgroupsview.h"
+#include "ygtkpkgquerycombo.h"
+#include "ygtkpkgpatternview.h"
+#include "ygtkpkglanguageview.h"
+#include "ygtkpkgundolist.h"
+#include "ygtkpkgmenubar.h"
+#include "ygtkpkgstatusbar.h"
+#include "ygtkpkgdetailview.h"
+
+#include "ygtkpkghistorydialog.h"
+#ifdef HAS_VESTIGIAL_DIALOG
+#include "ygtkpkgvestigialdialog.h"
+#endif
+
+//#define USE_LIST_BUTTONS
+
+YGPackageSelector *YGPackageSelector::singleton = 0;
+
+struct YGPackageSelector::Impl :
+ public Ypp::Interface, YGtkPkgListView::Listener, YGtkPkgQueryWidget::Listener,
+ YGtkPkgQueryCombo::Factory
+{
+GtkWidget *m_widget, *m_toolbox;
+YGtkPkgListView *m_list;
+YGtkPkgQueryCombo *m_combo;
+YGtkPkgSearchEntry *m_entry;
+std::list m_queryWidgets;
+YGtkPkgUndoList *m_undo;
+YGtkPkgStatusBar *m_status;
+YGtkPkgMenuBar *m_menu;
+std::list m_filterSuffices;
+GtkWidget *m_overview;
+YGtkPkgDetailView *m_details;
+guint m_refresh_id;
+Ypp::List m_refresh_list;
+bool has_patterns_mode;
+
+struct SuffixFilter : public Ypp::Match {
+ SuffixFilter (Impl *pThis) : pThis (pThis) {}
+
+ virtual bool match (Ypp::Selectable &sel)
+ {
+ if (!pThis->m_filterSuffices.empty()) {
+ std::string name (sel.name());
+ for (std::list ::iterator it = pThis->m_filterSuffices.begin();
+ it != pThis->m_filterSuffices.end(); it++)
+ if (YGUtils::endsWith (name, *it))
+ return false;
+ }
+ return true;
+ }
+
+ Impl *pThis;
+};
+
+ GtkWidget *getWidget() { return m_widget; }
+
+ GtkWidget *createMainArea()
+ {
+ bool onlineUpdate = YGPackageSelector::get()->onlineUpdateMode();
+
+ m_entry = new YGtkPkgSearchEntry();
+ m_queryWidgets.push_back (m_entry);
+
+ m_list = new YGtkPkgListView (false, Ypp::List::NAME_SORT, false, true);
+#ifdef USE_LIST_BUTTONS
+ m_list->addImageColumn (NULL, STATUS_ICON_PROP);
+#else
+ m_list->addCheckColumn (INSTALLED_CHECK_PROP);
+#endif
+ m_list->addTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1);
+ m_list->addTextColumn (_("Version"), VERSION_PROP, true, 125);
+ if (!onlineUpdate)
+ m_list->addTextColumn (_("Size"), SIZE_PROP, false, 85);
+#ifdef USE_LIST_BUTTONS
+ m_list->addButtonColumn (_("Action"), ACTION_BUTTON_PROP);
+#endif
+ m_list->addTextColumn (_("Repository"), REPOSITORY_PROP, false, 180);
+ if (!onlineUpdate)
+ m_list->addTextColumn (_("Supportability"), SUPPORT_PROP, false, 120);
+ m_list->setListener (this);
+ m_entry->setActivateWidget (m_list->getView());
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 2);
+ GtkWidget *label = gtk_label_new_with_mnemonic (_("Package _listing:"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), m_list->getView());
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_event_box_new(), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), m_entry->getWidget(), FALSE, TRUE, 0);
+ m_toolbox = gtk_hbox_new (FALSE, 6);
+
+ GtkWidget *overview = ygtk_html_wrap_new();
+ if (onlineUpdate)
+ ygtk_html_wrap_set_text (overview,
+ "<h1>Overview</h1>"
+ "<p>Press a patch in the list to see more information about it.</p>"
+ "<p>To install a patch, just click on its \"checkbox\".</p>", FALSE);
+ else
+ ygtk_html_wrap_set_text (overview,
+ "<h1>Overview</h1>"
+ "<p>Browse packages using the groups list on the left.</p>"
+ "<p>Press a package in the list to see more information about it.</p>"
+ "<p>To install or remove a package, just click on its \"checkbox\".</p>", FALSE);
+
+ m_overview = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_overview),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (m_overview),
+ GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (m_overview), overview);
+ GtkWidget *text = gtk_event_box_new();
+ gtk_container_add (GTK_CONTAINER (text), m_overview);
+
+ GtkWidget *list_vbox = gtk_vbox_new (FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (list_vbox), m_list->getWidget(), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (list_vbox), m_toolbox, FALSE, TRUE, 0);
+
+ GtkWidget *vpaned = gtk_vpaned_new();
+ gtk_paned_pack1 (GTK_PANED (vpaned), list_vbox, TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (vpaned), text, FALSE, TRUE);
+ YGUtils::setPaneRelPosition (vpaned, .65);
+
+ GtkWidget *_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (_vbox), hbox, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (_vbox), vpaned, TRUE, TRUE, 0);
+ return _vbox;
+ }
+
+ GtkWidget *createSidebar()
+ {
+ m_combo = new YGtkPkgQueryCombo (this);
+ if (YGPackageSelector::get()->onlineUpdateMode()) {
+ m_combo->add (_("Priorities"));
+ m_combo->add (_("Repositories"));
+
+ int active = YGPackageSelector::get()->repoMode() ? 1 : 0;
+ m_combo->setActive (active);
+ }
+ else {
+ m_combo->add (_("Groups"));
+ m_combo->add (_("RPM Groups"));
+ m_combo->add (_("Repositories"));
+ m_combo->add (_("Support"));
+ m_combo->add ("");
+ has_patterns_mode = !isPatternsPoolEmpty();
+ if (has_patterns_mode)
+ m_combo->add (_("Patterns"));
+ m_combo->add (_("Languages"));
+
+ int active = 5;
+ if (YGPackageSelector::get()->repoMode())
+ active = 2;
+ else if (YGPackageSelector::get()->searchMode())
+ active = 0;
+ m_combo->setActive (active);
+ }
+ m_queryWidgets.push_back (m_combo);
+
+ YGtkPkgFilterView *status = new YGtkPkgFilterView (new YGtkPkgStatusModel());
+ if (YGPackageSelector::get()->updateMode())
+ status->select (3);
+ m_queryWidgets.push_back (status);
+
+ GtkWidget *vpaned = gtk_vpaned_new();
+ gtk_paned_pack1 (GTK_PANED (vpaned), m_combo->getWidget(), TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (vpaned), status->getWidget(), FALSE, FALSE);
+ YGUtils::setPaneRelPosition (vpaned, .80);
+ return vpaned;
+ }
+
+ Impl() : m_menu (NULL), m_details (NULL), m_refresh_id (0), m_refresh_list (0)
+ {
+ Ypp::init();
+ m_undo = new YGtkPkgUndoList();
+ m_status = 0;
+
+ GtkWidget *hpaned = gtk_hpaned_new();
+ gtk_paned_pack1 (GTK_PANED (hpaned), createSidebar(), FALSE, TRUE);
+ gtk_paned_pack2 (GTK_PANED (hpaned), createMainArea(), TRUE, FALSE);
+ YGUtils::setPaneRelPosition (hpaned, .28);
+
+ m_widget = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (m_widget), hpaned, TRUE, TRUE, 0);
+ if (!YGPackageSelector::get()->onlineUpdateMode()) {
+ m_status = new YGtkPkgStatusBar (m_undo);
+ gtk_box_pack_start (GTK_BOX (m_widget), m_status->getWidget(), FALSE, TRUE, 0);
+ }
+ gtk_widget_show_all (m_widget);
+ gtk_widget_hide (m_toolbox);
+
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++)
+ (*it)->setListener (this);
+ }
+
+ ~Impl()
+ {
+ if (m_refresh_id)
+ g_source_remove (m_refresh_id);
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++)
+ delete *it;
+ delete m_list;
+ delete m_menu;
+ delete m_status;
+ delete m_details;
+ delete m_undo;
+ Ypp::finish();
+ }
+
+ void clearQueryWidgets()
+ {
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++)
+ (*it)->clearSelection();
+ }
+
+ // Ypp::Interface
+
+ static bool acceptText (Ypp::Selectable &selectable, const std::string &title,
+ const std::string &open, const std::string &text)
+ {
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ (GtkDialogFlags) 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ "%s %s", selectable.name().c_str(), title.c_str());
+ if (!open.empty())
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", open.c_str());
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
+
+ GtkWidget *view = ygtk_html_wrap_new(), *scroll;
+ ygtk_html_wrap_set_text (view, text.c_str(), FALSE);
+
+ scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (scroll), view);
+
+ GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox);
+ gtk_box_pack_start (vbox, scroll, TRUE, TRUE, 6);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 550, 500);
+ gtk_widget_show_all (dialog);
+
+ gint ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ bool confirmed = (ret == GTK_RESPONSE_YES);
+ gtk_widget_destroy (dialog);
+ return confirmed;
+ }
+
+ virtual bool showLicense (Ypp::Selectable &sel, const std::string &license)
+ {
+ return acceptText (sel, _("License Agreement"),
+ _("Do you accept the terms of this license?"), license);
+ }
+
+ virtual bool showMessage (Ypp::Selectable &sel, const std::string &message)
+ { return acceptText (sel, _("Warning Message"), _("Install anyway?"), message); }
+
+ virtual bool resolveProblems (const std::list &problems)
+ {
+ // we can't use ordinary radio buttons, as gtk+ enforces that in a group
+ // one must be selected...
+ #define DETAILS_PAD 25
+ enum ColumnAlias {
+ SHOW_TOGGLE_COL, ACTIVE_TOGGLE_COL, TEXT_COL, WEIGHT_TEXT_COL,
+ TEXT_PAD_COL, APPLY_PTR_COL, TOTAL_COLS
+ };
+
+ struct inner {
+ static void solution_toggled (GtkTreeModel *model, GtkTreePath *path)
+ {
+ GtkTreeStore *store = GTK_TREE_STORE (model);
+ GtkTreeIter iter, parent;
+
+ 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);
+ if (!apply)
+ return;
+
+ // 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);
+ if (apply) *apply = false;
+ } while (gtk_tree_model_iter_next (model, &iter));
+ }
+
+ enabled = !enabled;
+ *apply = enabled;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_store_set (store, &iter, ACTIVE_TOGGLE_COL, enabled, -1);
+ }
+ 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);
+ }
+ };
+
+ // model
+ GtkTreeStore *store = gtk_tree_store_new (TOTAL_COLS,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_INT,
+ G_TYPE_INT, G_TYPE_POINTER);
+ for (std::list ::const_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, -1);
+ if (!(*it)->details.empty()) {
+ GtkTreeIter details_iter;
+ gtk_tree_store_append (store, &details_iter, &problem_iter);
+ gtk_tree_store_set (store, &details_iter, SHOW_TOGGLE_COL, FALSE,
+ TEXT_COL, (*it)->details.c_str(), TEXT_PAD_COL, DETAILS_PAD, -1);
+ }
+
+ for (int i = 0; (*it)->getSolution (i); i++) {
+ Ypp::Problem::Solution *solution = (*it)->getSolution (i);
+ GtkTreeIter solution_iter;
+ gtk_tree_store_append (store, &solution_iter, &problem_iter);
+ gtk_tree_store_set (store, &solution_iter, SHOW_TOGGLE_COL, TRUE,
+ WEIGHT_TEXT_COL, PANGO_WEIGHT_NORMAL,
+ ACTIVE_TOGGLE_COL, FALSE, TEXT_COL, solution->description.c_str(),
+ APPLY_PTR_COL, &solution->apply, -1);
+ if (!solution->details.empty()) {
+ gtk_tree_store_append (store, &solution_iter, &problem_iter);
+ gtk_tree_store_set (store, &solution_iter, SHOW_TOGGLE_COL, FALSE,
+ WEIGHT_TEXT_COL, PANGO_WEIGHT_NORMAL,
+ TEXT_COL, solution->details.c_str(), TEXT_PAD_COL, DETAILS_PAD, -1);
+ }
+ }
+ }
+
+ // interface
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GtkDialogFlags (0), GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "%s",
+ _("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;
+ column = gtk_tree_view_column_new();
+
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "visible", SHOW_TOGGLE_COL, "active", ACTIVE_TOGGLE_COL, NULL);
+ gtk_cell_renderer_toggle_set_radio (
+ GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
+ // 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);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "text", TEXT_COL, "weight", WEIGHT_TEXT_COL, "xpad", TEXT_PAD_COL, NULL);
+ g_object_set (G_OBJECT (renderer), "wrap-width", 400,
+ "wrap-mode", PANGO_WRAP_WORD_CHAR, 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);
+
+ 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);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), -1, 500);
+ gtk_widget_show_all (dialog);
+
+ bool apply = (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_APPLY);
+ gtk_widget_destroy (dialog);
+ return apply;
+ }
+
+ // YGtkPkgListView::Listener
+
+ virtual void selectionChanged()
+ {
+ Ypp::List selected = m_list->getSelected();
+ if (selected.size() == 0) return;
+
+ if (m_overview) {
+ GtkWidget *parent = gtk_widget_get_parent (m_overview);
+ gtk_container_remove (GTK_CONTAINER (parent), m_overview);
+ m_overview = NULL;
+
+ m_details = new YGtkPkgDetailView();
+ gtk_container_add (GTK_CONTAINER (parent), m_details->getWidget());
+ }
+
+ m_details->setList (selected);
+ }
+
+ // YGtkPkgQueryWidget::Listener
+
+ void refreshQueryWidget (YGtkPkgQueryWidget *widget)
+ {
+ Ypp::Selectable::Type type = Ypp::Selectable::PACKAGE;
+ if (YGPackageSelector::get()->onlineUpdateMode())
+ type = Ypp::Selectable::PATCH;
+ Ypp::PoolQuery query (type);
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++) {
+ if (*it == widget)
+ continue;
+ (*it)->writeQuery (query);
+ }
+ query.addCriteria (new SuffixFilter (this));
+
+ Ypp::List list (query);
+ widget->updateList (list);
+ }
+
+ void refreshFilters (Ypp::List list)
+ {
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++) {
+ if ((*it)->begsUpdate()) {
+ if (YGPackageSelector::get()->yield()) return;
+
+ if ((*it)->modified)
+ refreshQueryWidget (*it);
+ else
+ (*it)->updateList (list);
+ }
+ }
+ }
+
+ void refreshToolbox()
+ {
+ // only present one toolbox widget as they may be quite large
+ GtkWidget *toolbox = 0;
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++)
+ if ((toolbox = (*it)->createToolbox()))
+ break;
+
+ GList *children = gtk_container_get_children (GTK_CONTAINER (m_toolbox));
+ for (GList *i = children; i; i = i->next)
+ gtk_container_remove (GTK_CONTAINER (m_toolbox), (GtkWidget *) i->data);
+ g_list_free (children);
+
+ if (toolbox) {
+ gtk_box_pack_end (GTK_BOX (m_toolbox), toolbox, FALSE, TRUE, 0);
+ gtk_widget_show (m_toolbox);
+ }
+ else
+ gtk_widget_hide (m_toolbox);
+ }
+
+ static gboolean refresh_filters_timeout_cb (gpointer data)
+ {
+ YGUI::ui()->busyCursor();
+ if (YGPackageSelector::get()->yield()) return FALSE;
+
+ Impl *pThis = (Impl *) data;
+ pThis->refreshToolbox();
+ pThis->refreshFilters (pThis->m_refresh_list);
+ pThis->m_refresh_id = 0;
+
+ YGUI::ui()->normalCursor();
+ return FALSE;
+ }
+
+ virtual void refreshQuery()
+ {
+ if (m_refresh_id) {
+ g_source_remove (m_refresh_id);
+ m_refresh_id = 0;
+ }
+
+ YGUI::ui()->busyCursor();
+ if (YGPackageSelector::get()->yield()) return;
+
+ std::list keywords;
+ if (m_entry->getAttribute() == Ypp::PoolQuery::NAME)
+ keywords = m_entry->getText();
+
+ Ypp::Selectable::Type type = Ypp::Selectable::PACKAGE;
+ if (YGPackageSelector::get()->onlineUpdateMode())
+ type = Ypp::Selectable::PATCH;
+ Ypp::PoolQuery query (type);
+ for (std::list ::iterator it = m_queryWidgets.begin();
+ it != m_queryWidgets.end(); it++)
+ (*it)->modified = (*it)->writeQuery (query);
+ query.addCriteria (new SuffixFilter (this));
+
+ Ypp::List list (query);
+ m_list->setList (list);
+ m_list->setHighlight (keywords);
+
+ YGUI::ui()->normalCursor();
+
+ m_refresh_list = list;
+ int wait = 800;
+ if (keywords.empty())
+ wait = 500;
+ if (list.size() == 0)
+ wait = 200;
+ m_refresh_id = g_timeout_add_full (G_PRIORITY_LOW, wait, refresh_filters_timeout_cb, this, NULL);
+ }
+
+ // YGtkPkgQueryCombo callback
+
+ virtual YGtkPkgQueryWidget *createQueryWidget (YGtkPkgQueryCombo *combo, int index)
+ {
+ Ypp::Busy busy (0);
+ YGtkPkgFilterModel *model = 0;
+ if (YGPackageSelector::get()->onlineUpdateMode()) {
+ switch (index) {
+ case 0: model = new YGtkPkgPriorityModel(); break;
+ case 1: model = new YGtkPkgRepositoryModel(); break;
+ }
+ }
+ else {
+ switch (index) {
+ case 0: model = new YGtkPkgPKGroupModel(); break;
+ case 1: return new YGtkPkgRpmGroupsView();
+ case 2: model = new YGtkPkgRepositoryModel(); break;
+ case 3: model = new YGtkPkgSupportModel(); break;
+ case 5:
+ if (has_patterns_mode)
+ return new YGtkPkgPatternView (Ypp::Selectable::PATTERN);
+ case 6: return new YGtkPkgLanguageView();
+ }
+ }
+ return new YGtkPkgFilterView (model);
+ }
+
+ // YGPackageSelector complementary methods
+
+ static bool confirmCancel()
+ {
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
+ "%s", _("Changes not saved!"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
+ _("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 yes = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES;
+ gtk_widget_destroy (dialog);
+ return yes;
+ }
+
+ bool confirmUnsupported()
+ {
+ struct UnsupportedMatch : public Ypp::Match {
+ virtual bool match (Ypp::Selectable &sel)
+ { return Ypp::Package (sel).support() <= 1; }
+ };
+
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GtkDialogFlags (0), GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
+ _("Unsupported packages"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Please realize that the following software is either unsupported "
+ "or requires an additional customer contract for support."));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
+ GTK_STOCK_APPLY, GTK_RESPONSE_YES, NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 500);
+
+ Ypp::PoolQuery query (Ypp::Selectable::PACKAGE);
+ query.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::TO_MODIFY));
+ query.addCriteria (new UnsupportedMatch());
+ Ypp::List list (query);
+
+ YGtkPkgListView view (true, Ypp::List::NAME_SORT, false, true);
+ view.addCheckColumn (INSTALLED_CHECK_PROP);
+ view.addTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1);
+ view.addTextColumn (_("Supportability"), SUPPORT_PROP, true, 140);
+ view.addTextColumn (_("Version"), VERSION_PROP, true, 110);
+ view.addTextColumn (_("Repository"), REPOSITORY_PROP, false, 160);
+ view.setListener (this);
+ view.setList (list);
+
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), view.getWidget());
+ gtk_widget_show_all (dialog);
+ int ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ return ret == GTK_RESPONSE_YES;
+ }
+};
+
+extern const char *pkg_help[], *patch_help[];
+
+static bool confirm_cb (void *pThis)
+{
+ if (Ypp::isModified())
+ return YGPackageSelector::Impl::confirmCancel();
+ return true;
+}
+
+static void wizard_action_cb (YGtkWizard *wizard, gpointer id,
+ gint id_type, YGPackageSelector *pThis)
+{
+ const gchar *action = (gchar *) id;
+ yuiMilestone() << "Closing PackageSelector with '" << action << "'\n";
+ if (!strcmp (action, "accept"))
+ pThis->apply();
+ else if (!strcmp (action, "cancel"))
+ pThis->cancel();
+}
+
+YGPackageSelector::YGPackageSelector (YWidget *parent, long mode)
+: YPackageSelector (NULL, mode), YGWidget (this, parent, YGTK_TYPE_WIZARD, NULL),
+m_historyDialog (NULL)
+#ifdef HAS_VESTIGIAL_DIALOG
+, m_vestigialDialog (NULL)
+#endif
+{
+ singleton = this;
+ setBorder (0);
+ YGDialog *dialog = YGDialog::currentDialog();
+ dialog->setCloseCallback (confirm_cb, this);
+
+ const char *icon, *title, **help;
+ if (onlineUpdateMode()) {
+ icon = THEMEDIR "/icons/22x22/apps/yast-online_update.png";
+ title = _("Online Update");
+ help = patch_help;
+ }
+ else {
+ icon = THEMEDIR "/icons/22x22/apps/yast-software.png";
+ title = _("Software Manager");
+ help = pkg_help;
+ }
+
+ YGtkWizard *wizard = YGTK_WIZARD (getWidget());
+ ygtk_wizard_set_header_text (wizard, title);
+ ygtk_wizard_set_header_icon (wizard, icon);
+ dialog->setIcon (icon);
+ ygtk_wizard_set_help_text (wizard, _("Please wait..."));
+
+ std::string cancel_str (YGUtils::mapKBAccel ("&Cancel"));
+ std::string apply_str (YGUtils::mapKBAccel ("&Apply"));
+ ygtk_wizard_set_button_label (wizard, wizard->abort_button, _(cancel_str.c_str()), GTK_STOCK_CANCEL);
+ ygtk_wizard_set_button_str_id (wizard, wizard->abort_button, "cancel");
+ ygtk_wizard_set_button_label (wizard, wizard->back_button, NULL, NULL);
+ ygtk_wizard_set_button_label (wizard, wizard->next_button, _(apply_str.c_str()), GTK_STOCK_APPLY);
+ ygtk_wizard_set_button_str_id (wizard, wizard->next_button, "accept");
+ g_signal_connect (G_OBJECT (wizard), "action-triggered",
+ G_CALLBACK (wizard_action_cb), this);
+
+ impl = new Impl(); // can take a little
+ ygtk_wizard_set_child (wizard, impl->getWidget());
+ impl->m_menu = new YGtkPkgMenuBar();
+ ygtk_wizard_set_custom_menubar (wizard, impl->m_menu->getWidget(), FALSE);
+ //** TEMP: work-around global-menubar-applet: see bug 595560
+ gtk_widget_show_all (impl->m_menu->getWidget());
+
+ std::string str;
+ str.reserve (6820);
+ for (int i = 0; help[i]; i++)
+ str.append (help [i]);
+ ygtk_wizard_set_help_text (wizard, str.c_str());
+ dialog->setTitle (title);
+
+ Ypp::setInterface (impl);
+ Ypp::runSolver(); // check dependencies at start
+ impl->refreshQuery();
+
+ if (summaryMode()) popupChanges();
+}
+
+YGPackageSelector::~YGPackageSelector()
+{
+ delete m_historyDialog;
+#ifdef HAS_VESTIGIAL_DIALOG
+ delete m_vestigialDialog;
+#endif
+ delete impl;
+ singleton = 0;
+}
+
+void YGPackageSelector::cancel()
+{
+ if (Ypp::isModified())
+ if (!Impl::confirmCancel())
+ return;
+ YGUI::ui()->sendEvent (new YCancelEvent());
+}
+
+void YGPackageSelector::apply()
+{
+ if (!Ypp::runSolver()) return; // final dependencies check
+ if (onlineUpdateMode())
+ if (!Ypp::showPendingLicenses (Ypp::Selectable::PATCH)) return;
+ if (!Ypp::showPendingLicenses (Ypp::Selectable::PACKAGE)) return;
+
+ if (Ypp::isModified()) { // confirm
+ if (!onlineUpdateMode() && confirmUnsupported()) {
+ if (!impl->confirmUnsupported())
+ return;
+ }
+ if (!impl->m_undo->popupDialog (true))
+ return;
+ }
+
+ YGUI::ui()->sendEvent (new YMenuEvent ("accept"));
+}
+
+void YGPackageSelector::showFilterWidget (const char *filter)
+{
+ int index = -1;
+ if (!strcmp (filter, "patterns"))
+ index = 5;
+ assert (index != -1);
+ impl->m_combo->setActive (index);
+}
+
+void YGPackageSelector::searchFor (Ypp::PoolQuery::StringAttribute attrb, const std::string &text)
+{
+ impl->clearQueryWidgets();
+ impl->m_entry->setText (attrb, text);
+ impl->refreshQuery();
+}
+
+void YGPackageSelector::popupChanges()
+{ impl->m_undo->popupDialog (false); }
+
+void YGPackageSelector::filterPkgSuffix (const std::string &suffix, bool enable)
+{
+ impl->m_filterSuffices.remove (suffix);
+ if (enable)
+ impl->m_filterSuffices.push_back (suffix);
+ if (Ypp::getInterface() == impl) // inited ?
+ impl->refreshQuery();
+}
+
+void YGPackageSelector::showRepoManager()
+{ YGUI::ui()->sendEvent (new YMenuEvent ("repo_mgr")); }
+
+void YGPackageSelector::showHistoryDialog()
+{
+ if (!m_historyDialog)
+ m_historyDialog = new YGtkPkgHistoryDialog();
+ m_historyDialog->popup();
+}
+
+#ifdef HAS_VESTIGIAL_DIALOG
+void YGPackageSelector::showVestigialDialog()
+{
+ if (!m_vestigialDialog)
+ m_vestigialDialog = new YGtkPkgVestigialDialog();
+ m_vestigialDialog->popup();
+}
+#endif
+
+YGtkPkgUndoList *YGPackageSelector::undoList()
+{ return impl->m_undo; }
+
+YGtkPkgSearchEntry *YGPackageSelector::getSearchEntry()
+{ return impl->m_entry; }
+
+bool YGPackageSelector::yield()
+{
+ static int _id = 0;
+ int id = ++_id;
+ while (g_main_context_iteration (NULL, FALSE)) ;
+ return id != _id;
+}
+
+#include "pkg/YGPackageSelectorPluginImpl.h"
+
+YPackageSelector *
+YGPackageSelectorPluginImpl::createPackageSelector (YWidget *parent, long modeFlags)
+{
+ modeFlags |= YPkg_SearchMode;
+ return new YGPackageSelector (parent, modeFlags);
+}
+
+YWidget *
+YGPackageSelectorPluginImpl::createPatternSelector (YWidget *parent, long modeFlags)
+{
+ modeFlags &= YPkg_SearchMode;
+ return new YGPackageSelector (parent, modeFlags);
+}
+
+YWidget *
+YGPackageSelectorPluginImpl::createSimplePatchSelector (YWidget *parent, long modeFlags)
+{
+ modeFlags |= YPkg_OnlineUpdateMode;
+ return new YGPackageSelector (parent, modeFlags);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelector.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,68 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YPackageSelector is implemented as a singleton, allowing
+ intercommunication of the widgets that compound it.
+*/
+
+#ifndef YGTK_PACKAGE_SELECTOR_H
+#define YGTK_PACKAGE_SELECTOR_H
+
+#include
+#include "YGWidget.h"
+#include "yzyppwrapper.h"
+
+//#define HAS_VESTIGIAL_DIALOG
+
+struct YGtkPkgUndoList;
+struct YGtkPkgSearchEntry;
+struct YGtkPkgHistoryDialog;
+struct YGtkPkgVestigialDialog;
+
+class YGPackageSelector : public YPackageSelector, YGWidget
+{
+public:
+ YGPackageSelector (YWidget *parent, long mode);
+ virtual ~YGPackageSelector();
+
+ static YGPackageSelector *get() { return singleton; }
+
+ void apply();
+ void cancel();
+
+ void showFilterWidget (const char *filter);
+ void searchFor (Ypp::PoolQuery::StringAttribute attrb, const std::string &text);
+ void popupChanges();
+ void filterPkgSuffix (const std::string &suffix, bool enable_filter);
+ void showRepoManager();
+
+ void showHistoryDialog();
+#ifdef HAS_VESTIGIAL_DIALOG
+ void showVestigialDialog();
+#endif
+
+ YGtkPkgUndoList *undoList();
+ YGtkPkgSearchEntry *getSearchEntry();
+
+ // let the UI function while processing something; returns 'true' if the
+ // function was called again while the UI was 'breathing' -- in which case
+ // you probably want to return.
+ bool yield();
+
+ YGWIDGET_IMPL_COMMON (YPackageSelector)
+
+ struct Impl;
+ Impl *impl;
+
+private:
+ static YGPackageSelector *singleton;
+
+ YGtkPkgHistoryDialog *m_historyDialog;
+#ifdef HAS_VESTIGIAL_DIALOG
+ YGtkPkgVestigialDialog *m_vestigialDialog;
+#endif
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,12 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include "pkg/YGPackageSelectorPluginImpl.h"
+
+extern "C"
+{
+ // Important to locate this symbol - see YGPackageSelectorPluginStub.cc
+ YGPackageSelectorPluginImpl PSP;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/YGPackageSelectorPluginImpl.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,22 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGPACKAGE_SELECTOR_PLUGIN_IMPL_H
+#define YGPACKAGE_SELECTOR_PLUGIN_IMPL_H
+
+struct YPackageSelector;
+struct YWidget;
+
+#include "YGPackageSelectorPluginIf.h"
+
+class YGPackageSelectorPluginImpl : public YGPackageSelectorPluginIf
+{
+public:
+ virtual YPackageSelector *createPackageSelector (YWidget *parent, long modeFlags);
+ virtual YWidget *createPatternSelector (YWidget *parent, long modeFlags);
+ virtual YWidget *createSimplePatchSelector (YWidget *parent, long modeFlags);
+};
+
+#endif /*YGPACKAGE_SELECTOR_PLUGIN_IMPL_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/pkg-selector-help.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/pkg-selector-help.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/pkg-selector-help.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/pkg-selector-help.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,105 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+
+const char *pkg_help[] = {
+ _("<h1>Purpose</h1>"
+ "<p>This tool lets you install, remove, and update applications.</p>"
+ "<p>Software in &product; is broken down and distributed in the form of "
+ "packages. This way, if multiple applications require a common system file, "
+ "this system file is shipped in its own package and is installed only once "
+ "if needed. The user need not be concerned about such underlying <i>dependencies</i>. "
+ "Likewise, the plugins and other non-essential data of a given application may "
+ "be shipped in their own packages, so the user may install them only if needed.</p>"),
+ _("<p>Common suffixes for complementory packages:</p>"
+ "<ul>"
+ "<li><b>-plugin-</b>: extends the application with extra functionality.</li>"
+ "<li><b>-devel</b>: headers for software development.</li>"
+ "<li><b>-debuginfo</b>: debug symbols for software testing.</li>"
+ "<li><b>-fr</b>, <b>-pl</b> or other language siglas: translation files (your language "
+ "will be marked for installation automatically when needed).</li>"
+ "</ul>"),
+ _("<p>Both the packages that are installed on your system, and the packages "
+ "that are available from the <i>repositories</i> you have configured will be listed "
+ "together. <i>Status</i> filters are available in the right-bottom box.</p>"),
+ _("<blockquote>A repository is a packages media; it can either be local (such as the "
+ "installation CD), or a remote internet server. You can find an utility to setup "
+ "repositories on the YaST control center, which can also be accessed via the "
+ "<b>Configuration > Repositories</b> menu item.</blockquote>"),
+ _("<h1>Usage</h1>"),
+ _("<h2>Install, Upgrade, Remove, Undo tab pages</h2>"
+ "<p>All packages are listed together unless you have selected a <i>status</i> filter "
+ "from the right-bottom box. The check-box next to the package name indicates whether "
+ "the package is installed or not. If a more recent version of an installed "
+ "package is available, the version text will be highlighted in blue and an "
+ "upgrade button conveniently placed next to it. It is highlighted red if the "
+ "version installed is no longer being made available in any configured repository.</p>"
+ "<p>The context menu (right click on a package) provides extra options. "
+ "The <b>Undo</b> option can be used to revert any changes you have made. Multiple "
+ "packages may be selected (using the Control key) and modified together.</p>"
+ "<p>Use the <b>Version</b> list over the description box to select a specific version "
+ "of a package.</p>"
+ "<p>Press the <b>Apply</b> button when you want your changes to be performed.</p>"),
+ _("<h2>Lock software</h2>"
+ "<p>Packages can be locked against automatic changes via the context menu.</p>"
+ "<p>Locking is only useful in very unusual cases: for instance, you may not want "
+ "to install a given driver because it interferes with your system, yet you want "
+ "to install some collection that includes it. Locks can be applied whether the "
+ "package is installed or not.</p>"),
+ _("<h2>Filters</h2>"),
+ _("<h3>Search</h3>"
+ "<p>Enter free text into the search-field to match their names and descriptions. "
+ "(a search for 'office' will bring up the 'LibreOffice' packages as well as "
+ "'AbiWord' which carries the word 'office' in its description). You can search for "
+ "multiple keywords by separating the with a white space (e.g. 'spread sheet' "
+ "would return 'libreoffice-calc').You may use the "
+ "search combined with a filter, like searching for a package in a given repository. "
+ "Other search attributes are provided, such as to search for a given file.</p>"),
+ _("<h3>Groups</h3>"
+ "<p>Software for &product; is indexed so that you can find software for a specific "
+ "task when you are not aware of the software selection available. A more detailed, "
+ "hierarchical classification is provided by the <b>RPM Groups</b> filter.</p>"),
+ _("<h3>Patterns and Languages</h3>"
+ "<p><b>Patterns</b> are task-oriented collections of multiple packages that "
+ "install like one. The installation of the <i>File Server</i> pattern, for example, "
+ "will install various packages needed for running such a server.</p>"
+ "<p>If you want to install a particular language, you may want to do so via the "
+ "<b>Language</b> tool from the YaST control center.</p>"),
+ _("<h2>Software details in the box below</h2>"
+ "<p>Explore the available information about the package in the box below. Note "
+ "that more information is available for installed packages than for those only "
+ "available from a repository.</p>"
+ "<p>You can also pick a specific version of the package to install from this "
+ "box.</p>"),
+ "<hr/><p>http://en.opensuse.org/YaST2-GTK</p>",
+ 0
+};
+
+const char *patch_help[] = {
+ _("<h1>Purpose</h1>"
+ "<p>This tool gives you control on overviewing and picking patches. You may also "
+ "reverse patches that have been applied to the system.</p>"),
+ _("<h1>Usage</h1>"
+ "<h2>Categories</h2>"
+ "<p>Patches are grouped as follows:</p>"
+ "<ul>"
+ "<li><b>Security</b>: patches a software flaw that could be exploited to gain "
+ "restricted privilege.</li>"
+ "<li><b>Recommended</b>: fixes non-security related flaws (e.g. data corruption, "
+ "performance slowdown)</li>"
+ "<li><b>Optional</b>: ones that only apply to few users.</li>"
+ "<li><b>Documentation</b>: fixes documentation errors.</li>"
+ "<li><b>YaST</b>: patches for the YaST control center tools.</li>"
+ "</ul>"),
+ _("<p>Only patches that apply to your system will be visible. You can be sure "
+ "that the decision to make a patch available is not done trivially.</p>"
+ "<p>If you are looking for applications enhancements, you should check for <i>upgrades</i> "
+ "on the <b>Software Manager</b>.</p>"),
+ 0
+};
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.c
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.c?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.c (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.c Mon Aug 1 09:44:45 2011
@@ -0,0 +1,329 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkCellRendererButton widget */
+// check the header file for information about this widget
+
+#include "ygtkcellrendererbutton.h"
+#include
+
+#define INNER_BORDER 4
+#define OUTER_BORDER 1
+#define BORDER (INNER_BORDER+OUTER_BORDER)
+#define DEPRESS_PAD 1
+#define PIXBUF_TEXT_SPACING 4
+
+enum {
+ PROP_0,
+ PROP_ACTIVE,
+ PROP_PIXBUF,
+ PROP_ICON_NAME,
+ PROP_STOCK_ID,
+ PROP_ICON_SIZE,
+};
+
+static guint toggle_cell_signal = 0;
+
+G_DEFINE_TYPE (YGtkCellRendererButton, ygtk_cell_renderer_button, GTK_TYPE_CELL_RENDERER_TEXT)
+
+static void ygtk_cell_renderer_button_init (YGtkCellRendererButton *bcell)
+{
+ bcell->active = FALSE;
+ GtkCellRenderer *cell = GTK_CELL_RENDERER (bcell);
+ cell->xpad = BORDER;
+ cell->ypad = BORDER;
+ cell->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
+ bcell->icon_size = 16;
+}
+
+static void unset_image_properties (YGtkCellRendererButton *cell)
+{
+ if (cell->icon_name) {
+ g_free (cell->icon_name);
+ cell->icon_name = NULL;
+ }
+ if (cell->pixbuf) {
+ g_object_unref (cell->pixbuf);
+ cell->pixbuf = NULL;
+ }
+}
+
+static void ygtk_cell_renderer_button_finalize (GObject *object)
+{
+ YGtkCellRendererButton *ccell = YGTK_CELL_RENDERER_BUTTON (object);
+ unset_image_properties (ccell);
+ G_OBJECT_CLASS (ygtk_cell_renderer_button_parent_class)->finalize (object);
+}
+
+static void ygtk_cell_renderer_button_get_property (GObject *object,
+ guint param_id, GValue *value, GParamSpec *pspec)
+{
+ if (pspec->owner_type == YGTK_TYPE_CELL_RENDERER_BUTTON) {
+ YGtkCellRendererButton *bcell = YGTK_CELL_RENDERER_BUTTON (object);
+ switch (param_id) {
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, bcell->active);
+ break;
+ case PROP_PIXBUF:
+ g_value_set_object (value, G_OBJECT (bcell->pixbuf));
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value, bcell->stock_id);
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value, bcell->icon_name);
+ break;
+ case PROP_ICON_SIZE:
+ g_value_set_uint (value, bcell->icon_size);
+ break;
+ }
+ }
+ else
+ G_OBJECT_CLASS (ygtk_cell_renderer_button_parent_class)->get_property (
+ object, param_id, value, pspec);
+}
+
+static void ygtk_cell_renderer_button_set_property (GObject *object,
+ guint param_id, const GValue *value, GParamSpec *pspec)
+{
+ if (pspec->owner_type == YGTK_TYPE_CELL_RENDERER_BUTTON) {
+ YGtkCellRendererButton *bcell = YGTK_CELL_RENDERER_BUTTON (object);
+ switch (param_id) {
+ case PROP_ACTIVE:
+ bcell->active = g_value_get_boolean (value);
+ break;
+ case PROP_PIXBUF:
+ unset_image_properties (bcell);
+ bcell->pixbuf = (GdkPixbuf *) g_value_dup_object (value);
+ break;
+ case PROP_STOCK_ID:
+ unset_image_properties (bcell);
+ bcell->stock_id = g_value_dup_string (value);
+ break;
+ case PROP_ICON_NAME:
+ unset_image_properties (bcell);
+ bcell->icon_name = g_value_dup_string (value);
+ break;
+ case PROP_ICON_SIZE:
+ bcell->icon_size = g_value_get_uint (value);
+ break;
+ }
+ }
+ else
+ G_OBJECT_CLASS (ygtk_cell_renderer_button_parent_class)->set_property (
+ object, param_id, value, pspec);
+}
+
+static PangoLayout *create_layout (YGtkCellRendererButton *bcell, GtkWidget *widget)
+{
+ GtkCellRendererText *tcell = GTK_CELL_RENDERER_TEXT (bcell);
+ if (tcell->text)
+ return gtk_widget_create_pango_layout (widget, tcell->text);
+ return NULL;
+}
+
+static void ensure_pixbuf (YGtkCellRendererButton *cell, GtkWidget *widget)
+{
+ if ((cell->icon_name || cell->stock_id) && !cell->pixbuf) {
+ if (cell->icon_name) {
+ GtkIconTheme *theme = gtk_icon_theme_get_default();
+ GError *error = 0;
+ cell->pixbuf = gtk_icon_theme_load_icon (theme, cell->icon_name,
+ cell->icon_size, GTK_ICON_LOOKUP_FORCE_SIZE, &error);
+ if (!cell->pixbuf)
+ g_warning ("Couldn't load ygtk-cell-renderer-button icon: %s\nGtk: %s\n",
+ cell->icon_name, error->message);
+ }
+ else // stock-id
+ cell->pixbuf = gtk_widget_render_icon (widget, cell->stock_id,
+ GTK_ICON_SIZE_BUTTON, "button");
+ }
+}
+
+static void ygtk_cell_renderer_button_get_size_full (GtkCellRenderer *cell,
+ GtkWidget *widget, GdkRectangle *cell_area, gint *_xoffset, gint *_yoffset,
+ gint *_width, gint *_height, gint *_pixbuf_xoffset, gint *_pixbuf_yoffset,
+ gint *_pixbuf_width, gint *_pixbuf_height, gint *_text_xoffset, gint *_text_yoffset)
+{
+ YGtkCellRendererButton *bcell = YGTK_CELL_RENDERER_BUTTON (cell);
+ ensure_pixbuf (bcell, widget);
+
+ int pixbuf_width = 0, pixbuf_height = 0;
+ if (bcell->pixbuf) {
+ pixbuf_width = gdk_pixbuf_get_width (bcell->pixbuf);
+ pixbuf_height = gdk_pixbuf_get_height (bcell->pixbuf);
+ }
+
+ PangoLayout *layout = create_layout (bcell, widget);
+ int text_width = 0, text_height = 0;
+ if (layout) {
+ PangoRectangle rect;
+ pango_layout_get_pixel_extents (layout, NULL, &rect);
+ text_width = rect.x + rect.width;
+ text_height = rect.y + rect.height;
+ }
+
+ int width, height;
+ width = pixbuf_width + text_width;
+ if (pixbuf_width && text_width)
+ width += PIXBUF_TEXT_SPACING;
+ height = MAX (pixbuf_height, text_height);
+
+ if (cell_area) {
+ gboolean reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
+ gfloat xalign = cell->xalign, yalign = cell->yalign;
+ if (reverse)
+ xalign = 1.0 - xalign;
+
+ int cell_width = cell_area->width - cell->xpad*2,
+ cell_height = cell_area->height - cell->ypad*2;
+ int xoffset = (xalign * (cell_width - width)) + cell->xpad;
+ int yoffset = (yalign * (cell_height - height)) + cell->ypad;
+ if (_xoffset) *_xoffset = xoffset;
+ if (_yoffset) *_yoffset = yoffset;
+
+ int text_x = xoffset, text_y;
+ if (pixbuf_width && !reverse)
+ text_x += (pixbuf_width + PIXBUF_TEXT_SPACING);
+ text_y = (yalign * (cell_height - text_height)) + cell->ypad;
+
+ int pixbuf_x = xoffset, pixbuf_y;
+ if (text_width && reverse)
+ pixbuf_x += (text_width + PIXBUF_TEXT_SPACING);
+ pixbuf_y = (yalign * (cell_height - pixbuf_height)) + cell->ypad;
+
+ if (_pixbuf_xoffset) *_pixbuf_xoffset = pixbuf_x;
+ if (_pixbuf_yoffset) *_pixbuf_yoffset = pixbuf_y;
+ if (_pixbuf_width) *_pixbuf_width = pixbuf_width;
+ if (_pixbuf_height) *_pixbuf_height = pixbuf_height;
+ if (_text_xoffset) *_text_xoffset = text_x;
+ if (_text_yoffset) *_text_yoffset = text_y;
+ }
+
+ if (_width) *_width = width + (cell->xpad * 2);
+ if (_height) *_height = height + (cell->ypad * 2);
+}
+
+static void ygtk_cell_renderer_button_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget, GdkRectangle *cell_area, gint *xoffset, gint *yoffset,
+ gint *width, gint *height)
+{
+ ygtk_cell_renderer_button_get_size_full (cell, widget, cell_area,
+ xoffset, yoffset, width, height, NULL, NULL, NULL, NULL, NULL, NULL);
+}
+
+static void ygtk_cell_renderer_button_render (GtkCellRenderer *cell,
+ GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area,
+ GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags)
+{
+ YGtkCellRendererButton *bcell = YGTK_CELL_RENDERER_BUTTON (cell);
+
+ gboolean has_focus = FALSE;
+ if (flags & GTK_CELL_RENDERER_SELECTED)
+ has_focus = GTK_WIDGET_HAS_FOCUS (widget);
+
+ GtkStateType state = GTK_STATE_NORMAL;
+ if (!cell->sensitive || GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE)
+ state = GTK_STATE_INSENSITIVE;
+ else if ((flags & GTK_CELL_RENDERER_PRELIT))
+ state = GTK_STATE_PRELIGHT;
+
+ GtkShadowType shadow = GTK_SHADOW_OUT;
+ if (bcell->active) {
+ shadow = GTK_SHADOW_IN;
+ state = GTK_STATE_ACTIVE;
+ }
+
+ int text_xoffset, text_yoffset, pixbuf_xoffset, pixbuf_yoffset, pixbuf_width,
+ pixbuf_height, width, height;
+ ygtk_cell_renderer_button_get_size_full (cell, widget, cell_area,
+ NULL, NULL, &width, &height, &pixbuf_xoffset, &pixbuf_yoffset, &pixbuf_width,
+ &pixbuf_height, &text_xoffset, &text_yoffset);
+
+ int x = cell_area->x + OUTER_BORDER + 1;
+ int y = cell_area->y + (cell_area->height - height)/2 + OUTER_BORDER;
+ width -= OUTER_BORDER*2; height -= OUTER_BORDER*2;
+
+ gtk_paint_box (widget->style, window, state, shadow, expose_area, widget,
+ "button", x, y, width, height);
+
+ int cell_area_x = cell_area->x, cell_area_y = cell_area->y;
+ if (bcell->active) {
+ cell_area->x += DEPRESS_PAD;
+ cell_area->y += DEPRESS_PAD;
+ }
+
+ // paint
+ ensure_pixbuf (bcell, widget);
+ if (bcell->pixbuf) {
+ int x = cell_area->x + pixbuf_xoffset, y = cell_area->y + pixbuf_yoffset;
+ cairo_t *cr = gdk_cairo_create (window);
+ gdk_cairo_set_source_pixbuf (cr, bcell->pixbuf, x, y);
+ cairo_rectangle (cr, x, y, pixbuf_width, pixbuf_height);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+ }
+
+ PangoLayout *layout = create_layout (bcell, widget);
+ if (layout) {
+ int x = cell_area->x + text_xoffset, y = cell_area->y + text_yoffset;
+ GtkStyle *style = gtk_widget_get_style (widget);
+ gtk_paint_layout (style, window, state, TRUE, expose_area, widget,
+ "cellrenderertext", x, y, layout);
+ g_object_unref (G_OBJECT (layout));
+ }
+
+ cell_area->x = cell_area_x; cell_area->y = cell_area_y;
+}
+
+static gboolean ygtk_cell_renderer_button_activate (GtkCellRenderer *cell,
+ GdkEvent *event, GtkWidget *widget, const gchar *path, GdkRectangle *background_area,
+ GdkRectangle *cell_area, GtkCellRendererState flags)
+{
+ GdkEventButton *_event = &event->button;
+ if (_event->x >= cell_area->x && _event->x <= cell_area->x + cell_area->width) {
+ g_signal_emit (cell, toggle_cell_signal, 0, path);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+GtkCellRenderer *ygtk_cell_renderer_button_new (void)
+{ return g_object_new (YGTK_TYPE_CELL_RENDERER_BUTTON, NULL); }
+
+gboolean ygtk_cell_renderer_button_get_active (YGtkCellRendererButton *cell)
+{ return cell->active; }
+
+static void ygtk_cell_renderer_button_class_init (YGtkCellRendererButtonClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ object_class->get_property = ygtk_cell_renderer_button_get_property;
+ object_class->set_property = ygtk_cell_renderer_button_set_property;
+ object_class->finalize = ygtk_cell_renderer_button_finalize;
+
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+ cell_class->get_size = ygtk_cell_renderer_button_get_size;
+ cell_class->render = ygtk_cell_renderer_button_render;
+ cell_class->activate = ygtk_cell_renderer_button_activate;
+
+ GParamFlags readwrite_flag =
+ G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB;
+ g_object_class_install_property (object_class, PROP_ACTIVE,
+ g_param_spec_boolean ("active", "Toggle state", "The toggle state of the button",
+ FALSE, readwrite_flag));
+ g_object_class_install_property (object_class, PROP_PIXBUF,
+ g_param_spec_object ("pixbuf", "Image", "Side image", GDK_TYPE_PIXBUF, readwrite_flag));
+ g_object_class_install_property (object_class, PROP_ICON_NAME,
+ g_param_spec_string ("icon-name", "Icon name", "Theme icon to render", NULL, readwrite_flag));
+ g_object_class_install_property (object_class, PROP_STOCK_ID,
+ g_param_spec_string ("stock-id", "Stock id", "Stock icon to render", NULL, readwrite_flag));
+ g_object_class_install_property (object_class, PROP_ICON_SIZE,
+ g_param_spec_uint ("icon-size", "Size", "Size of the icon to render",
+ 0, G_MAXUINT, 22, readwrite_flag));
+
+ toggle_cell_signal = g_signal_new ("toggled", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (YGtkCellRendererButtonClass, toggled),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrendererbutton.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,51 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* GtkButton meets GtkCellRenderer.
+*/
+
+#ifndef YGTK_CELL_RENDERER_BUTTON_H
+#define YGTK_CELL_RENDERER_BUTTON_H
+
+#include
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_CELL_RENDERER_BUTTON (ygtk_cell_renderer_button_get_type ())
+#define YGTK_CELL_RENDERER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_CELL_RENDERER_BUTTON, YGtkCellRendererButton))
+#define YGTK_CELL_RENDERER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_CELL_RENDERER_BUTTON, YGtkCellRendererButtonClass))
+#define YGTK_IS_CELL_RENDERER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_CELL_RENDERER_BUTTON))
+#define YGTK_IS_CELL_RENDERER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_CELL_RENDERER_BUTTON))
+#define YGTK_CELL_RENDERER_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_CELL_RENDERER_BUTTON, YGtkCellRendererButtonClass))
+
+typedef struct _YGtkCellRendererButton
+{
+ GtkCellRendererText parent;
+
+ // private:
+ GdkPixbuf *pixbuf;
+ gchar *icon_name, *stock_id;
+ gint icon_size;
+ guint active : 2;
+} YGtkCellRendererButton;
+
+typedef struct _YGtkCellRendererButtonClass
+{
+ GtkCellRendererTextClass parent_class;
+
+ void (* toggled) (YGtkCellRendererButton *renderer, const gchar *path);
+} YGtkCellRendererButtonClass;
+
+GtkCellRenderer *ygtk_cell_renderer_button_new (void);
+GType ygtk_cell_renderer_button_get_type (void) G_GNUC_CONST;
+
+gboolean ygtk_cell_renderer_button_get_active (YGtkCellRendererButton *cell);
+
+G_END_DECLS
+#endif /*YGTK_CELL_RENDERER_BUTTON_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.c
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.c?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.c (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.c Mon Aug 1 09:44:45 2011
@@ -0,0 +1,221 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkCellRendererSideButton widget */
+// check the header file for information about this widget
+
+#include "ygtkcellrenderersidebutton.h"
+#include
+
+enum {
+ PROP_0,
+ PROP_ACTIVE,
+ PROP_STOCK_ID,
+ PROP_BUTTON_VISIBLE,
+};
+
+static guint toggle_cell_signal = 0;
+
+G_DEFINE_TYPE (YGtkCellRendererSideButton, ygtk_cell_renderer_side_button, GTK_TYPE_CELL_RENDERER_TEXT)
+
+static void ygtk_cell_renderer_side_button_init (YGtkCellRendererSideButton *bcell)
+{ GTK_CELL_RENDERER (bcell)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; }
+
+static void free_pixbuf (YGtkCellRendererSideButton *cell)
+{
+ if (cell->stock_id) {
+ g_free (cell->stock_id);
+ cell->stock_id = NULL;
+ }
+ if (cell->pixbuf) {
+ g_object_unref (cell->pixbuf);
+ cell->pixbuf = NULL;
+ }
+}
+
+static void ensure_pixbuf (YGtkCellRendererSideButton *cell, GtkWidget *widget)
+{
+ if (!cell->pixbuf && cell->stock_id)
+ cell->pixbuf = gtk_widget_render_icon (widget, cell->stock_id, GTK_ICON_SIZE_BUTTON, NULL);
+}
+
+static void ygtk_cell_renderer_side_button_finalize (GObject *object)
+{
+ YGtkCellRendererSideButton *bcell = YGTK_CELL_RENDERER_SIDE_BUTTON (object);
+ free_pixbuf (bcell);
+ G_OBJECT_CLASS (ygtk_cell_renderer_side_button_parent_class)->finalize (object);
+}
+
+static void ygtk_cell_renderer_side_button_get_property (
+ GObject *object, guint param_id, GValue *value, GParamSpec *pspec)
+{
+ if (pspec->owner_type == YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON) {
+ YGtkCellRendererSideButton *bcell = YGTK_CELL_RENDERER_SIDE_BUTTON (object);
+ switch (param_id) {
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, bcell->active);
+ break;
+ case PROP_STOCK_ID:
+ g_value_set_string (value, bcell->stock_id);
+ break;
+ case PROP_BUTTON_VISIBLE:
+ g_value_set_boolean (value, bcell->button_visible);
+ break;
+ }
+ }
+ else
+ G_OBJECT_CLASS (ygtk_cell_renderer_side_button_parent_class)->get_property (
+ object, param_id, value, pspec);
+}
+
+static void ygtk_cell_renderer_side_button_set_property (GObject *object,
+ guint param_id, const GValue *value, GParamSpec *pspec)
+{
+ if (pspec->owner_type == YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON) {
+ YGtkCellRendererSideButton *bcell = YGTK_CELL_RENDERER_SIDE_BUTTON (object);
+ switch (param_id) {
+ case PROP_ACTIVE:
+ bcell->active = g_value_get_boolean (value);
+ break;
+ case PROP_STOCK_ID:
+ free_pixbuf (bcell);
+ bcell->stock_id = g_value_dup_string (value);
+ break;
+ case PROP_BUTTON_VISIBLE:
+ bcell->button_visible = g_value_get_boolean (value);
+ break;
+ }
+ }
+ else
+ G_OBJECT_CLASS (ygtk_cell_renderer_side_button_parent_class)->set_property (
+ object, param_id, value, pspec);
+}
+
+static void ygtk_cell_renderer_side_button_get_size (
+ GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *cell_area,
+ gint *x_offset, gint *y_offset, gint *width, gint *height)
+{
+ GTK_CELL_RENDERER_CLASS (ygtk_cell_renderer_side_button_parent_class)->get_size (
+ cell, widget, cell_area, x_offset, y_offset, width, height);
+ YGtkCellRendererSideButton *bcell = YGTK_CELL_RENDERER_SIDE_BUTTON (cell);
+ if (bcell->button_visible) {
+ gint icon_width, icon_height;
+ gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, &icon_width, &icon_height);
+ *width += icon_width + 8 + 4;
+ }
+}
+
+static void ygtk_cell_renderer_side_button_render (
+ GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget,
+ GdkRectangle *background_area, GdkRectangle *cell_area,
+ GdkRectangle *expose_area, GtkCellRendererState flags)
+{
+ YGtkCellRendererSideButton *bcell = YGTK_CELL_RENDERER_SIDE_BUTTON (cell);
+ GdkRectangle text_area = *cell_area;
+ gint icon_width, icon_height;
+ if (bcell->button_visible) {
+ gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, &icon_width, &icon_height);
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ text_area.x += icon_width + 8;
+ text_area.width -= icon_width + 8 + 4;
+ }
+ GTK_CELL_RENDERER_CLASS (ygtk_cell_renderer_side_button_parent_class)->render (
+ cell, window, widget, background_area, &text_area, expose_area, flags);
+
+ if (bcell->button_visible) {
+ GtkStateType state = GTK_STATE_NORMAL;
+ GtkShadowType shadow = GTK_SHADOW_OUT;
+ if (!cell->sensitive || GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE)
+ state = GTK_STATE_INSENSITIVE;
+ /* else if ((flags & GTK_CELL_RENDERER_PRELIT))
+ state = GTK_STATE_PRELIGHT;*/
+ if (bcell->active) {
+ shadow = GTK_SHADOW_IN;
+ state = GTK_STATE_ACTIVE;
+ }
+
+ GdkRectangle button_area = *cell_area;
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ button_area.x = cell_area->x + 2;
+ else
+ button_area.x = cell_area->x + cell_area->width - icon_width - 8;
+ button_area.width = icon_width + 4;
+ button_area.height = icon_height + 4;
+ button_area.y = cell_area->y + ((cell_area->height - button_area.height) / 2);
+ gtk_paint_box (widget->style, window, state, shadow, expose_area, widget,
+ "button", button_area.x, button_area.y, button_area.width, button_area.height);
+
+ GdkRectangle icon_area = button_area;
+ icon_area.x += 2;
+ icon_area.y += 2;
+ if (bcell->active) {
+ cell_area->x += 2;
+ cell_area->y += 2;
+ }
+
+ ensure_pixbuf (bcell, widget);
+ cairo_t *cr = gdk_cairo_create (window);
+ gdk_cairo_set_source_pixbuf (cr, bcell->pixbuf, icon_area.x, icon_area.y);
+ cairo_rectangle (cr, icon_area.x, icon_area.y, icon_width, icon_height);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+ }
+}
+
+static gboolean ygtk_cell_renderer_side_button_activate (
+ GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path,
+ GdkRectangle *background_area, GdkRectangle *cell_area, GtkCellRendererState flags)
+{
+ YGtkCellRendererSideButton *bcell = YGTK_CELL_RENDERER_SIDE_BUTTON (cell);
+ if (bcell->button_visible) {
+ GdkEventButton *_event = (GdkEventButton *) event;
+ gint icon_width, icon_height;
+ gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, &icon_width, &icon_height);
+ int icon_x, x = _event->x - cell_area->x;
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ icon_x = 2;
+ else
+ icon_x = cell_area->width - (icon_width+12);
+ icon_width += 8;
+ if (x >= icon_x && x <= icon_x + icon_width) {
+ g_signal_emit (cell, toggle_cell_signal, 0, path);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+GtkCellRenderer *ygtk_cell_renderer_side_button_new (void)
+{ return g_object_new (YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON, NULL); }
+
+gboolean ygtk_cell_renderer_side_button_get_active (YGtkCellRendererSideButton *cell)
+{ return cell->active; }
+
+static void ygtk_cell_renderer_side_button_class_init (YGtkCellRendererSideButtonClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ object_class->get_property = ygtk_cell_renderer_side_button_get_property;
+ object_class->set_property = ygtk_cell_renderer_side_button_set_property;
+ object_class->finalize = ygtk_cell_renderer_side_button_finalize;
+
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+ cell_class->get_size = ygtk_cell_renderer_side_button_get_size;
+ cell_class->render = ygtk_cell_renderer_side_button_render;
+ cell_class->activate = ygtk_cell_renderer_side_button_activate;
+
+ GParamFlags readwrite_flag =
+ G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB;
+ g_object_class_install_property (object_class, PROP_ACTIVE,
+ g_param_spec_boolean ("active", "Toggle state", "The toggle state of the button",
+ FALSE, readwrite_flag));
+ g_object_class_install_property (object_class, PROP_STOCK_ID,
+ g_param_spec_string ("stock-id", "Stock ID", "Stock icon to render", NULL, readwrite_flag));
+ g_object_class_install_property (object_class, PROP_BUTTON_VISIBLE,
+ g_param_spec_boolean ("button-visible", "Is Button Visible", "Whether to show side button", TRUE, readwrite_flag));
+
+ toggle_cell_signal = g_signal_new ("toggled", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (YGtkCellRendererSideButtonClass, toggled),
+ NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderersidebutton.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,50 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* A icon GtkButton next to a GtkLabel.
+*/
+
+#ifndef YGTK_CELL_RENDERER_SIDE_BUTTON_H
+#define YGTK_CELL_RENDERER_SIDE_BUTTON_H
+
+#include
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON (ygtk_cell_renderer_side_button_get_type())
+#define YGTK_CELL_RENDERER_SIDE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON, YGtkCellRendererSideButton))
+#define YGTK_CELL_RENDERER_SIDE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON, YGtkCellRendererSideButtonClass))
+#define YGTK_IS_CELL_RENDERER_SIDE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON))
+#define YGTK_IS_CELL_RENDERER_SIDE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON))
+#define YGTK_CELL_RENDERER_SIDE_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_CELL_RENDERER_SIDE_BUTTON, YGtkCellRendererSideButtonClass))
+
+typedef struct YGtkCellRendererSideButton
+{
+ GtkCellRendererText parent;
+
+ // private:
+ guint active : 2, button_visible : 2;
+ gchar *stock_id;
+ GdkPixbuf *pixbuf;
+} YGtkCellRendererSideButton;
+
+typedef struct YGtkCellRendererSideButtonClass
+{
+ GtkCellRendererTextClass parent_class;
+
+ void (* toggled) (YGtkCellRendererSideButton *renderer, const gchar *path);
+} YGtkCellRendererSideButtonClass;
+
+GtkCellRenderer *ygtk_cell_renderer_side_button_new (void);
+GType ygtk_cell_renderer_side_button_get_type (void) G_GNUC_CONST;
+
+gboolean ygtk_cell_renderer_side_button_get_active (YGtkCellRendererSideButton *cell);
+
+G_END_DECLS
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.c
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.c?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.c (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.c Mon Aug 1 09:44:45 2011
@@ -0,0 +1,56 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkCellRendererText cell renderer */
+// check the header file for information about this cell renderer
+
+#include "ygtkcellrenderertext.h"
+#include
+#include
+
+G_DEFINE_TYPE (YGtkCellRendererText, ygtk_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT)
+
+static void ygtk_cell_renderer_text_init (YGtkCellRendererText *bcell)
+{}
+
+gboolean filter_color_cb (PangoAttribute *attrb, gpointer data)
+{
+ PangoAttrType type = attrb->klass->type;
+ return type == PANGO_ATTR_FOREGROUND || type == PANGO_ATTR_BACKGROUND;
+}
+
+static void ygtk_cell_renderer_text_render (
+ GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget,
+ GdkRectangle *background_area, GdkRectangle *cell_area,
+ GdkRectangle *expose_area, GtkCellRendererState flags)
+{
+ GtkCellRendererText *tcell = GTK_CELL_RENDERER_TEXT (cell);
+ PangoAttrList *old_extra_attrs = 0, *new_extra_attrs = 0;
+ if (flags & (GTK_CELL_RENDERER_SELECTED | GTK_CELL_RENDERER_INSENSITIVE)) {
+ old_extra_attrs = pango_attr_list_copy (tcell->extra_attrs);
+ new_extra_attrs = tcell->extra_attrs;
+
+ PangoAttrList *t = pango_attr_list_filter (tcell->extra_attrs,
+ filter_color_cb, NULL);
+ pango_attr_list_unref (t);
+ }
+
+ GTK_CELL_RENDERER_CLASS (ygtk_cell_renderer_text_parent_class)->render (
+ cell, window, widget, background_area, cell_area, expose_area, flags);
+
+ if (old_extra_attrs) {
+ tcell->extra_attrs = old_extra_attrs;
+ pango_attr_list_unref (new_extra_attrs);
+ }
+}
+
+GtkCellRenderer *ygtk_cell_renderer_text_new (void)
+{ return g_object_new (YGTK_TYPE_CELL_RENDERER_TEXT, NULL); }
+
+static void ygtk_cell_renderer_text_class_init (YGtkCellRendererTextClass *class)
+{
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+ cell_class->render = ygtk_cell_renderer_text_render;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkcellrenderertext.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,42 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkCellRendererText is a sub-class of GtkCellRendererText that
+ strips any markup in the cell when the row is selected.
+*/
+
+#ifndef YGTK_CELL_RENDERER_TEXT_H
+#define YGTK_CELL_RENDERER_TEXT_H
+
+#include
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_CELL_RENDERER_TEXT (ygtk_cell_renderer_text_get_type())
+#define YGTK_CELL_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_CELL_RENDERER_TEXT, YGtkCellRendererText))
+#define YGTK_CELL_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_CELL_RENDERER_TEXT, YGtkCellRendererTextClass))
+#define YGTK_IS_CELL_RENDERER_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_CELL_RENDERER_TEXT))
+#define YGTK_IS_CELL_RENDERER_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_CELL_RENDERER_TEXT))
+#define YGTK_CELL_RENDERER_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_CELL_TEXT, YGtkCellRendererTextClass))
+
+typedef struct YGtkCellRendererText
+{
+ GtkCellRendererText parent;
+} YGtkCellRendererText;
+
+typedef struct YGtkCellRendererTextClass
+{
+ GtkCellRendererTextClass parent_class;
+} YGtkCellRendererTextClass;
+
+GtkCellRenderer *ygtk_cell_renderer_text_new (void);
+GType ygtk_cell_renderer_text_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,1312 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgDetailView, selectable info-box */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGDialog.h"
+#include "YGUtils.h"
+#include "ygtkpkgdetailview.h"
+#include
+#include
+#include "YGPackageSelector.h"
+#include "ygtkrichtext.h"
+#include "ygtkpkgsearchentry.h"
+#include "ygtkpkglistview.h"
+#include
+
+#define BROWSER_BIN "/usr/bin/firefox"
+#define GNOME_OPEN_BIN "/usr/bin/gnome-open"
+
+static std::string onlyInstalledMsg() {
+ std::string s ("<i>");
+ s += _("Information only available for installed packages.");
+ s += "</i>";
+ return s;
+}
+
+static const char *keywordOpenTag = "<keyword>", *keywordCloseTag = "</keyword>";
+
+struct BusyOp {
+ BusyOp() {
+ YGDialog::currentDialog()->busyCursor();
+ while (g_main_context_iteration (NULL, FALSE)) ;
+ }
+ ~BusyOp() {
+ YGDialog::currentDialog()->normalCursor();
+ }
+};
+
+struct DetailWidget {
+ virtual ~DetailWidget() {}
+ virtual GtkWidget *getWidget() = 0;
+ virtual void refreshList (Ypp::List list) = 0;
+ virtual void setList (Ypp::List list) = 0;
+};
+
+struct DetailName : public DetailWidget {
+ GtkWidget *hbox, *icon, *text;
+
+ DetailName()
+ {
+ text = ygtk_rich_text_new();
+ icon = gtk_image_new();
+
+ hbox = gtk_hbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (hbox), text, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
+ }
+
+ virtual GtkWidget *getWidget()
+ { return hbox; }
+
+ virtual void refreshList (Ypp::List list)
+ {
+ std::string str;
+ str.reserve (1024);
+ if (list.size() > 0) {
+ Ypp::ListProps props (list);
+ str = "";
+ if (list.size() == 1) {
+ Ypp::Selectable &sel = list.get (0);
+ if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
+ str += sel.summary() + " - " + "<b>" + sel.name() + "</b>";
+ else
+ str += "<b>" + sel.name() + "</b> - " + sel.summary();
+ }
+ else {
+ str += "<b>";
+ str += _("Several selected");
+ str += "</b>";
+ }
+ str += "</font></p>";
+ }
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
+ }
+
+ virtual void setList (Ypp::List list)
+ {
+ gtk_widget_hide (icon);
+ if (list.size() == 1) {
+ Ypp::Selectable &sel = list.get (0);
+
+ gtk_image_clear (GTK_IMAGE (icon));
+ GtkIconTheme *icons = gtk_icon_theme_get_default();
+ GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (icons,
+ sel.name().c_str(), 32, GtkIconLookupFlags (0), NULL);
+ if (pixbuf) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (icon), pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ gtk_widget_show (icon);
+ }
+ }
+
+ refreshList (list);
+ }
+};
+
+struct DetailDescription : public DetailWidget {
+ GtkWidget *text, *popup;
+ std::string link_str;
+
+ DetailDescription() : popup (NULL)
+ {
+ text = ygtk_rich_text_new();
+ g_signal_connect (G_OBJECT (text), "link-clicked",
+ G_CALLBACK (link_clicked_cb), this);
+ }
+
+ virtual ~DetailDescription()
+ { if (popup) gtk_widget_destroy (popup); }
+
+ virtual GtkWidget *getWidget()
+ { return text; }
+
+ virtual void refreshList (Ypp::List list)
+ { setList (list); }
+
+ virtual void setList (Ypp::List list)
+ {
+ std::string str;
+ str.reserve (2048);
+ if (list.size() == 1) {
+ Ypp::Selectable &sel = list.get (0);
+ str = sel.description (true);
+
+ YGtkPkgSearchEntry *search = YGPackageSelector::get()->getSearchEntry();
+ if (search->getAttribute() == Ypp::PoolQuery::DESCRIPTION) {
+ std::list keywords;
+ keywords = YGPackageSelector::get()->getSearchEntry()->getText();
+ highlightMarkup (str, keywords, keywordOpenTag, keywordCloseTag,
+ strlen (keywordOpenTag), strlen (keywordCloseTag));
+ }
+
+ if (sel.type() == Ypp::Selectable::PACKAGE) {
+ Ypp::Package pkg (sel);
+ std::string url (pkg.url());
+ if (!url.empty()) {
+ str += "<p><i>"; str += _("Web site:");
+ str += "</i> ";
+ str += url; str += "</a></p>";
+ }
+ if (pkg.isCandidatePatch()) {
+ Ypp::Selectable _patch = pkg.getCandidatePatch();
+ Ypp::Patch patch (_patch);
+ str += "<p><i>"; str += _("Patch issued:");
+ str += "</i> "; str += _patch.summary();
+ str += " <b>("; str += Ypp::Patch::prioritySummary (patch.priority());
+ str += ")</b>"; str += "</p>";
+
+ }
+ }
+ }
+ else {
+ if (list.size() > 0) {
+ str += "<ul>";
+ for (int i = 0; i < list.size(); i++)
+ str += "<li>" + list.get (i).name() + "</li>";
+ str += "</ul>";
+ }
+ }
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
+ }
+
+ static void link_clicked_cb (YGtkRichText *text, const gchar *link, DetailDescription *pThis)
+ {
+ if (!pThis->popup) {
+ GtkWidget *menu = pThis->popup = gtk_menu_new();
+ gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (text), NULL);
+
+ GtkWidget *item;
+ if (g_file_test (BROWSER_BIN, G_FILE_TEST_IS_EXECUTABLE)) {
+ std::string label (YGUtils::mapKBAccel ("&Open"));
+ if (getuid() == 0) {
+ const char *username = getenv ("USERNAME");
+ if (!username || !(*username))
+ username = "root";
+ label += " ("; label += _("as");
+ label += " "; label += username; label += ")";
+ }
+ item = gtk_image_menu_item_new_with_mnemonic (label.c_str());
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+ gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
+ gtk_widget_show (item);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (open_link_cb), pThis);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
+ gtk_widget_show (item);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (copy_link_cb), pThis);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ }
+ gtk_menu_popup (GTK_MENU (pThis->popup), NULL, NULL, NULL, NULL,
+ 0, gtk_get_current_event_time());
+ pThis->link_str = link;
+ }
+
+ static void open_link_cb (GtkMenuItem *item, DetailDescription *pThis)
+ {
+ const std::string &link = pThis->link_str;
+ std::string command;
+ command.reserve (256);
+
+ const char *username = 0;
+ if (getuid() == 0) {
+ username = getenv ("USERNAME");
+ if (username && !(*username))
+ username = 0;
+ }
+
+ if (username) {
+ command += "gnomesu -u ";
+ command += username;
+ command += " -c \"" BROWSER_BIN " --new-window ";
+ command += link;
+ command += "\"";
+ }
+ else {
+ command += BROWSER_BIN " --new-window ";
+ command += link;
+ }
+ command += " &";
+ (void) system (command.c_str());
+ }
+
+ static void copy_link_cb (GtkMenuItem *item, DetailDescription *pThis)
+ {
+ const std::string &link = pThis->link_str;
+ GtkClipboard *clipboard =
+ gtk_widget_get_clipboard (pThis->text, GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, link.c_str(), -1);
+ }
+};
+
+struct DetailExpander : public DetailWidget {
+ GtkWidget *expander;
+ Ypp::List list;
+ bool dirty;
+
+ DetailExpander (const std::string &label, bool default_expanded)
+ : list (0), dirty (false)
+ {
+ std::string str = "<b>" + label + "</b>";
+ expander = gtk_expander_new (str.c_str());
+ gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
+ gtk_expander_set_expanded (GTK_EXPANDER (expander), default_expanded);
+ g_signal_connect_after (G_OBJECT (expander), "notify::expanded",
+ G_CALLBACK (expanded_cb), this);
+ }
+
+ virtual GtkWidget *getWidget() { return expander; }
+
+ void updateList()
+ {
+ if (dirty)
+ if (gtk_expander_get_expanded (GTK_EXPANDER (expander)))
+ if (visible()) {
+ showList (list);
+ dirty = false;
+ }
+ }
+
+ bool visible()
+ {
+ if (onlySingleList())
+ return list.size() == 1;
+ return list.size() > 0;
+ }
+
+ virtual void setList (Ypp::List list)
+ {
+ this->list = list;
+ dirty = true;
+ visible() ? gtk_widget_show (expander) : gtk_widget_hide (expander);
+ updateList();
+ }
+
+ virtual void refreshList (Ypp::List list)
+ {
+ if (gtk_expander_get_expanded (GTK_EXPANDER (expander)))
+ showRefreshList (list);
+ else
+ dirty = true;
+ }
+
+ static void expanded_cb (GObject *object, GParamSpec *param_spec, DetailExpander *pThis)
+ { pThis->updateList(); }
+
+ void setChild (GtkWidget *child)
+ { gtk_container_add (GTK_CONTAINER (expander), child); }
+
+ // use this method to only request data when/if necessary; so to speed up expander children
+ virtual void showList (Ypp::List list) = 0;
+ virtual void showRefreshList (Ypp::List list) = 0;
+ virtual bool onlySingleList() = 0; // show only when list.size()==1
+};
+
+struct DetailsExpander : public DetailExpander {
+ GtkWidget *text;
+
+ DetailsExpander()
+ : DetailExpander (_("Details"), true)
+ {
+ text = ygtk_rich_text_new();
+ gtk_widget_set_size_request (text, 160, -1);
+ setChild (text);
+ }
+
+ virtual bool onlySingleList() { return true; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::Selectable sel = list.get (0);
+ ZyppSelectable zsel = sel.zyppSel();
+ ZyppResObject zobj = zsel->theObj();
+ ZyppPackage zpkg = castZyppPackage (zobj);
+
+ std::string str;
+ std::string b ("<i>"), _b ("</i> "), i (""), _i(""), br ("<br/>");
+ str.reserve (2048);
+ str += b + _("Size:") + _b + i + zobj->installSize().asString() + _i;
+ str += br + b + _("License:") + _b + i + zpkg->license() + _i;
+ if (zsel->hasInstalledObj())
+ str += br + b + ("Installed at:") + _b + i +
+ zsel->installedObj()->installtime().form ("%x") + _i;
+ if (zsel->hasCandidateObj())
+ str += br + b + ("Latest build:") + _b + i +
+ zsel->candidateObj()->buildtime().form ("%x") + _i;
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
+ }
+
+ virtual void showRefreshList (Ypp::List list) {}
+};
+
+typedef zypp::ResPoolProxy::const_iterator ZyppPoolIterator;
+inline ZyppPoolIterator zyppSrcPkgBegin()
+{ return zyppPool().byKindBeginzypp::SrcPackage(); }
+inline ZyppPoolIterator zyppSrcPkgEnd()
+{ return zyppPool().byKindEndzypp::SrcPackage(); }
+
+struct VersionExpander : public DetailExpander {
+ GtkWidget *versions_box;
+ std::list Ypp::Version versions;
+
+ VersionExpander()
+ : DetailExpander (_("Versions"), false)
+ {
+ versions_box = gtk_vbox_new (FALSE, 2);
+
+ // draw border
+ GtkWidget *frame = gtk_frame_new (NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (frame), 2);
+ gtk_container_add (GTK_CONTAINER (frame), versions_box);
+ setChild (frame);
+ }
+
+ GtkWidget *addVersion (Ypp::Selectable &sel, Ypp::Version version, GtkWidget *group)
+ {
+ GtkWidget *button = gtk_toggle_button_new();
+ gtk_container_add (GTK_CONTAINER (button), gtk_image_new());
+
+ GtkWidget *label = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+
+ g_object_set_data (G_OBJECT (button), "nb", GINT_TO_POINTER (versions.size()));
+ updateVersionWidget (hbox, sel, version);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (button_clicked_cb), this);
+
+ GtkWidget *widget = hbox;
+ if ((versions.size() % 2) == 1)
+ g_signal_connect (G_OBJECT (widget), "expose-event",
+ G_CALLBACK (draw_gray_cb), NULL);
+ versions.push_back (version);
+ gtk_box_pack_start (GTK_BOX (versions_box), widget, FALSE, TRUE, 0);
+ return widget;
+ }
+
+ void updateVersionLabel (GtkWidget *label, Ypp::Selectable &sel, Ypp::Version &version)
+ {
+ std::string repo; bool modified;
+ if (version.isInstalled()) {
+ repo = _("Installed");
+ modified = sel.toRemove();
+ }
+ else {
+ repo = version.repository().name();
+ modified = sel.toInstall();
+ }
+ modified = modified && version.toModify();
+
+ std::string number (version.number()), arch (version.arch());
+ char *tooltip = g_strdup_printf ("%s <small>(%s)</small>\n<small>%s</small>",
+ number.c_str(), arch.c_str(), repo.c_str());
+ number = YGUtils::truncate (number, 20, 0);
+ char *str = g_strdup_printf ("%s%s <small>(%s)</small>\n<small>%s</small>%s",
+ modified ? "<i>" : "", number.c_str(), arch.c_str(), repo.c_str(),
+ modified ? "</i>" : "");
+
+ gtk_label_set_markup (GTK_LABEL (label), str);
+ if (number.size() > 20)
+ gtk_widget_set_tooltip_markup (label, tooltip);
+ g_free (tooltip); g_free (str);
+ }
+
+ void updateVersionButton (GtkWidget *button, Ypp::Selectable &sel, Ypp::Version &version)
+ {
+ const char *stock, *tooltip;
+ bool modified, can_modify = true;
+ if (version.isInstalled()) {
+ tooltip = _("Remove");
+ stock = GTK_STOCK_DELETE;
+ can_modify = sel.canRemove();
+ modified = sel.toRemove();
+ }
+ else {
+ if (sel.hasInstalledVersion()) {
+ Ypp::Version installed = sel.installed();
+ if (installed < version) {
+ tooltip = _("Upgrade");
+ stock = GTK_STOCK_GO_UP;
+ }
+ else if (installed > version) {
+ tooltip = _("Downgrade");
+ stock = GTK_STOCK_GO_DOWN;
+ }
+ else {
+ tooltip = _("Re-install");
+ stock = GTK_STOCK_REFRESH;
+ }
+ }
+ else {
+ tooltip = _("Install");
+ stock = GTK_STOCK_SAVE;
+ }
+ modified = sel.toInstall();
+ }
+ modified = modified && version.toModify();
+ if (modified)
+ tooltip = _("Undo");
+
+ g_signal_handlers_block_by_func (button, (gpointer) button_clicked_cb, this);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), modified);
+ g_signal_handlers_unblock_by_func (button, (gpointer) button_clicked_cb, this);
+ can_modify ? gtk_widget_show (button) : gtk_widget_hide (button);
+ gtk_widget_set_tooltip_text (button, tooltip);
+ gtk_image_set_from_stock (GTK_IMAGE (gtk_bin_get_child (GTK_BIN(button))),
+ stock, GTK_ICON_SIZE_BUTTON);
+ }
+
+ void updateVersionWidget (GtkWidget *widget, Ypp::Selectable &sel, Ypp::Version &version)
+ {
+ GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
+ GtkWidget *label = (GtkWidget *) children->data;
+ GtkWidget *button = (GtkWidget *) children->next->data;
+ g_list_free (children);
+
+ updateVersionLabel (label, sel, version);
+ updateVersionButton (button, sel, version);
+ }
+
+ void updateMultiselectionButton (GtkWidget *button)
+ {
+ Ypp::ListProps props (list);
+
+ const char *stock, *tooltip;
+ bool modified, hide = false;
+ if (props.isInstalled()) {
+ tooltip = _("Remove");
+ stock = GTK_STOCK_DELETE;
+ }
+ else if (props.isNotInstalled()) {
+ tooltip = _("Install");
+ stock = GTK_STOCK_SAVE;
+ }
+ else
+ hide = true;
+ modified = props.toModify();
+ if (modified)
+ tooltip = _("Undo");
+
+ g_signal_handlers_block_by_func (button, (gpointer) button_clicked_cb, this);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), modified);
+ g_signal_handlers_unblock_by_func (button, (gpointer) button_clicked_cb, this);
+ hide ? gtk_widget_hide (button) : gtk_widget_show (button);
+ gtk_widget_set_tooltip_text (button, tooltip);
+ gtk_image_set_from_stock (GTK_IMAGE (gtk_bin_get_child (GTK_BIN(button))),
+ stock, GTK_ICON_SIZE_BUTTON);
+ }
+
+ void clearVersions()
+ {
+ GList *children = gtk_container_get_children (GTK_CONTAINER (versions_box));
+ for (GList *i = children; i; i = i->next)
+ gtk_container_remove (GTK_CONTAINER (versions_box), (GtkWidget *) i->data);
+ g_list_free (children);
+ versions.clear();
+ }
+
+ Ypp::Version &getVersion (GtkToggleButton *button)
+ {
+ int nb = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "nb"));
+ std::list Ypp::Version::iterator it = versions.begin();
+ for (int i = 0; i < nb; i++) it++;
+ return *it;
+ }
+
+ static void button_clicked_cb (GtkToggleButton *button, VersionExpander *pThis)
+ {
+ BusyOp op;
+ if (gtk_toggle_button_get_active (button)) { // was un-pressed
+ if (pThis->list.size() > 1) {
+ Ypp::ListProps props (pThis->list);
+ if (props.hasUpgrade())
+ pThis->list.install();
+ else if (props.isInstalled())
+ pThis->list.remove();
+ else if (props.isNotInstalled())
+ pThis->list.install();
+ else if (props.toModify())
+ pThis->list.undo();
+ }
+ else {
+ Ypp::Selectable sel = pThis->list.get (0);
+ Ypp::Version &version = pThis->getVersion (button);
+
+ if (sel.toModify())
+ sel.undo();
+ if (version.isInstalled())
+ sel.remove();
+ else {
+ sel.setCandidate (version);
+ sel.install();
+ }
+ }
+ }
+ else // button was pressed
+ pThis->list.undo();
+ }
+
+ virtual bool onlySingleList() { return false; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::ListProps props (list);
+ clearVersions();
+
+ if (list.size() == 1) {
+ Ypp::Selectable sel = list.get (0);
+ GtkWidget *radio = 0;
+ for (int i = 0; i < sel.totalVersions(); i++)
+ radio = addVersion (sel, sel.version (i), radio);
+ }
+ else {
+ GtkWidget *button = gtk_toggle_button_new();
+ gtk_container_add (GTK_CONTAINER (button), gtk_image_new());
+
+ GtkWidget *label = gtk_label_new (_("Several selected"));
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (versions_box), hbox, FALSE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+
+ updateMultiselectionButton (button);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (button_clicked_cb), this);
+ }
+
+ gtk_widget_set_sensitive (versions_box, !props.isLocked());
+ }
+
+ virtual void showRefreshList (Ypp::List list)
+ {
+ // update radios
+ GList *children = gtk_container_get_children (GTK_CONTAINER (versions_box));
+ if (list.size() == 1) {
+ Ypp::Selectable &sel = list.get (0);
+ std::list Ypp::Version::iterator it = versions.begin();
+ for (GList *i = children; i; i = i->next, it++)
+ updateVersionWidget ((GtkWidget *) i->data, sel, *it);
+ }
+ else {
+ GtkWidget *hbox = (GtkWidget *) children->data;
+ GList *l = gtk_container_get_children (GTK_CONTAINER (hbox));
+ GtkWidget *button = (GtkWidget *) l->next->data;
+ g_list_free (l);
+ updateMultiselectionButton (button);
+ }
+ g_list_free (children);
+ }
+
+ static gboolean draw_gray_cb (GtkWidget *widget, GdkEventExpose *event)
+ {
+ GtkAllocation *alloc = &widget->allocation;
+ int x = alloc->x, y = alloc->y, w = alloc->width, h = alloc->height;
+
+ cairo_t *cr = gdk_cairo_create (widget->window);
+ cairo_rectangle (cr, x, y, w, h);
+ // use alpha to cope with styles who might not have a white background
+ cairo_set_source_rgba (cr, 0, 0, 0, .060);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+ return FALSE;
+ }
+};
+
+struct SupportExpander : public DetailWidget {
+ // not derived from DetailExpander as this one behaves a little differently
+ GtkWidget *text, *expander;
+
+ SupportExpander()
+ {
+ text = ygtk_rich_text_new();
+ expander = gtk_expander_new ("");
+ gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
+ gtk_container_add (GTK_CONTAINER (expander), text);
+ }
+
+ virtual GtkWidget *getWidget() { return expander; }
+
+ virtual void refreshList (Ypp::List list) {}
+
+ virtual void setList (Ypp::List list)
+ {
+ if (list.size() == 1) {
+ gtk_widget_show (expander);
+
+ Ypp::Selectable sel = list.get (0);
+ Ypp::Package pkg (sel);
+
+ std::string label ("<b>" + std::string (_("Supportability:")) + "</b> ");
+ label += Ypp::Package::supportSummary (pkg.support());
+ gtk_expander_set_label (GTK_EXPANDER (expander), label.c_str());
+
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text),
+ Ypp::Package::supportDescription (pkg.support()).c_str());
+ }
+ else
+ gtk_widget_hide (expander);
+ }
+};
+
+struct DependenciesExpander : public DetailExpander {
+ GtkWidget *vbox;
+
+ DependenciesExpander()
+ : DetailExpander (_("Dependencies"), false)
+ {
+ vbox = gtk_vbox_new (FALSE, 6);
+ setChild (vbox);
+ }
+
+ void clear()
+ {
+ GList *children = gtk_container_get_children (GTK_CONTAINER (vbox));
+ for (GList *i = children; i; i = i->next)
+ gtk_container_remove (GTK_CONTAINER (vbox), (GtkWidget *) i->data);
+ g_list_free (children);
+ }
+
+ void addLine (const std::string &col1, const std::string &col2,
+ const std::string &col3, int dep)
+ {
+// if (dep >= 0)
+// gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new(), FALSE, TRUE, 0);
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ GtkWidget *col;
+ col = ygtk_rich_text_new();
+ gtk_widget_set_size_request (col, 100, -1);
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (col),
+ ("<i>" + col1 + "</i>").c_str());
+ gtk_box_pack_start (GTK_BOX (hbox), col, FALSE, TRUE, 0);
+ // by settings both the two following "col" text widgets with the same
+ // fixed width, and expanded=True, we ensure all rows have the same size
+ col = ygtk_rich_text_new();
+ gtk_widget_set_size_request (col, 80, -1);
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (col), col2.c_str());
+ if (dep == 0)
+ g_signal_connect (G_OBJECT (col), "link-clicked",
+ G_CALLBACK (requires_link_cb), NULL);
+ else if (dep == 2)
+ g_signal_connect (G_OBJECT (col), "link-clicked",
+ G_CALLBACK (provides_link_cb), NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), col, TRUE, TRUE, 0);
+ col = ygtk_rich_text_new();
+ gtk_widget_set_size_request (col, 80, -1);
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (col), col3.c_str());
+ if (dep == 0)
+ g_signal_connect (G_OBJECT (col), "link-clicked",
+ G_CALLBACK (requires_link_cb), NULL);
+ else if (dep == 2)
+ g_signal_connect (G_OBJECT (col), "link-clicked",
+ G_CALLBACK (provides_link_cb), NULL);
+ gtk_box_pack_start (GTK_BOX (hbox), col, TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+ }
+
+ static void requires_link_cb (GtkWidget *widget, const gchar *link)
+ { YGPackageSelector::get()->searchFor (Ypp::PoolQuery::REQUIRES, link); }
+
+ static void provides_link_cb (GtkWidget *widget, const gchar *link)
+ { YGPackageSelector::get()->searchFor (Ypp::PoolQuery::PROVIDES, link); }
+
+
+ virtual bool onlySingleList() { return true; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::Selectable sel = list.get (0);
+
+ clear();
+ std::string i ("<i>"), _i ("</i>"), b ("<b>"), _b ("</b>");
+ std::string installed_str (i + b + _("Installed Version:") + _b + _i);
+ std::string candidate_str (i + b + _("Available Version:") + _b + _i);
+ bool hasInstalled = sel.hasInstalledVersion(),
+ hasCandidate = sel.hasCandidateVersion();
+ if (hasInstalled)
+ installed_str += "<br>" + sel.installed().number();
+ if (hasCandidate)
+ candidate_str += "<br>" + sel.candidate().number();
+ addLine ("", installed_str, candidate_str, -1);
+ for (int dep = 0; dep < VersionDependencies::total(); dep++) {
+ std::string inst, cand;
+ if (hasInstalled)
+ inst = VersionDependencies (sel.installed()).getText (dep);
+ if (hasCandidate)
+ cand = VersionDependencies (sel.candidate()).getText (dep);
+ if (!inst.empty() || !cand.empty())
+ addLine (VersionDependencies::getLabel (dep), inst, cand, dep);
+ }
+ gtk_widget_show_all (vbox);
+ }
+
+ virtual void showRefreshList (Ypp::List list)
+ { showList (list); }
+
+ struct VersionDependencies {
+ VersionDependencies (Ypp::Version version)
+ : m_version (version) {}
+
+ static int total()
+ { return ((int) zypp::Dep::SUPPLEMENTS_e) + 1; }
+
+ static const char *getLabel (int dep)
+ {
+
+ switch ((zypp::Dep::for_use_in_switch) dep) {
+ case zypp::Dep::PROVIDES_e: return "Provides:";
+ case zypp::Dep::PREREQUIRES_e: return "Pre-requires:";
+ case zypp::Dep::REQUIRES_e: return "Requires:";
+ case zypp::Dep::CONFLICTS_e: return "Conflicts:";
+ case zypp::Dep::OBSOLETES_e: return "Obsoletes:";
+ case zypp::Dep::RECOMMENDS_e: return "Recommends:";
+ case zypp::Dep::SUGGESTS_e: return "Suggests:";
+ case zypp::Dep::ENHANCES_e: return "Enhances:";
+ case zypp::Dep::SUPPLEMENTS_e: return "Supplements:";
+ }
+ return 0;
+ }
+
+ // zypp::Dep(zypp::Dep::for_use_in_switch) construtor is private
+ static zypp::Dep getDep (int dep)
+ {
+ switch (dep) {
+ case 0: return zypp::Dep::PROVIDES;
+ case 1: return zypp::Dep::PREREQUIRES;
+ case 2: return zypp::Dep::REQUIRES;
+ case 3: return zypp::Dep::CONFLICTS;
+ case 4: return zypp::Dep::OBSOLETES;
+ case 5: return zypp::Dep::RECOMMENDS;
+ case 6: return zypp::Dep::SUGGESTS;
+ case 7: return zypp::Dep::ENHANCES;
+ case 8: return zypp::Dep::SUPPLEMENTS;
+ }
+ return zypp::Dep::PROVIDES;
+ }
+
+
+ std::string getText (int dep)
+ {
+ std::string keyword;
+ YGtkPkgSearchEntry *search = YGPackageSelector::get()->getSearchEntry();
+ if ((dep == 0 && search->getAttribute() == Ypp::PoolQuery::PROVIDES) ||
+ (dep == 2 && search->getAttribute() == Ypp::PoolQuery::REQUIRES))
+ keyword = search->getTextStr();
+
+ ZyppResObject zobj = m_version.zyppObj();
+ zypp::Capabilities caps = zobj->dep (getDep (dep));
+ std::string ret;
+ ret.reserve (4092);
+ for (zypp::Capabilities::const_iterator it = caps.begin();
+ it != caps.end(); it++) {
+ if (!ret.empty())
+ ret += ", ";
+
+ std::string str (it->asString());
+ bool highlight = (str == keyword);
+
+
+ if (dep == 0 || dep == 2) {
+ std::string::size_type i;
+ i = MIN (str.find (' '), str.find ('('));
+
+ std::string name (str, 0, i);
+ ret += "" + YGUtils::escapeMarkup (name) + "</a>";
+ if (i != std::string::npos) {
+ std::string rest (str, i);
+ ret += YGUtils::escapeMarkup (rest);
+ }
+ }
+ else
+ ret += YGUtils::escapeMarkup (str);
+
+ if (highlight)
+ ret += keywordCloseTag;
+ }
+ return ret;
+ }
+
+ Ypp::Version m_version;
+ };
+};
+
+struct FilelistExpander : public DetailExpander {
+ GtkWidget *text;
+
+ FilelistExpander()
+ : DetailExpander (_("File list"), false)
+ {
+ text = ygtk_rich_text_new();
+ g_signal_connect (G_OBJECT (text), "link-clicked",
+ G_CALLBACK (dirname_pressed_cb), this);
+ setChild (text);
+ }
+
+ virtual bool onlySingleList() { return true; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::Selectable sel = list.get (0);
+ if (sel.isInstalled())
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), filelist (sel).c_str());
+ else
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), onlyInstalledMsg().c_str());
+ }
+
+ virtual void showRefreshList (Ypp::List list) {}
+
+ static void dirname_pressed_cb (GtkWidget *text, const gchar *link, FilelistExpander *pThis)
+ {
+ gchar *cmd = g_strdup_printf (GNOME_OPEN_BIN " %s &", link);
+ (void) system (cmd);
+ g_free (cmd);
+ }
+
+ static std::string filelist (Ypp::Selectable &sel)
+ {
+ std::string text;
+ text.reserve (4096);
+
+ ZyppResObject zobj = sel.installed().zyppObj();
+ ZyppPackage zpkg = castZyppPackage (zobj);
+ if (zpkg) {
+ YStringTree tree ("");
+
+ zypp::Package::FileList files = zpkg->filelist();
+ for (zypp::Package::FileList::iterator it = files.begin();
+ it != files.end(); it++)
+ tree.addBranch (*it, '/');
+
+ struct inner {
+ static std::string path (YStringTreeItem *item)
+ {
+ std::string str;
+ str.reserve (1024);
+ for (YStringTreeItem *i = item->parent(); i->parent(); i = i->parent()) {
+ std::string val (i->value().orig());
+ std::string prefix ("/");
+ str = prefix + val + str;
+ }
+ return str;
+ }
+
+ static void traverse (YStringTreeItem *item, std::string &text)
+ {
+ if (!item) return;
+
+ // traverse nodes first
+ bool has_leaves = false;
+ for (YStringTreeItem *i = item; i; i = i->next()) {
+ YStringTreeItem *child = i->firstChild();
+ if (child)
+ traverse (child, text);
+ else
+ has_leaves = true;
+ }
+
+ // traverse leaves now
+ if (has_leaves) {
+ std::string dirname (path (item));
+ text += "" + dirname + "</a>";
+ text += "<blockquote>";
+
+ std::string keyword;
+ YGtkPkgSearchEntry *search = YGPackageSelector::get()->getSearchEntry();
+ if (search->getAttribute() == Ypp::PoolQuery::FILELIST)
+ keyword = search->getTextStr();
+ if (!keyword.empty() && keyword[0] == '/') {
+ std::string _dirname (keyword, 0, keyword.find_last_of ('/'));
+ if (dirname == _dirname)
+ keyword = std::string (keyword, _dirname.size()+1);
+ else
+ keyword.clear();
+ }
+
+ for (YStringTreeItem *i = item; i; i = i->next())
+ if (!i->firstChild()) {
+ if (i != item) // not first
+ text += ", ";
+ std::string basename (i->value().orig());
+
+ bool highlight = (basename == keyword);
+ if (highlight)
+ text += keywordOpenTag;
+ text += basename;
+ if (highlight)
+ text += keywordCloseTag;
+ }
+
+ text += "</blockquote>";
+ }
+ }
+ };
+
+ inner::traverse (tree.root(), text);
+ }
+ return text;
+ }
+};
+
+struct ChangelogExpander : public DetailExpander {
+ GtkWidget *text;
+
+ ChangelogExpander()
+ : DetailExpander (_("Changelog"), false)
+ {
+ text = ygtk_rich_text_new();
+ setChild (text);
+ }
+
+ virtual bool onlySingleList() { return true; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::Selectable sel = list.get (0);
+ if (sel.isInstalled())
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), changelog (sel).c_str());
+ else
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), onlyInstalledMsg().c_str());
+ }
+
+ virtual void showRefreshList (Ypp::List list) {}
+
+ static std::string changelog (Ypp::Selectable &sel)
+ {
+ std::string text;
+ text.reserve (32768);
+ text += "<p><i>";
+ text += _("Changelog applies only to the installed version.");
+ text += "</i></p>";
+ ZyppResObject zobj = sel.installed().zyppObj();
+ ZyppPackage zpkg = castZyppPackage (zobj);
+ if (zpkg) {
+ const std::list zypp::ChangelogEntry &logs = zpkg->changelog();
+ for (std::list zypp::ChangelogEntry::const_iterator it = logs.begin();
+ it != logs.end(); it++) {
+ std::string date (it->date().form ("%d %B %Y")), author (it->author()),
+ changes (it->text());
+ author = YGUtils::escapeMarkup (author);
+ changes = YGUtils::escapeMarkup (changes);
+ YGUtils::replace (changes, "\n", 1, "<br>");
+ if (author.compare (0, 2, "- ", 2) == 0) // zypp returns a lot of author strings as
+ author.erase (0, 2); // "- author". wtf?
+ text += "<i>" + date + " (" + author + "):</i><br><blockquote>" + changes + "</blockquote>";
+ }
+ }
+ return text;
+ }
+};
+
+struct AuthorsExpander : public DetailExpander {
+ GtkWidget *text;
+
+ AuthorsExpander()
+ : DetailExpander (_("Authors"), false)
+ {
+ text = ygtk_rich_text_new();
+ setChild (text);
+ }
+
+ virtual bool onlySingleList() { return true; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::Selectable sel = list.get (0);
+ std::string str (authors (sel));
+ if (str.empty()) {
+ str = "<i>"; str += _("Attribute not-specified."); str += "</i>";
+ }
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
+ }
+
+ virtual void showRefreshList (Ypp::List list) {}
+
+ static std::string authors (Ypp::Selectable &sel)
+ {
+ std::string text;
+ ZyppResObject object = sel.zyppSel()->theObj();
+ ZyppPackage package = castZyppPackage (object);
+ if (package) {
+ std::string packager = package->packager(), vendor = package->vendor(), authors;
+ packager = YGUtils::escapeMarkup (packager);
+ vendor = YGUtils::escapeMarkup (vendor);
+ const std::list std::string &authorsList = package->authors();
+ for (std::list std::string::const_iterator it = authorsList.begin();
+ it != authorsList.end(); it++) {
+ std::string author (*it);
+ author = YGUtils::escapeMarkup (author);
+ if (!authors.empty())
+ authors += "<br>";
+ authors += author;
+ }
+ // look for Authors line in description
+ std::string description = package->description();
+ std::string::size_type i = description.find ("\nAuthors:\n-----", 0);
+ if (i != std::string::npos) {
+ i += sizeof ("\nAuthors:\n----");
+ i = description.find ("\n", i);
+ if (i != std::string::npos)
+ i++;
+ }
+ else {
+ i = description.find ("\nAuthor:", 0);
+ if (i == std::string::npos) {
+ i = description.find ("\nAuthors:", 0);
+ if (i != std::string::npos)
+ i++;
+ }
+ if (i != std::string::npos)
+ i += sizeof ("\nAuthor:");
+ }
+ if (i != std::string::npos) {
+ std::string str = description.substr (i);
+ str = YGUtils::escapeMarkup (str);
+ YGUtils::replace (str, "\n", 1, "<br>");
+ authors += str;
+ }
+
+ if (!authors.empty()) {
+ text = "<i>"; text += _("Developed by:"); text += "</i>";
+ text += ("<blockquote>" + authors) + "</blockquote>";
+ if (!packager.empty() || !vendor.empty()) {
+ text += "<i>"; text += _("Packaged by:"); text += "</i>";
+ text += "<blockquote>";
+ if (!packager.empty()) text += packager + " ";
+ if (!vendor.empty()) text += "(" + vendor + ")";
+ text += "</blockquote>";
+ }
+ }
+ }
+ return text;
+ }
+};
+
+struct ContentsExpander : public DetailExpander {
+ YGtkPkgListView *view;
+
+ ContentsExpander()
+ : DetailExpander (_("Applies to"), false)
+ {
+ view = new YGtkPkgListView (true, Ypp::List::NAME_SORT, false, false);
+ view->addCheckColumn (INSTALLED_CHECK_PROP);
+ view->addTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1);
+ view->addTextColumn (_("Version"), VERSION_PROP, true, 125);
+ view->addTextColumn (_("Size"), SIZE_PROP, false, 85);
+ view->addTextColumn (_("Repository"), REPOSITORY_PROP, false, 180);
+ view->addTextColumn (_("Supportability"), SUPPORT_PROP, false, 120);
+ gtk_widget_set_size_request (view->getWidget(), -1, 150);
+
+ setChild (view->getWidget());
+ }
+
+ virtual ~ContentsExpander()
+ { delete view; }
+
+ virtual bool onlySingleList() { return true; }
+
+ virtual void showList (Ypp::List list)
+ {
+ Ypp::Selectable sel = list.get (0);
+ Ypp::Collection col (sel);
+
+ Ypp::PoolQuery query (Ypp::Selectable::PACKAGE);
+ query.addCriteria (new Ypp::FromCollectionMatch (col));
+ view->setQuery (query);
+ }
+
+ virtual void showRefreshList (Ypp::List list) {}
+};
+
+struct YGtkPkgDetailView::Impl : public Ypp::SelListener
+{
+std::list m_widgets;
+GtkWidget *m_scroll;
+Ypp::List m_list;
+
+ Impl() : m_list (0)
+ {
+ DetailWidget *widget;
+
+ GtkWidget *side_vbox = gtk_vbox_new (FALSE, 0);
+
+ if (!YGPackageSelector::get()->onlineUpdateMode()) {
+ widget = new DetailsExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (side_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ }
+ widget = new VersionExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (side_vbox), widget->getWidget(), FALSE, TRUE, 0);
+
+ GtkWidget *main_vbox = gtk_vbox_new (FALSE, 0);
+
+ widget = new DetailName();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+
+ widget = new DetailDescription();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ GtkWidget *detail_description = widget->getWidget();
+
+ if (YGPackageSelector::get()->onlineUpdateMode()) {
+ widget = new ContentsExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ }
+ else {
+ widget = new FilelistExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ widget = new ChangelogExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ widget = new AuthorsExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ widget = new DependenciesExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ widget = new SupportExpander();
+ m_widgets.push_back (widget);
+ gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
+ }
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), side_vbox, FALSE, TRUE, 0);
+
+ GtkWidget *child = gtk_event_box_new();
+ gtk_container_add (GTK_CONTAINER (child), hbox);
+
+ GdkColor *color = &detail_description->style->base [GTK_STATE_NORMAL];
+ gtk_widget_modify_bg (child, GTK_STATE_NORMAL, color);
+
+ m_scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (m_scroll), child);
+
+ gtk_widget_show_all (m_scroll);
+ g_signal_connect (G_OBJECT (m_scroll), "realize",
+ G_CALLBACK (scroll_realize_cb), this);
+ Ypp::addSelListener (this);
+ }
+
+ ~Impl()
+ {
+ for (std::list ::iterator it = m_widgets.begin();
+ it != m_widgets.end(); it++)
+ delete *it;
+ Ypp::removeSelListener (this);
+ }
+
+ void refreshList (Ypp::List list)
+ {
+ for (std::list ::iterator it = m_widgets.begin();
+ it != m_widgets.end(); it++)
+ (*it)->refreshList (list);
+ }
+
+ void setList (Ypp::List list)
+ {
+ for (std::list ::iterator it = m_widgets.begin();
+ it != m_widgets.end(); it++)
+ (*it)->setList (list);
+
+ m_list = list;
+ scrollTop();
+ }
+
+ virtual void selectableModified()
+ { refreshList (m_list); }
+
+ void scrollTop()
+ {
+ GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW (m_scroll);
+ GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment (scroll);
+ YGUtils::scrollWidget (vadj, true);
+ }
+
+ // fix cursor keys support
+ static void move_cursor_cb (GtkTextView *view, GtkMovementStep step, gint count,
+ gboolean extend_selection, GtkWidget *scroll)
+ {
+ GtkScrolledWindow *_scroll = GTK_SCROLLED_WINDOW (scroll);
+ GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment (_scroll);
+ int height = scroll->allocation.height;
+ gdouble increment;
+ switch (step) {
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ increment = height / 10.0;
+ break;
+ case GTK_MOVEMENT_PAGES:
+ increment = height * 0.9;
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ increment = adj->upper - adj->lower;
+ break;
+ default:
+ increment = 0.0;
+ break;
+ }
+
+ gdouble value = adj->value + (count * increment);
+ value = MIN (value, adj->upper - adj->page_size);
+ value = MAX (value, adj->lower);
+ if (value != adj->value)
+ gtk_adjustment_set_value (adj, value);
+ }
+
+ static void fix_keys (GtkWidget *widget, void *_scroll)
+ {
+ GtkWidget *scroll = (GtkWidget *) _scroll;
+ if (GTK_IS_TEXT_VIEW (widget))
+ g_signal_connect (G_OBJECT (widget), "move-cursor",
+ G_CALLBACK (move_cursor_cb), scroll);
+ else if (GTK_IS_CONTAINER (widget))
+ gtk_container_foreach (GTK_CONTAINER (widget), fix_keys, _scroll);
+ }
+
+ static void scroll_realize_cb (GtkWidget *widget, Impl *pThis)
+ { fix_keys (widget, widget); }
+};
+
+YGtkPkgDetailView::YGtkPkgDetailView()
+: impl (new Impl()) {}
+
+YGtkPkgDetailView::~YGtkPkgDetailView()
+{ delete impl; }
+
+GtkWidget *YGtkPkgDetailView::getWidget()
+{ return impl->m_scroll; }
+
+void YGtkPkgDetailView::setSelectable (Ypp::Selectable &sel)
+{
+ Ypp::List list (1);
+ list.append (sel);
+ impl->setList (list);
+}
+
+void YGtkPkgDetailView::setList (Ypp::List list)
+{ impl->setList (list); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgdetailview.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,29 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Text box information on a given selectable.
+*/
+
+#ifndef YGTK_PKG_DETAIL_VIEW_H
+#define YGTK_PKG_DETAIL_VIEW_H
+
+#include
+#include "yzyppwrapper.h"
+
+struct YGtkPkgDetailView
+{
+ YGtkPkgDetailView();
+ ~YGtkPkgDetailView();
+
+ GtkWidget *getWidget();
+
+ void setSelectable (Ypp::Selectable &sel);
+ void setList (Ypp::List list);
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,759 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgFilterView, several zypp attribute query criteria implementations */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "YGUI.h"
+#include "config.h"
+#include "YGUtils.h"
+#include "ygtkpkgfilterview.h"
+#include "ygtkpkglistview.h"
+#include "YGPackageSelector.h"
+#include
+#include "ygtktreeview.h"
+#include "ygtkcellrenderertext.h"
+
+// List store abstract
+
+struct YGtkPkgFilterModel::Impl {
+ GtkTreeModel *filter, *model;
+
+ int convertlIterToStoreRow (GtkTreeIter *iter)
+ {
+ GtkTreeIter _iter;
+ gtk_tree_model_filter_convert_iter_to_child_iter (
+ GTK_TREE_MODEL_FILTER (filter), &_iter, iter);
+
+ GtkTreePath *path = gtk_tree_model_get_path (model, &_iter);
+ int row = gtk_tree_path_get_indices (path)[0];
+ gtk_tree_path_free (path);
+ return row;
+ }
+};
+
+YGtkPkgFilterModel::YGtkPkgFilterModel()
+: impl (new Impl())
+{
+ GtkListStore *store = gtk_list_store_new (TOTAL_COLUMNS, GDK_TYPE_PIXBUF,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT,
+ G_TYPE_POINTER);
+ impl->model = GTK_TREE_MODEL (store);
+
+ impl->filter = gtk_tree_model_filter_new (impl->model, NULL);
+ gtk_tree_model_filter_set_visible_column (
+ GTK_TREE_MODEL_FILTER (impl->filter), VISIBLE_COLUMN);
+ g_object_unref (G_OBJECT (impl->model));
+}
+
+YGtkPkgFilterModel::~YGtkPkgFilterModel()
+{ g_object_unref (G_OBJECT (impl->filter)); }
+
+GtkTreeModel *YGtkPkgFilterModel::getModel()
+{ return impl->filter; }
+
+struct UpdateData {
+ YGtkPkgFilterModel *pThis;
+ Ypp::List *list;
+ UpdateData (YGtkPkgFilterModel *pThis, Ypp::List *list)
+ : pThis (pThis), list (list) {}
+};
+
+static gboolean update_list_cb (GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer _data)
+{
+ gchar *text;
+ UpdateData *data = (UpdateData *) _data;
+ gpointer mdata;
+ gtk_tree_model_get (model, iter, YGtkPkgFilterModel::TEXT_COLUMN, &text,
+ YGtkPkgFilterModel::DATA_COLUMN, &mdata, -1);
+
+ bool separator = !(*text);
+ g_free (text);
+ if (separator) return FALSE;
+
+ int row = gtk_tree_path_get_indices (path)[0];
+ if (row == 0 && data->pThis->firstRowIsAll())
+ data->pThis->setRowCount (0, data->list->size());
+ else
+ data->pThis->updateRow (*data->list, row, mdata);
+ return FALSE;
+}
+
+void YGtkPkgFilterModel::updateList (Ypp::List list)
+{
+ if (!begsUpdate()) return;
+ UpdateData data (this, &list);
+ gtk_tree_model_foreach (impl->model, update_list_cb, &data);
+}
+
+bool YGtkPkgFilterModel::writeQuery (Ypp::PoolQuery &query, GtkTreeIter *iter)
+{
+ gpointer data;
+ gtk_tree_model_get (impl->filter, iter, DATA_COLUMN, &data, -1);
+
+ int row = impl->convertlIterToStoreRow (iter);
+ if (row == 0 && firstRowIsAll())
+ return false;
+ return writeRowQuery (query, row, data);
+}
+
+GtkWidget *YGtkPkgFilterModel::createToolbox (GtkTreeIter *iter)
+{
+ int row = impl->convertlIterToStoreRow (iter);
+ return createToolboxRow (row);
+}
+
+void YGtkPkgFilterModel::addRow (const char *icon, const char *text,
+ bool enabled, gpointer data, bool defaultVisible)
+{
+ // we use cell-render-pixbuf's "pixbuf" rather than "icon-name" so we
+ // can use a fixed size
+ GdkPixbuf *pixbuf = 0;
+ if (icon) {
+ if (!strcmp (icon, "empty")) {
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
+ gdk_pixbuf_fill (pixbuf, 0xffffff00);
+ }
+ else
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
+ icon, 32, GtkIconLookupFlags (0), NULL);
+ }
+
+ int weight = PANGO_WEIGHT_NORMAL;
+ if (firstRowIsAll() && gtk_tree_model_iter_n_children (impl->model, NULL) == 0)
+ weight = PANGO_WEIGHT_BOLD;
+
+ GtkTreeIter iter;
+ GtkListStore *store = GTK_LIST_STORE (impl->model);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, ICON_COLUMN, pixbuf, TEXT_COLUMN, text,
+ COUNT_NUMBER_COLUMN, "", ENABLED_COLUMN, enabled, VISIBLE_COLUMN, defaultVisible,
+ DATA_COLUMN, data, WEIGHT_COLUMN, weight, -1);
+
+ if (pixbuf) g_object_unref (pixbuf);
+}
+
+void YGtkPkgFilterModel::addSeparator()
+{ addRow (NULL, "", true, NULL); }
+
+void YGtkPkgFilterModel::setRowCount (int row, int count)
+{
+ GtkListStore *store = GTK_LIST_STORE (impl->model);
+ GtkTreeIter iter;
+ gtk_tree_model_iter_nth_child (impl->model, &iter, NULL, row);
+
+ gchar *str = g_strdup_printf ("%d", count);
+ gtk_list_store_set (store, &iter, COUNT_NUMBER_COLUMN, str,
+ VISIBLE_COLUMN, row == 0 || count > 0, -1);
+ g_free (str);
+}
+
+// Status
+
+struct YGtkPkgStatusModel::Impl : public Ypp::SelListener {
+ Impl (YGtkPkgStatusModel *parent)
+ : parent (parent), list (0)
+ { Ypp::addSelListener (this); }
+
+ ~Impl()
+ { Ypp::removeSelListener (this); }
+
+ virtual void selectableModified()
+ { // make sure to update the "Modified" row on packages change
+ parent->updateRow (list, modifiedRow(), NULL);
+ }
+
+ YGtkPkgStatusModel *parent;
+
+ static int modifiedRow()
+ { return YGPackageSelector::get()->onlineUpdateMode() ? 2 : 5; }
+
+ Ypp::List list;
+};
+
+static Ypp::StatusMatch::Status rowToStatus (int row)
+{
+ if (YGPackageSelector::get()->onlineUpdateMode())
+ switch (row) {
+ case 0: return Ypp::StatusMatch::NOT_INSTALLED;
+ case 1: return Ypp::StatusMatch::IS_INSTALLED;
+ case 2: return Ypp::StatusMatch::TO_MODIFY;
+ }
+ else
+ switch (row) {
+ case 1: return Ypp::StatusMatch::NOT_INSTALLED;
+ case 2: return Ypp::StatusMatch::IS_INSTALLED;
+ case 3: return Ypp::StatusMatch::HAS_UPGRADE;
+ case 4: return Ypp::StatusMatch::IS_LOCKED;
+ case 5: return Ypp::StatusMatch::TO_MODIFY;
+ }
+ return (Ypp::StatusMatch::Status) 0;
+}
+
+YGtkPkgStatusModel::YGtkPkgStatusModel()
+: impl (new Impl (this))
+{
+ if (YGPackageSelector::get()->onlineUpdateMode()) {
+ // Translators: this refers to the package status
+ addRow (NULL, _("Available"), true, 0);
+ // Translators: this refers to the package status
+ addRow (NULL, _("Installed"), true, 0);
+ // Translators: this refers to the package status
+ addRow (NULL, _("Modified"), true, 0, false);
+ }
+ else {
+ // Translators: "Any status" may be translated as "All statuses" (whichever's smaller)
+ addRow (NULL, _("All packages"), true, 0);
+ // Translators: this refers to the package status
+ addRow (NULL, _("Not installed"), true, 0);
+ addRow (NULL, _("Installed"), true, 0);
+ // Translators: refers to package status: may be translated as "Upgrade"
+ addRow (NULL, _("Upgrades"), true, 0, false);
+ // Translators: this refers to the package status
+ addRow (NULL, _("Locked"), true, 0, false);
+ addRow (NULL, _("Modified"), true, 0, false);
+ }
+}
+
+YGtkPkgStatusModel::~YGtkPkgStatusModel()
+{ delete impl; }
+
+bool YGtkPkgStatusModel::firstRowIsAll()
+{ return !YGPackageSelector::get()->onlineUpdateMode(); }
+
+void YGtkPkgStatusModel::updateRow (Ypp::List list, int row, gpointer data)
+{
+ impl->list = list;
+ Ypp::StatusMatch match (rowToStatus (row));
+ setRowCount (row, list.count (&match));
+}
+
+bool YGtkPkgStatusModel::writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data)
+{
+ query.addCriteria (new Ypp::StatusMatch (rowToStatus (row)));
+ return true;
+}
+
+static void upgrade_patches_clicked_cb (GtkButton *button, YGtkPkgStatusModel *pThis)
+{
+ Ypp::startTransactions();
+ for (int i = 0; i < pThis->impl->list.size(); i++) {
+ Ypp::Selectable sel = pThis->impl->list.get (i);
+ Ypp::Package pkg (sel);
+ if (sel.hasUpgrade() && pkg.isCandidatePatch())
+ sel.install();
+ }
+ Ypp::finishTransactions();
+}
+
+static void upgrade_all_clicked_cb (GtkButton *button, YGtkPkgStatusModel *pThis)
+{
+ Ypp::startTransactions();
+ for (int i = 0; i < pThis->impl->list.size(); i++) {
+ Ypp::Selectable sel = pThis->impl->list.get (i);
+ if (sel.hasUpgrade())
+ sel.install();
+ }
+ Ypp::finishTransactions();
+}
+
+struct PkgHasPatchMatch : public Ypp::Match {
+ virtual bool match (Ypp::Selectable &sel)
+ {
+ Ypp::Package pkg (sel);
+ return pkg.isCandidatePatch();
+ }
+};
+
+GtkWidget *YGtkPkgStatusModel::createToolboxRow (int row)
+{ // "Upgrade All" button
+ if (row == 3 && !YGPackageSelector::get()->onlineUpdateMode()) {
+ PkgHasPatchMatch match;
+ bool hasPatches = impl->list.count (&match);
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6), *button, *icon;
+
+ // Translators: this is shown next to the "Upgrade All" button
+ button = gtk_button_new_with_label (_("Only Upgrade Patches"));
+ gtk_widget_set_sensitive (button, hasPatches);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (upgrade_patches_clicked_cb), this);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+
+ button = gtk_button_new_with_label (_("Upgrade All"));
+ icon = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button), icon);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (upgrade_all_clicked_cb), this);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+
+ gtk_widget_show_all (hbox);
+ return hbox;
+ }
+ return NULL;
+}
+
+// PackageKit-based Group
+
+struct PKGroup {
+ const char *name, *icon;
+ YPkgGroupEnum id;
+
+ PKGroup (YPkgGroupEnum id) : id (id) {
+ name = zypp_tag_group_enum_to_localised_text (id);
+ icon = zypp_tag_enum_to_icon (id);
+ }
+ bool operator < (const PKGroup &other) const
+ { return strcmp (this->name, other.name) < 0; }
+};
+
+YGtkPkgPKGroupModel::YGtkPkgPKGroupModel()
+{
+ std::set <PKGroup> groups;
+ for (int i = 0; i < YPKG_GROUP_UNKNOWN; i++)
+ groups.insert (PKGroup ((YPkgGroupEnum) i));
+
+ addRow ("empty", _("All packages"), true, 0);
+ for (std::set <PKGroup>::const_iterator it = groups.begin();
+ it != groups.end(); it++)
+ addRow (it->icon, it->name, true, GINT_TO_POINTER (((int)it->id)+1));
+
+ for (int i = YPKG_GROUP_UNKNOWN; i < YPKG_GROUP_TOTAL; i++) {
+#if ZYPP_VERSION >= 6030004
+ if (i == YPKG_GROUP_MULTIVERSION && zypp::sat::Pool::instance().multiversionEmpty())
+#else
+ if (i == YPKG_GROUP_MULTIVERSION)
+#endif
+ continue;
+ if (i == YPKG_GROUP_ORPHANED) continue;
+ std::string name = zypp_tag_group_enum_to_localised_text ((YPkgGroupEnum) i);
+ const char *icon = zypp_tag_enum_to_icon ((YPkgGroupEnum) i);
+ if (i == YPKG_GROUP_RECENT)
+ // Translators: when "upload" isn't easy to translate, translate this as "7 days old"
+ name += std::string ("\n<small>") + _("(uploaded last 7 days)") + "</small>";
+ addRow (icon, name.c_str(), true, GINT_TO_POINTER (i+1));
+ if (i == YPKG_GROUP_UNKNOWN)
+ addSeparator();
+ }
+}
+
+void YGtkPkgPKGroupModel::updateRow (Ypp::List list, int row, gpointer data)
+{
+ YPkgGroupEnum id = (YPkgGroupEnum) (GPOINTER_TO_INT (data)-1);
+ Ypp::PKGroupMatch match (id);
+ setRowCount (row, list.count (&match));
+}
+
+bool YGtkPkgPKGroupModel::writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data)
+{
+ YPkgGroupEnum id = (YPkgGroupEnum) (GPOINTER_TO_INT (data)-1);
+ query.addCriteria (new Ypp::PKGroupMatch (id));
+ return true;
+}
+
+// Repository
+
+struct YGtkPkgRepositoryModel::Impl {
+ // cannot store as point at the list-store
+ std::vector Ypp::Repository repos;
+ Ypp::Repository *selected;
+
+ Impl() : selected (NULL)
+ { repos.reserve (zyppPool().knownRepositoriesSize()); }
+};
+
+YGtkPkgRepositoryModel::YGtkPkgRepositoryModel()
+: impl (new Impl())
+{
+ addRow (NULL, _("All repositories"), true, 0);
+
+ for (zypp::ResPoolProxy::repository_iterator it = zyppPool().knownRepositoriesBegin();
+ it != zyppPool().knownRepositoriesEnd(); it++) {
+ Ypp::Repository repo (*it);
+ const char *icon = getRepositoryStockIcon (repo);
+ std::string label (getRepositoryLabel (repo));
+ addRow (icon, label.c_str(), true, GINT_TO_POINTER (1));
+ impl->repos.push_back (repo);
+ }
+
+ zypp::RepoManager manager;
+ std::list zypp::RepoInfo known_repos = manager.knownRepositories();
+ for (std::list zypp::RepoInfo::const_iterator it = known_repos.begin();
+ it != known_repos.end(); it++) {
+ Ypp::Repository repo (*it);
+ if (!repo.enabled()) {
+ const char *icon = getRepositoryStockIcon (repo);
+ std::string label (getRepositoryLabel (repo));
+ addRow (icon, label.c_str(), false, GINT_TO_POINTER (0));
+ }
+ }
+
+ addRow (GTK_STOCK_MISSING_IMAGE, _("None"), true, GINT_TO_POINTER (2));
+}
+
+YGtkPkgRepositoryModel::~YGtkPkgRepositoryModel()
+{ delete impl; }
+
+void YGtkPkgRepositoryModel::updateRow (Ypp::List list, int row, gpointer data)
+{
+ if (GPOINTER_TO_INT (data) == 1) { // normal repo
+ Ypp::Repository &repo = impl->repos[row-1];
+ bool isSystem = repo.isSystem();
+ int count = 0;
+ for (int i = 0; i < list.size(); i++) {
+ Ypp::Selectable sel = list.get (i);
+ if (isSystem) {
+ if (sel.isInstalled())
+ count++;
+ }
+ else for (int i = 0; i < sel.totalVersions(); i++) {
+ Ypp::Version version = sel.version (i);
+ if (!version.isInstalled()) {
+ Ypp::Repository pkg_repo = version.repository();
+ if (repo == pkg_repo) {
+ count++;
+ break;
+ }
+ }
+ }
+ }
+ setRowCount (row, count);
+ }
+ else if (GPOINTER_TO_INT (data) == 2) { // 'none'
+ Ypp::PKGroupMatch match (YPKG_GROUP_ORPHANED);
+ setRowCount (row, list.count (&match));
+ }
+}
+
+bool YGtkPkgRepositoryModel::writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data)
+{
+ impl->selected = 0;
+ if (GPOINTER_TO_INT (data) == 1) {
+ Ypp::Repository &repo = impl->repos[row-1];
+ query.addRepository (repo);
+ impl->selected = &repo;
+ }
+ else if (GPOINTER_TO_INT (data) == 2)
+ query.addCriteria (new Ypp::PKGroupMatch (YPKG_GROUP_ORPHANED));
+ return true;
+}
+
+static void sync_toolbox_buttons (Ypp::Repository *repo, GtkWidget *box)
+{
+ GtkWidget *button, *undo;
+ GList *children = gtk_container_get_children (GTK_CONTAINER (box));
+ button = (GtkWidget *) g_list_nth_data (children, 0);
+ undo = (GtkWidget *) g_list_nth_data (children, 1);
+ g_list_free (children);
+
+ if (zypp::getZYpp()->resolver()->upgradingRepo (repo->zyppRepo())) {
+ gtk_widget_set_sensitive (button, FALSE);
+ gtk_widget_show (undo);
+ }
+ else {
+ gtk_widget_set_sensitive (button, TRUE);
+ gtk_widget_hide (undo);
+ }
+}
+
+static void switch_repo_status (Ypp::Repository *repo)
+{
+ ZyppRepository zrepo = repo->zyppRepo();
+ if (zypp::getZYpp()->resolver()->upgradingRepo (zrepo))
+ zypp::getZYpp()->resolver()->removeUpgradeRepo (zrepo);
+ else
+ zypp::getZYpp()->resolver()->addUpgradeRepo (zrepo);
+}
+
+static void switch_clicked_cb (GtkButton *button, YGtkPkgRepositoryModel *pThis)
+{
+ Ypp::Repository *repo = pThis->impl->selected;
+ switch_repo_status (repo);
+ if (!Ypp::runSolver()) // on solver cancel -- switch back
+ switch_repo_status (repo);
+ sync_toolbox_buttons (repo, gtk_widget_get_parent (GTK_WIDGET (button)));
+}
+
+GtkWidget *YGtkPkgRepositoryModel::createToolboxRow (int row)
+{
+ if (row > 0 && impl->selected) {
+ if (impl->selected->isOutdated()) {
+ GtkWidget *label = gtk_label_new (
+ _("Repository not refreshed in a long time."));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
+ YGUtils::setWidgetFont (label,
+ PANGO_STYLE_ITALIC, PANGO_WEIGHT_NORMAL, PANGO_SCALE_MEDIUM);
+ GtkWidget *icon = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON);
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ return hbox;
+ }
+ else if (!impl->selected->isSystem()) {
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6), *button;
+ button = gtk_button_new_from_stock (GTK_STOCK_UNDO);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (switch_clicked_cb), this);
+ gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ button = gtk_button_new_with_label (
+ _("Switch installed packages to the versions in this repository"));
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (switch_clicked_cb), this);
+ gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ sync_toolbox_buttons (impl->selected, hbox);
+ return hbox;
+ }
+ }
+ return NULL;
+}
+
+static void edit_clicked_cb (GtkWidget *button, YGtkPkgRepositoryModel *pThis)
+{ YGPackageSelector::get()->showRepoManager(); }
+
+GtkWidget *YGtkPkgRepositoryModel::createInternalToolbox()
+{
+ if (!YGPackageSelector::get()->repoMgrEnabled()) return NULL;
+ GtkWidget *button = gtk_button_new_with_label (_("Edit Repositories"));
+ GtkWidget *icon = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (button), icon);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (edit_clicked_cb), this);
+
+ GtkWidget *align = gtk_alignment_new (0, 0, 0, 1);
+ gtk_container_add (GTK_CONTAINER (align), button);
+ return align;
+}
+
+GtkWidget *YGtkPkgRepositoryModel::createInternalPopup()
+{
+ if (!YGPackageSelector::get()->repoMgrEnabled()) return NULL;
+ GtkWidget *menu = gtk_menu_new();
+ GtkWidget *item = gtk_image_menu_item_new_with_mnemonic (_("Edit Repositories"));
+ GtkWidget *icon = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (edit_clicked_cb), this);
+ return menu;
+}
+
+// Support
+
+YGtkPkgSupportModel::YGtkPkgSupportModel()
+{
+ addRow (NULL, _("All packages"), true, 0);
+ for (int i = 0; i < Ypp::Package::supportTotal(); i++)
+ addRow (NULL, Ypp::Package::supportSummary (i).c_str(), true, 0, false);
+}
+
+void YGtkPkgSupportModel::updateRow (Ypp::List list, int row, gpointer data)
+{
+ Ypp::SupportMatch match (row-1);
+ setRowCount (row, list.count (&match));
+}
+
+bool YGtkPkgSupportModel::writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data)
+{
+ query.addCriteria (new Ypp::SupportMatch (row-1));
+ return true;
+}
+
+// Priority
+
+YGtkPkgPriorityModel::YGtkPkgPriorityModel()
+{
+ // Translators: "Any priority" may be translated as "All priorities" (whichever's smaller)
+ addRow (NULL, _("All patches"), true, 0);
+ for (int i = 0; i < Ypp::Patch::priorityTotal(); i++)
+ addRow (NULL, Ypp::Patch::prioritySummary (i), true, 0, false);
+}
+
+void YGtkPkgPriorityModel::updateRow (Ypp::List list, int row, gpointer data)
+{
+ Ypp::PriorityMatch match (row-1);
+ setRowCount (row, list.count (&match));
+}
+
+bool YGtkPkgPriorityModel::writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data)
+{
+ query.addCriteria (new Ypp::PriorityMatch (row-1));
+ return true;
+}
+
+// View widget
+
+struct YGtkPkgFilterView::Impl {
+ GtkWidget *box, *scroll, *view;
+ YGtkPkgFilterModel *model;
+
+ Impl (YGtkPkgFilterModel *model) : model (model) {}
+ ~Impl() { delete model; }
+};
+
+static gboolean tree_selection_possible_cb (GtkTreeSelection *selection,
+ GtkTreeModel *model, GtkTreePath *path, gboolean is_selected, gpointer data)
+{
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ int col = GPOINTER_TO_INT (data);
+ gboolean val;
+ gtk_tree_model_get (model, &iter, col, &val, -1);
+ return val;
+}
+
+static void selection_changed_cb (GtkTreeSelection *selection, YGtkPkgFilterView *pThis)
+{
+ if (gtk_tree_selection_get_selected (selection, NULL, NULL))
+ pThis->notify();
+}
+
+static void right_click_cb (YGtkTreeView *view, gboolean outreach, YGtkPkgFilterView *pThis)
+{
+ GtkWidget *menu = pThis->impl->model->createInternalPopup();
+ if (menu) ygtk_tree_view_popup_menu (view, menu);
+}
+
+YGtkPkgFilterView::YGtkPkgFilterView (YGtkPkgFilterModel *model)
+: YGtkPkgQueryWidget(), impl (new Impl (model))
+{
+ bool updates = model->begsUpdate();
+ impl->view = ygtk_tree_view_new (NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (impl->view), model->getModel());
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ gtk_tree_view_set_headers_visible (view, FALSE);
+ gtk_tree_view_set_search_column (view, YGtkPkgFilterModel::TEXT_COLUMN);
+ if (updates)
+ gtk_tree_view_set_tooltip_column (view, YGtkPkgFilterModel::TEXT_COLUMN);
+ gtk_tree_view_set_enable_tree_lines (view, TRUE);
+ gtk_tree_view_set_row_separator_func (view, YGUtils::empty_row_is_separator_cb,
+ GINT_TO_POINTER (YGtkPkgFilterModel::TEXT_COLUMN), NULL);
+ gtk_tree_view_expand_all (view);
+ g_signal_connect (G_OBJECT (view), "right-click",
+ G_CALLBACK (right_click_cb), this);
+
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ if (model->hasIconCol()) {
+ renderer = gtk_cell_renderer_pixbuf_new();
+ column = gtk_tree_view_column_new_with_attributes (NULL,
+ renderer, "pixbuf", YGtkPkgFilterModel::ICON_COLUMN,
+ "sensitive", YGtkPkgFilterModel::ENABLED_COLUMN, NULL);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
+ }
+ renderer = ygtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "markup", YGtkPkgFilterModel::TEXT_COLUMN,
+ "sensitive", YGtkPkgFilterModel::ENABLED_COLUMN,
+ "weight", YGtkPkgFilterModel::WEIGHT_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "text", YGtkPkgFilterModel::COUNT_NUMBER_COLUMN,
+ "sensitive", YGtkPkgFilterModel::ENABLED_COLUMN,
+ "weight", YGtkPkgFilterModel::WEIGHT_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "xalign", 1.0,
+ "scale", PANGO_SCALE_SMALL, "foreground", "#8c8c8c", NULL);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+ gtk_tree_selection_set_select_function (selection, tree_selection_possible_cb,
+ GINT_TO_POINTER (YGtkPkgFilterModel::ENABLED_COLUMN), NULL);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_changed_cb), this);
+ clearSelection();
+
+ impl->scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (impl->scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (impl->scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (impl->scroll), impl->view);
+
+ GtkWidget *toolbox = model->createInternalToolbox();
+ if (toolbox) {
+ impl->box = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (impl->box), impl->scroll, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (impl->box), toolbox, FALSE, TRUE, 0);
+ }
+ else
+ impl->box = impl->scroll;
+ gtk_widget_show_all (impl->box);
+}
+
+YGtkPkgFilterView::~YGtkPkgFilterView()
+{ delete impl; }
+
+GtkWidget *YGtkPkgFilterView::getWidget()
+{ return impl->box; }
+
+bool YGtkPkgFilterView::begsUpdate()
+{ return impl->model->begsUpdate(); }
+
+void YGtkPkgFilterView::updateList (Ypp::List list)
+{
+ impl->model->updateList (list);
+
+ // always ensure some row is selected
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ GtkTreeModel *model;
+ if (!gtk_tree_selection_get_selected (selection, &model, NULL)) {
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb, this);
+ gtk_tree_selection_select_iter (selection, &iter);
+ g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb, this);
+ }
+ }
+}
+
+void YGtkPkgFilterView::clearSelection()
+{ select (0); /* select 1st row, so some row is selected */ }
+
+bool YGtkPkgFilterView::writeQuery (Ypp::PoolQuery &query)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ return impl->model->writeQuery (query, &iter);
+ return false;
+}
+
+GtkWidget *YGtkPkgFilterView::createToolbox()
+{
+ GtkTreeIter iter;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+ return impl->model->createToolbox (&iter);
+ return NULL;
+}
+
+void YGtkPkgFilterView::select (int row)
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb, this);
+ GtkTreeIter iter;
+ if (row >= 0) {
+ gtk_tree_model_iter_nth_child (impl->model->getModel(), &iter, NULL, row);
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+ else
+ gtk_tree_selection_unselect_all (selection);
+ g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb, this);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgfilterview.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,140 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Several user interfaces for zypp query attributes.
+
+ Create a List-model and pass it to FilterView in order to
+ use it. Example:
+ QueryWidget *query_widget = new YGtkPkgFilterView (new YGtkPkgStatusModel());
+ GtkWidget *gtk_widget = query_widget->getWidget();
+
+ One can very easily re-implement YGtkPkgFilterView to use the GtkComboBox.
+*/
+
+#ifndef YGTK_PKG_FILTER_VIEW_H
+#define YGTK_PKG_FILTER_VIEW_H
+
+#include "ygtkpkgquerywidget.h"
+#include
+
+struct YGtkPkgFilterModel // abstract
+{
+ enum Column { ICON_COLUMN, TEXT_COLUMN, COUNT_NUMBER_COLUMN,
+ VISIBLE_COLUMN, ENABLED_COLUMN, WEIGHT_COLUMN, DATA_COLUMN, TOTAL_COLUMNS };
+
+ YGtkPkgFilterModel();
+ virtual ~YGtkPkgFilterModel();
+ GtkTreeModel *getModel();
+
+ virtual void updateList (Ypp::List list);
+ virtual bool writeQuery (Ypp::PoolQuery &query, GtkTreeIter *iter);
+ virtual GtkWidget *createToolbox (GtkTreeIter *iter);
+
+ virtual bool hasIconCol() = 0;
+ virtual bool firstRowIsAll() = 0;
+
+ virtual bool begsUpdate() = 0;
+ virtual void updateRow (Ypp::List list, int row, gpointer data) = 0;
+ virtual bool writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data) = 0;
+
+ virtual GtkWidget *createToolboxRow (int selectedRow) { return NULL; }
+ virtual GtkWidget *createInternalToolbox() { return NULL; }
+ virtual GtkWidget *createInternalPopup() { return NULL; }
+
+ void addRow (const char *icon, const char *text, bool enabled, gpointer data, bool defaultVisible = true);
+ void addSeparator();
+ void setRowCount (int row, int count);
+
+ struct Impl;
+ Impl *impl;
+};
+
+// implementations
+
+struct YGtkPkgStatusModel : public YGtkPkgFilterModel
+{
+ YGtkPkgStatusModel();
+ virtual ~YGtkPkgStatusModel();
+ virtual bool hasIconCol() { return false; }
+ virtual bool firstRowIsAll();
+ virtual bool begsUpdate() { return true; }
+ virtual void updateRow (Ypp::List list, int row, gpointer data);
+ virtual bool writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data);
+ virtual GtkWidget *createToolboxRow (int selectedRow);
+
+ struct Impl;
+ Impl *impl;
+};
+
+struct YGtkPkgPKGroupModel : public YGtkPkgFilterModel
+{
+ YGtkPkgPKGroupModel();
+ virtual bool hasIconCol() { return true; }
+ virtual bool firstRowIsAll() { return true; }
+ virtual bool begsUpdate() { return true; }
+ virtual void updateRow (Ypp::List list, int row, gpointer data);
+ virtual bool writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data);
+};
+
+struct YGtkPkgRepositoryModel : public YGtkPkgFilterModel
+{
+ YGtkPkgRepositoryModel();
+ virtual ~YGtkPkgRepositoryModel();
+ virtual bool hasIconCol() { return true; }
+ virtual bool firstRowIsAll() { return true; }
+ virtual bool begsUpdate() { return true; }
+ virtual void updateRow (Ypp::List list, int row, gpointer data);
+ virtual bool writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data);
+ virtual GtkWidget *createToolboxRow (int selectedRow);
+ virtual GtkWidget *createInternalToolbox();
+ virtual GtkWidget *createInternalPopup();
+
+ struct Impl;
+ Impl *impl;
+};
+
+struct YGtkPkgSupportModel : public YGtkPkgFilterModel
+{
+ YGtkPkgSupportModel();
+ virtual bool hasIconCol() { return false; }
+ virtual bool firstRowIsAll() { return true; }
+ virtual bool begsUpdate() { return true; }
+ virtual void updateRow (Ypp::List list, int row, gpointer data);
+ virtual bool writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data);
+};
+
+struct YGtkPkgPriorityModel : public YGtkPkgFilterModel
+{
+ YGtkPkgPriorityModel();
+ virtual bool hasIconCol() { return false; }
+ virtual bool firstRowIsAll() { return true; }
+ virtual bool begsUpdate() { return true; }
+ virtual void updateRow (Ypp::List list, int row, gpointer data);
+ virtual bool writeRowQuery (Ypp::PoolQuery &query, int row, gpointer data);
+};
+
+// widget
+
+struct YGtkPkgFilterView : public YGtkPkgQueryWidget
+{
+ YGtkPkgFilterView (YGtkPkgFilterModel *model);
+ virtual ~YGtkPkgFilterView();
+ virtual GtkWidget *getWidget();
+
+ virtual bool begsUpdate();
+ virtual void updateList (Ypp::List list);
+
+ virtual void clearSelection();
+ virtual bool writeQuery (Ypp::PoolQuery &query);
+
+ virtual GtkWidget *createToolbox();
+
+ void select (int row);
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,670 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgHistoryDialog, dialog */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "ygtkpkghistorydialog.h"
+#include "YGDialog.h"
+#include "YGUtils.h"
+#include "YGPackageSelector.h"
+#include "ygtkpkglistview.h"
+#include
+#include "ygtktreeview.h"
+#include "ygtkcellrenderertext.h"
+
+#include
+#define FILENAME "/var/log/zypp/history"
+
+static std::string reqbyTreatment (const std::string &reqby)
+{
+ if (reqby.empty())
+ return _("automatic");
+ if (reqby.compare (0, 4, "root", 4) == 0) {
+ std::string str (_("user:"));
+ str += " root";
+ return str;
+ }
+ return reqby;
+}
+
+struct Handler
+{
+ virtual void date (const std::string &str, bool first) = 0;
+ virtual void item (const std::string &action, const std::string &name,
+ const std::string &description, const std::string &repositoryName,
+ const std::string &repositoryUrl, const std::string &reqby, bool autoReq) = 0;
+};
+
+struct LogListHandler
+{
+ GtkListStore *store;
+
+ enum Column { ICON_COLUMN, NAME_COLUMN, VERSION_URL_COLUMN, REPOSITORY_COLUMN,
+ REQBY_COLUMN, REPOSITORY_ICON_COLUMN, REPOSITORY_URL_COLUMN, SHORTCUT_COLUMN,
+ COLOR_COLUMN, XPAD_COLUMN, TOTAL_COLUMNS };
+
+ LogListHandler()
+ {
+ store = gtk_list_store_new (TOTAL_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT);
+ }
+
+ ~LogListHandler()
+ { g_object_unref (G_OBJECT (store)); }
+
+ GtkTreeModel *getModel()
+ { return GTK_TREE_MODEL (store); }
+
+ void addRow (GtkTreeIter *iter)
+ {
+ gtk_list_store_append (store, iter);
+ gtk_list_store_set (store, iter, ICON_COLUMN, NULL, NAME_COLUMN, NULL,
+ VERSION_URL_COLUMN, NULL, REPOSITORY_COLUMN, NULL, REQBY_COLUMN, NULL,
+ REPOSITORY_ICON_COLUMN, NULL, REPOSITORY_URL_COLUMN, NULL,
+ SHORTCUT_COLUMN, NULL, COLOR_COLUMN, NULL, XPAD_COLUMN, 0, -1);
+ }
+
+ int date (const std::string &str, bool first)
+ {
+ GtkTreeIter iter;
+ if (!first) addRow (&iter); // white space
+ std::string _date = std::string ("<b>\u26ab ") + str + "</b>";
+ addRow (&iter);
+ gtk_list_store_set (store, &iter, NAME_COLUMN, _date.c_str(), -1);
+
+ GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+ int row = gtk_tree_path_get_indices (path)[0];
+ gtk_tree_path_free (path);
+ return row;
+ }
+
+ void item (const std::string &action, const std::string &name,
+ const std::string &description, const std::string &repositoryName,
+ const std::string &repositoryUrl, const std::string &reqby, bool autoReq)
+ {
+ GtkTreeIter iter;
+ const char *icon = 0;
+ std::string shortcut (name);
+ if (action == _("install"))
+ icon = GTK_STOCK_ADD;
+ else if (action == _("upgrade"))
+ icon = GTK_STOCK_GO_UP;
+ else if (action == _("remove"))
+ icon = GTK_STOCK_REMOVE;
+ else if (action == _("downgrade"))
+ icon = GTK_STOCK_GO_DOWN;
+ else if (action == _("re-install"))
+ icon = GTK_STOCK_REFRESH;
+ else {
+ icon = getRepositoryStockIcon (name);
+ shortcut = "_repo";
+ }
+
+ std::string _name;
+ _name.reserve (action.size() + name.size() + 64);
+ _name = "<b>";
+ _name += action + "</b> " + name;
+ int xpad = 0; // autoReq ? 25 : 0;
+
+ const char *repo_icon = 0, *color = 0;
+ bool is_patch = false;
+ if (action == _("upgrade") && !repositoryUrl.empty()) {
+ // if 'upgrade' and from '*update*' server then mark as patch
+ repo_icon = getRepositoryStockIcon (repositoryUrl);
+ if (repositoryUrl.find ("update") != std::string::npos) {
+ //color = "red";
+ std::string tag;
+ tag.reserve (64);
+ tag = "<small>"; tag += _("patch"); tag += "</span></small>";
+ _name += " "; _name += tag;
+ is_patch = true;
+ }
+ }
+ if (autoReq && !is_patch) { // dependency
+ std::string tag;
+ tag.reserve (64);
+ tag = "<small>"; tag += _("auto"); tag += "</span></small>";
+ _name += " "; _name += tag;
+ }
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, ICON_COLUMN, icon, NAME_COLUMN, _name.c_str(),
+ VERSION_URL_COLUMN, description.c_str(), REPOSITORY_COLUMN, repositoryName.c_str(),
+ REPOSITORY_ICON_COLUMN, repo_icon, REPOSITORY_URL_COLUMN, repositoryUrl.c_str(),
+ REQBY_COLUMN, reqby.c_str(), SHORTCUT_COLUMN, shortcut.c_str(),
+ COLOR_COLUMN, color, XPAD_COLUMN, xpad, -1);
+ }
+};
+
+struct DateListHandler
+{
+ GtkListStore *store;
+
+ enum Column { TEXT_COLUMN, LOG_ROW_COLUMN, TOTAL_COLUMNS };
+
+ DateListHandler()
+ { store = gtk_list_store_new (TOTAL_COLUMNS, G_TYPE_STRING, G_TYPE_INT); }
+
+ ~DateListHandler()
+ { g_object_unref (G_OBJECT (store)); }
+
+ GtkTreeModel *getModel()
+ { return GTK_TREE_MODEL (store); }
+
+ void date (const std::string &str, bool first, int log_row)
+ {
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, TEXT_COLUMN, str.c_str(),
+ LOG_ROW_COLUMN, log_row, -1);
+ }
+};
+
+struct ListHandler : public Handler
+{
+ LogListHandler *log_handler;
+ DateListHandler *date_handler;
+
+ ListHandler()
+ {
+ log_handler = new LogListHandler();
+ date_handler = new DateListHandler();
+ }
+
+ ~ListHandler()
+ { delete log_handler; delete date_handler; }
+
+ virtual void date (const std::string &str, bool first)
+ {
+ int row = log_handler->date (str, first);
+ date_handler->date (str, first, row);
+ }
+
+ virtual void item (const std::string &a, const std::string &n,
+ const std::string &d, const std::string &rn,
+ const std::string &ru, const std::string &rb, bool ar)
+ { log_handler->item (a, n, d, rn, ru, rb, ar); }
+};
+
+struct FileHandler : public Handler
+{
+ FILE *file;
+
+ FileHandler (const char *filename)
+ { file = fopen (filename, "w"); }
+
+ ~FileHandler()
+ { fclose (file); }
+
+ void addSpace()
+ { (void) fwrite ("\n", sizeof (char), 1, file); }
+
+ virtual void date (const std::string &str, bool first)
+ {
+ if (!first)
+ addSpace();
+ (void) fwrite (str.c_str(), sizeof (char), str.size(), file);
+ addSpace(); addSpace();
+ }
+
+ virtual void item (const std::string &action, const std::string &name,
+ const std::string &description, const std::string &repositoryName,
+ const std::string &repositoryUrl, const std::string &reqby, bool autoReq)
+ {
+ std::string str;
+ str.reserve (action.size() + name.size() + description.size() + 4);
+ str = std::string ("\t") + action + " " + name + " " + description + "\n";
+ (void) fwrite (str.c_str(), sizeof (char), str.size(), file);
+ }
+};
+
+struct ZyppHistoryParser
+{
+ Handler *handler;
+ std::string _date;
+ std::map installed;
+
+ ZyppHistoryParser (Handler *handler)
+ : handler (handler)
+ {
+ zypp::parser::HistoryLogReader parser (FILENAME, boost::ref (*this));
+ try {
+ parser.readAll();
+ }
+ catch (const zypp::Exception &ex) {
+ yuiWarning () << "Error: Could not load log file" << FILENAME << ": "
+ << ex.asUserHistory() << std::endl;
+ }
+ }
+
+ bool operator() (const zypp::HistoryItem::Ptr &item)
+ {
+ std::string date (item->date.form ("%d %B %Y"));
+ if (_date != date) {
+ handler->date (date, _date.empty());
+ _date = date;
+ }
+
+ std::string action, name, descrpt, repoName, repoUrl, reqby, t;
+ bool autoreq = false;
+ switch (item->action.toEnum()) {
+ case zypp::HistoryActionID::NONE_e:
+ break;
+ case zypp::HistoryActionID::INSTALL_e: {
+ zypp::HistoryItemInstall *_item =
+ static_cast (item.get());
+ name = _item->name;
+ descrpt = _item->edition.version();
+ Ypp::getRepositoryFromAlias (_item->repoalias, repoName, repoUrl);
+ reqby = _item->reqby; autoreq = reqby.empty();
+ reqby = reqbyTreatment (reqby);
+ zypp::Edition edition = _item->edition;
+ std::map ::iterator it;
+ it = installed.find (name);
+ if (it == installed.end())
+ action = _("install");
+ else {
+ zypp::Edition prev_edition = it->second;
+ if (edition > prev_edition)
+ action = _("upgrade");
+ else if (edition < prev_edition)
+ action = _("downgrade");
+ else // (edition == prev_edition)
+ action = _("re-install");
+ }
+ installed[name] = edition;
+ break;
+ }
+ case zypp::HistoryActionID::REMOVE_e: {
+ zypp::HistoryItemRemove *_item =
+ static_cast (item.get());
+ action = _("remove");
+ name = _item->name;
+ descrpt = _item->edition.version();
+ reqby = _item->reqby; autoreq = reqby.empty();
+ reqby = reqbyTreatment (reqby);
+ std::map ::iterator it;
+ it = installed.find (name);
+ if (it != installed.end())
+ installed.erase (it);
+ break;
+ }
+ case zypp::HistoryActionID::REPO_ADD_e: {
+ zypp::HistoryItemRepoAdd *_item =
+ static_cast (item.get());
+ action = _("add repository");
+ Ypp::getRepositoryFromAlias (_item->alias, name, t);
+ descrpt = _item->url.asString();
+ break;
+ }
+ case zypp::HistoryActionID::REPO_REMOVE_e: {
+ zypp::HistoryItemRepoRemove *_item =
+ static_cast (item.get());
+ action = _("remove repository");
+ name = _item->alias;
+ break;
+ }
+ case zypp::HistoryActionID::REPO_CHANGE_ALIAS_e: {
+ zypp::HistoryItemRepoAliasChange *_item =
+ static_cast (item.get());
+ action = _("change repository alias");
+ name = _item->oldalias + " -> " + _item->newalias;
+ break;
+ }
+ case zypp::HistoryActionID::REPO_CHANGE_URL_e: {
+ zypp::HistoryItemRepoUrlChange *_item =
+ static_cast (item.get());
+ action = _("change repository url");
+ Ypp::getRepositoryFromAlias (_item->alias, name, t);
+ descrpt = _item->newurl.asString();
+ break;
+ }
+ }
+ if (!action.empty())
+ handler->item (action, name, descrpt, repoName, repoUrl, reqby, autoreq);
+ return true;
+ }
+};
+
+static void goto_clicked (GtkTreeView *log_view)
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (log_view);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ char *shortcut;
+ gtk_tree_model_get (model, &iter, LogListHandler::SHORTCUT_COLUMN, &shortcut, -1);
+ if (!strcmp (shortcut, "_repo"))
+ YGPackageSelector::get()->showRepoManager();
+ else
+ YGPackageSelector::get()->searchFor (Ypp::PoolQuery::NAME, shortcut);
+ g_free (shortcut);
+
+ GtkWidget *dialog = gtk_widget_get_toplevel (GTK_WIDGET (log_view));
+ gtk_widget_hide (dialog);
+ }
+}
+
+static void log_selection_changed_cb (GtkTreeSelection *selection, GtkDialog *dialog)
+{
+ bool selected = gtk_tree_selection_count_selected_rows (selection) > 0;
+ gtk_dialog_set_response_sensitive (dialog, 1, selected);
+}
+
+static void log_row_activated_cb (GtkTreeView *view, GtkTreePath *path,
+ GtkTreeViewColumn *column)
+{ goto_clicked (view); }
+
+static gboolean log_can_select_cb (GtkTreeSelection *selection, GtkTreeModel *model,
+ GtkTreePath *path, gboolean path_currently_selected, gpointer data)
+{
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gchar *shortcut;
+ gtk_tree_model_get (model, &iter, LogListHandler::SHORTCUT_COLUMN, &shortcut, -1);
+ bool can_select = shortcut != NULL;
+ if (shortcut) g_free (shortcut);
+ return can_select;
+}
+
+static void date_selection_changed_cb (GtkTreeSelection *selection, GtkTreeView *log_view)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ int log_row;
+ gtk_tree_model_get (model, &iter, 1, &log_row, -1);
+
+ GtkTreePath *path = gtk_tree_path_new_from_indices (log_row, -1);
+ gtk_tree_view_scroll_to_cell (log_view, path, NULL, TRUE, 0, 0);
+ gtk_tree_path_free (path);
+ }
+}
+
+static void save_to_file (GtkWindow *parent)
+{
+ GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Save to"), parent,
+ GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+ gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ FileHandler handler (filename);
+ ZyppHistoryParser parser (&handler);
+ g_free (filename);
+ }
+ gtk_widget_destroy (dialog);
+}
+
+static void response_cb (GtkDialog *dialog, gint response, GtkTreeView *log_view)
+{
+ switch (response) {
+ case 1: goto_clicked (log_view); break;
+ case 2: save_to_file (GTK_WINDOW (dialog)); break;
+ default: gtk_widget_hide (GTK_WIDGET (dialog)); break;
+ }
+}
+
+static gboolean query_tooltip_cb (GtkWidget *widget, gint x, gint y,
+ gboolean keyboard_mode, GtkTooltip *tooltip, YGtkPkgListView *pThis)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (widget);
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ if (gtk_tree_view_get_tooltip_context (view,
+ &x, &y, keyboard_mode, &model, &path, &iter)) {
+ gtk_tree_view_set_tooltip_row (view, tooltip, path);
+ gtk_tree_path_free (path);
+
+ GtkTreeViewColumn *column;
+ int bx, by;
+ gtk_tree_view_convert_widget_to_bin_window_coords (
+ view, x, y, &bx, &by);
+ gtk_tree_view_get_path_at_pos (
+ view, x, y, NULL, &column, NULL, NULL);
+
+ std::string text;
+ text.reserve (254);
+ const char *icon = 0;
+
+ if (column == ygtk_tree_view_get_column (YGTK_TREE_VIEW (view), 2)) { // repository
+ char *name, *url;
+ gtk_tree_model_get (model, &iter, LogListHandler::REPOSITORY_COLUMN, &name,
+ LogListHandler::REPOSITORY_URL_COLUMN, &url, -1);
+ if (name && *name) {
+ text = name;
+ if (url && *url) {
+ text += "\n<small>"; text += url; text += "</small>";
+ icon = getRepositoryStockIcon (url);
+ }
+ if (url)
+ g_free (url);
+ }
+ if (name)
+ g_free (name);
+ }
+
+ if (!text.empty()) {
+ gtk_tooltip_set_markup (tooltip, text.c_str());
+ gtk_tooltip_set_icon_from_icon_name (tooltip,
+ icon, GTK_ICON_SIZE_BUTTON);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void goto_activate_cb (GtkMenuItem *item, GtkTreeView *view)
+{ goto_clicked (view); }
+
+static void right_click_cb (YGtkTreeView *view, gboolean outreach)
+{
+ GtkWidget *menu = gtk_menu_new();
+ if (!outreach) {
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+ bool selected = gtk_tree_selection_get_selected (selection, NULL, NULL);
+
+ GtkWidget *item = gtk_image_menu_item_new_from_stock (GTK_STOCK_JUMP_TO, NULL);
+ gtk_widget_set_sensitive (item, selected);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (goto_activate_cb), view);
+ }
+
+ ygtk_tree_view_append_show_columns_item (view, menu);
+ ygtk_tree_view_popup_menu (view, menu);
+}
+
+static gboolean read_logs_idle_cb (void *data)
+{
+ GtkWidget **views = (GtkWidget **) data;
+ GtkWidget *dialog = views[0];
+ GtkTreeView *log_view = GTK_TREE_VIEW (views[1]);
+ GtkTreeView *date_view = GTK_TREE_VIEW (views[2]);
+
+ ListHandler handler;
+ ZyppHistoryParser parser (&handler);
+
+ gtk_tree_view_set_model (date_view, handler.date_handler->getModel());
+ gtk_tree_view_set_model (log_view, handler.log_handler->getModel());
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (date_view);
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter_first (
+ gtk_tree_view_get_model (date_view), &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+
+ gdk_window_set_cursor (dialog->window, NULL);
+ return FALSE;
+}
+
+YGtkPkgHistoryDialog::YGtkPkgHistoryDialog()
+{
+ GtkCellRenderer *renderer, *pix_renderer;
+ GtkTreeViewColumn *column;
+
+ GtkWidget *log_view = ygtk_tree_view_new (_("No entries."));
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (log_view), LogListHandler::SHORTCUT_COLUMN);
+ gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (log_view), TRUE);
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (log_view), TRUE);
+ gtk_widget_set_has_tooltip (log_view, TRUE);
+ g_signal_connect (G_OBJECT (log_view), "query-tooltip",
+ G_CALLBACK (query_tooltip_cb), this);
+ g_signal_connect (G_OBJECT (log_view), "right-click",
+ G_CALLBACK (right_click_cb), this);
+
+ bool reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column, _("Action"));
+ gtk_tree_view_column_set_spacing (column, 6);
+
+ pix_renderer = gtk_cell_renderer_pixbuf_new();
+ if (!reverse)
+ gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
+
+ renderer = ygtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "markup", LogListHandler::NAME_COLUMN, "xpad", LogListHandler::XPAD_COLUMN,
+ "foreground", LogListHandler::COLOR_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
+
+ if (reverse)
+ gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, pix_renderer,
+ "icon-name", LogListHandler::ICON_COLUMN, NULL);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (log_view), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (_("Version / URL"), renderer,
+ "text", LogListHandler::VERSION_URL_COLUMN, "xpad", LogListHandler::XPAD_COLUMN,
+ "foreground", LogListHandler::COLOR_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_fixed_width (column, 120);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (log_view), column);
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column, _("Repository"));
+ gtk_tree_view_column_set_spacing (column, 2);
+
+ pix_renderer = gtk_cell_renderer_pixbuf_new();
+ if (!reverse)
+ gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "text", LogListHandler::REPOSITORY_COLUMN, NULL);
+
+ if (reverse)
+ gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, pix_renderer,
+ "icon-name", LogListHandler::REPOSITORY_ICON_COLUMN, NULL);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_fixed_width (column, 140);
+ gtk_tree_view_column_set_visible (column, FALSE);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (log_view), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (_("Requested by"), renderer,
+ "text", LogListHandler::REQBY_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_fixed_width (column, 100);
+ gtk_tree_view_column_set_visible (column, FALSE);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (log_view), column);
+
+ GtkWidget *log_scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (log_scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (log_scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (log_scroll), log_view);
+
+ GtkWidget *date_view = gtk_tree_view_new();
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (date_view), DateListHandler::TEXT_COLUMN);
+ gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (date_view), TRUE);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (_("Date"), renderer,
+ "text", DateListHandler::TEXT_COLUMN, NULL);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (date_view), column);
+
+ GtkWidget *date_scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (date_scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (date_scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (date_scroll), date_view);
+
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_OTHER, GTK_BUTTONS_NONE,
+ _("Show History (%s)"), FILENAME);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_JUMP_TO, 1);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Save to File"), 2);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 1, FALSE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 650, 600);
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (response_cb), log_view);
+ g_signal_connect (G_OBJECT (dialog), "delete-event",
+ G_CALLBACK (gtk_true), log_view);
+
+ GtkWidget *hpaned = gtk_hpaned_new();
+ gtk_paned_pack1 (GTK_PANED (hpaned), date_scroll, FALSE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (hpaned), log_scroll, TRUE, FALSE);
+ YGUtils::setPaneRelPosition (hpaned, .30);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hpaned);
+
+ gtk_widget_show_all (dialog);
+ m_dialog = dialog;
+
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (log_view));
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (log_selection_changed_cb), dialog);
+ g_signal_connect (G_OBJECT (log_view), "row-activated",
+ G_CALLBACK (log_row_activated_cb), NULL);
+ gtk_tree_selection_set_select_function (selection, log_can_select_cb, NULL, NULL);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (date_view));
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (date_selection_changed_cb), log_view);
+
+ GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
+ gdk_window_set_cursor (dialog->window, cursor);
+ gdk_cursor_unref (cursor);
+
+ GtkWidget **views = g_new (GtkWidget *, 3);
+ views[0] = dialog; views[1] = log_view; views[2] = date_view;
+ g_idle_add_full (G_PRIORITY_LOW, read_logs_idle_cb, views, g_free);
+}
+
+YGtkPkgHistoryDialog::~YGtkPkgHistoryDialog()
+{ gtk_widget_destroy (m_dialog); }
+
+void YGtkPkgHistoryDialog::popup()
+{ gtk_window_present (GTK_WINDOW (m_dialog)); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkghistorydialog.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,29 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Show /var/log/zypp/history.
+ Uses zypp::parser::HistoryLogReader.
+*/
+
+#ifndef YGTK_PKG_HISTORY_DIALOG_H
+#define YGTK_PKG_HISTORY_DIALOG_H
+
+#include
+
+struct YGtkPkgHistoryDialog
+{
+ YGtkPkgHistoryDialog();
+ ~YGtkPkgHistoryDialog();
+
+ void popup();
+
+private:
+ GtkWidget *m_dialog;
+};
+
+// you do not want to use this class directly:
+// use YGPackageSelector::get()->showHistoryDialog()
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,41 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* Textdomain "yast2-gtk" */
+/* YGtkPkgLanguageView, language list implementation */
+// check the header file for information about this widget
+
+#include "YGi18n.h"
+#include "config.h"
+#include "ygtkpkglanguageview.h"
+#include
+
+YGtkPkgLanguageView::YGtkPkgLanguageView()
+: YGtkPkgListView (true, Ypp::List::NAME_SORT, false, true)
+{
+ addCheckColumn (INSTALLED_CHECK_PROP);
+ addTextColumn (NULL, NAME_SUMMARY_PROP, true, -1);
+
+ Ypp::LangQuery query;
+ YGtkPkgListView::setList (query);
+
+ YGtkPkgListView::setListener (this);
+}
+
+GtkWidget *YGtkPkgLanguageView::getWidget()
+{ return YGtkPkgListView::getWidget(); }
+
+bool YGtkPkgLanguageView::writeQuery (Ypp::PoolQuery &query)
+{
+ Ypp::List list (getSelected());
+ if (list.size() > 0) {
+ Ypp::Collection col (list.get (0));
+ query.addCriteria (new Ypp::FromCollectionMatch (col));
+ return true;
+ }
+ return false;
+}
+
+void YGtkPkgLanguageView::selectionChanged()
+{ notify(); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglanguageview.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,33 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Unlike the pattern view, this one is a simple widget derived from
+ the packages one.
+*/
+
+#ifndef YGTK_PKG_LANGUAGE_LIST_H
+#define YGTK_PKG_LANGUAGE_LIST_H
+
+#include "ygtkpkglistview.h"
+#include "ygtkpkgquerywidget.h"
+
+struct YGtkPkgLanguageView : public YGtkPkgListView, YGtkPkgListView::Listener, YGtkPkgQueryWidget
+{
+ YGtkPkgLanguageView();
+ virtual GtkWidget *getWidget();
+
+ virtual bool begsUpdate() { return false; }
+ virtual void updateList (Ypp::List list) {}
+
+ virtual void clearSelection() {}
+ virtual bool writeQuery (Ypp::PoolQuery &query);
+
+ virtual void selectionChanged();
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,1094 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgListView, Zypp GtkTreeView implementation */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include "YGi18n.h"
+#include "YGUtils.h"
+#include "YGUI.h"
+#include "YGPackageSelector.h"
+#include "ygtkpkglistview.h"
+#include "ygtktreeview.h"
+#include "ygtktreemodel.h"
+#include "ygtkcellrenderertext.h"
+#include "ygtkcellrendererbutton.h"
+#include "ygtkcellrenderersidebutton.h"
+#include
+#include
+
+#define GRAY_COLOR "#727272"
+
+//** Model
+
+enum ImplProperty {
+ // booleans
+ HAS_UPGRADE_PROP = TOTAL_PROPS, TO_UPGRADE_PROP, CAN_TOGGLE_INSTALL_PROP,
+ MANUAL_MODIFY_PROP, IS_LOCKED_PROP,
+ // integer
+ XPAD_PROP,
+ // string
+ FOREGROUND_PROP, BACKGROUND_PROP, REPOSITORY_STOCK_PROP,
+ ACTION_ICON_PROP,
+ // pointer
+ PTR_PROP,
+ TOTAL_IMPL_PROPS
+};
+
+static GType _columnType (int col)
+{
+ switch (col) {
+ case NAME_PROP: case ACTION_NAME_PROP: case NAME_SUMMARY_PROP:
+ case VERSION_PROP: case SINGLE_VERSION_PROP: case REPOSITORY_PROP:
+ case SUPPORT_PROP: case SIZE_PROP: case STATUS_ICON_PROP:
+ case ACTION_BUTTON_PROP: case ACTION_ICON_PROP: case FOREGROUND_PROP:
+ case BACKGROUND_PROP: case REPOSITORY_STOCK_PROP:
+ return G_TYPE_STRING;
+ case INSTALLED_CHECK_PROP:
+ case HAS_UPGRADE_PROP: case TO_UPGRADE_PROP: case CAN_TOGGLE_INSTALL_PROP:
+ case MANUAL_MODIFY_PROP: case IS_LOCKED_PROP:
+ return G_TYPE_BOOLEAN;
+ case XPAD_PROP:
+ return G_TYPE_INT;
+ case PTR_PROP:
+ return G_TYPE_POINTER;
+ }
+ return 0;
+}
+
+struct YGtkZyppModel : public YGtkTreeModel, Ypp::SelListener
+{
+ // we pass GtkTreeView to the model, so we can test for selected rows
+ // and modify text markup appropriely (trashing the data-view model, heh)
+
+ YGtkZyppModel (Ypp::List list) : m_list (list.clone())
+ { addSelListener (this); }
+
+ ~YGtkZyppModel()
+ { removeSelListener (this); }
+
+ void setHighlight (std::list std::string keywords)
+ { m_keywords = keywords; }
+
+protected:
+ Ypp::List m_list;
+ std::list std::string m_keywords;
+
+ virtual int rowsNb() { return m_list.size(); }
+ virtual int columnsNb() const { return TOTAL_IMPL_PROPS; }
+ virtual bool showEmptyEntry() const { return false; }
+
+ virtual GType columnType (int col) const
+ { return _columnType (col); }
+
+ virtual void getValue (int row, int col, GValue *value)
+ {
+ Ypp::Selectable &sel = m_list.get (row);
+ switch (col) {
+ case NAME_PROP: {
+ std::string str (sel.name());
+ highlightMarkupSpan (str, m_keywords);
+ g_value_set_string (value, str.c_str());
+ break;
+ }
+ case ACTION_NAME_PROP: {
+ std::string str ("<b>"), name (sel.name());
+ str.reserve (name.size() + 35);
+ str += getStatusAction (&sel);
+ str += "</b> ";
+ str += name;
+ g_value_set_string (value, str.c_str());
+ break;
+ }
+ case NAME_SUMMARY_PROP: {
+ std::string name (sel.name()), summary (sel.summary()), str;
+ summary = YGUtils::escapeMarkup (summary);
+ highlightMarkupSpan (name, m_keywords);
+ highlightMarkupSpan (summary, m_keywords);
+ str.reserve (name.size() + summary.size() + 64);
+ str = name;
+ if (!summary.empty()) {
+ str += "\n";
+ str += "";
+ str += "<small>" + summary + "</small>";
+ str += "</span>";
+ }
+ g_value_set_string (value, str.c_str());
+ break;
+ }
+ case REPOSITORY_PROP: {
+ std::string str;
+ if (sel.hasCandidateVersion()) {
+ Ypp::Repository repo (sel.candidate().repository());
+ str = getRepositoryLabel (repo);
+ }
+#if 0
+ else {
+ Ypp::Repository repo (sel.installed().repository());
+ str = getRepositoryLabel (repo);
+ }
+#endif
+ g_value_set_string (value, str.c_str());
+ break;
+ }
+ case REPOSITORY_STOCK_PROP: {
+ const char *stock = 0;
+ if (sel.hasCandidateVersion()) {
+ Ypp::Repository repo (sel.candidate().repository());
+ stock = getRepositoryStockIcon (repo);
+ }
+#if 0
+ else {
+ Ypp::Repository repo (sel.installed().repository());
+ stock = getRepositoryStockIcon (repo);
+ }
+#endif
+ g_value_set_string (value, stock);
+ break;
+ }
+ case SUPPORT_PROP: {
+ if (sel.type() == Ypp::Selectable::PACKAGE) {
+ Ypp::Package pkg (sel);
+ std::string str (Ypp::Package::supportSummary (pkg.support()));
+ g_value_set_string (value, str.c_str());
+ }
+ break;
+ }
+ case SIZE_PROP: {
+ Size_t size = sel.anyVersion().size();
+ g_value_set_string (value, size.asString().c_str());
+ break;
+ }
+ case VERSION_PROP: {
+ std::string str;
+ str.reserve (128);
+ int cmp = 0;
+ bool hasCandidate = sel.hasCandidateVersion();
+ bool patch = false;
+ if (hasCandidate) {
+ Ypp::Version candidate = sel.candidate();
+ if (sel.isInstalled()) {
+ Ypp::Version installed = sel.installed();
+ if (candidate > installed)
+ cmp = 1;
+ if (candidate < installed)
+ cmp = -1;
+ }
+ }
+ if (cmp > 0) {
+ str += "";
+
+ if (sel.type() == Ypp::Selectable::PACKAGE) {
+ Ypp::Package pkg (sel);
+ patch = pkg.isCandidatePatch();
+ }
+ }
+ else if (cmp < 0)
+ str += "";
+
+ if (cmp == 0) {
+ if (sel.isInstalled()) {
+ if (!hasCandidate) // red for orphan too
+ str += "";
+ str += sel.installed().number();
+ if (!hasCandidate)
+ str += "</span>";
+ }
+ else
+ str += sel.candidate().number();
+ }
+ else {
+ str += sel.candidate().number();
+ if (patch)
+ { str += " <small>"; str += _("patch"); str += "</small>"; }
+ str += "</span>\n<small>";
+ str += sel.installed().number();
+ str += "</small>";
+ }
+ g_value_set_string (value, str.c_str());
+ break;
+ }
+ case SINGLE_VERSION_PROP: {
+ std::string str;
+ str.reserve (128);
+ if (sel.hasCandidateVersion() && !sel.toRemove())
+ str = sel.candidate().number();
+ else
+ str = sel.installed().number();
+ g_value_set_string (value, str.c_str());
+ break;
+ }
+ case INSTALLED_CHECK_PROP: {
+ bool installed; // whether it is installed or will be at apply
+ if (sel.toInstall())
+ installed = true;
+ else if (sel.toRemove())
+ installed = false;
+ else
+ installed = sel.isInstalled();
+ g_value_set_boolean (value, installed);
+ break;
+ }
+ case HAS_UPGRADE_PROP:
+ g_value_set_boolean (value, sel.hasUpgrade());
+ break;
+ case TO_UPGRADE_PROP:
+ g_value_set_boolean (value, sel.hasUpgrade() && sel.toInstall());
+ break;
+ case CAN_TOGGLE_INSTALL_PROP:
+ g_value_set_boolean (value, !sel.isInstalled() || sel.canRemove());
+ break;
+ case MANUAL_MODIFY_PROP:
+ g_value_set_boolean (value, sel.toModify() && !sel.toModifyAuto());
+ break;
+ case IS_LOCKED_PROP:
+ g_value_set_boolean (value, !sel.isLocked());
+ break;
+ case BACKGROUND_PROP: {
+ const char *color = 0;
+ if (sel.toModify())
+ color = "#f4f4b7";
+ g_value_set_string (value, color);
+ break;
+ }
+ case FOREGROUND_PROP: {
+ const char *color = 0;
+ if (sel.toModifyAuto())
+ color = "#6f6f6f";
+ g_value_set_string (value, color);
+ break;
+ }
+ case XPAD_PROP: {
+ int xpad = sel.toModifyAuto() ? 20 : 0;
+ g_value_set_int (value, xpad);
+ break;
+ }
+ case STATUS_ICON_PROP:
+ g_value_set_string (value, getStatusStockIcon (sel));
+ break;
+ case ACTION_ICON_PROP: {
+ const char *stock;
+ if (sel.toModify())
+ stock = GTK_STOCK_UNDO;
+ else if (sel.isInstalled())
+ stock = GTK_STOCK_REMOVE;
+ else
+ stock = GTK_STOCK_ADD;
+ g_value_set_string (value, stock);
+ break;
+ }
+ case ACTION_BUTTON_PROP: {
+ const char *text;
+ if (sel.toModify())
+ text = _("Undo");
+ else if (sel.isInstalled())
+ text = _("Remove");
+ else
+ text = _("Install");
+ g_value_set_string (value, text);
+ break;
+ }
+ case PTR_PROP:
+ g_value_set_pointer (value, (void *) &sel);
+ break;
+ }
+ }
+
+ virtual void selectableModified()
+ {
+ for (int i = 0; i < rowsNb(); i++)
+ listener->rowChanged (i);
+ }
+};
+
+static Ypp::Selectable *ygtk_zypp_model_get_sel (GtkTreeModel *model, gchar *path_str)
+{
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter_from_string (model, &iter, path_str);
+ Ypp::Selectable *sel;
+ gtk_tree_model_get (model, &iter, PTR_PROP, &sel, -1);
+ return sel;
+}
+
+static Ypp::Selectable *ygtk_zypp_model_get_sel (GtkTreeModel *model, GtkTreePath *path)
+{
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ Ypp::Selectable *sel;
+ gtk_tree_model_get (model, &iter, PTR_PROP, &sel, -1);
+ return sel;
+}
+
+//** View
+
+struct YGtkPkgListView::Impl {
+ GtkWidget *scroll, *view;
+ YGtkPkgListView::Listener *listener;
+ Ypp::List list;
+ bool descriptiveTooltip;
+ int sort_attrb, ascendent : 2;
+ bool userModified;
+ std::list std::string m_keywords;
+ bool indentAuto, colorModified;
+
+ Impl (bool descriptiveTooltip, int default_sort_attrb, bool indentAuto, bool colorModified)
+ : listener (NULL), list (0), descriptiveTooltip (descriptiveTooltip),
+ sort_attrb (default_sort_attrb), ascendent (true), userModified (false),
+ indentAuto (indentAuto), colorModified (colorModified) {}
+
+ void setList (Ypp::List _list, int _attrb, bool _ascendent, bool userSorted, const std::list std::string &keywords)
+ {
+ if (userSorted) userModified = true;
+ if (_list != list || sort_attrb != _attrb || ascendent != _ascendent) {
+ if (_attrb != -1) {
+ if (_list == list && sort_attrb == _attrb)
+ _list.reverse();
+ else
+ _list.sort ((Ypp::List::SortAttribute) _attrb, _ascendent);
+ }
+ list = _list;
+ sort_attrb = _attrb;
+ ascendent = _ascendent;
+ }
+
+ GtkTreeModel *model = ygtk_tree_model_new (new YGtkZyppModel (list));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (view), model);
+ g_object_unref (G_OBJECT (model));
+ setHighlight (keywords);
+
+ if (userModified) {
+ GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (view));
+ for (GList *i = columns; i; i = i->next) {
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data;
+ bool v = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (column), "attrb")) == _attrb;
+ gtk_tree_view_column_set_sort_indicator (column, v);
+ if (v)
+ gtk_tree_view_column_set_sort_order (column,
+ ascendent ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING);
+ }
+ g_list_free (columns);
+ }
+
+ // search_column is one prop (among others) that gets reset on new model
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (view), NAME_PROP);
+ }
+
+ void setHighlight (const std::list std::string &keywords)
+ {
+ if (m_keywords.empty() && keywords.empty()) return;
+ m_keywords = keywords;
+ GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+ YGtkZyppModel *zmodel = (YGtkZyppModel *) ygtk_tree_model_get_model (model);
+ zmodel->setHighlight (keywords);
+ gtk_widget_queue_draw (view);
+ }
+};
+
+static void right_click_cb (YGtkTreeView *view, gboolean outreach, YGtkPkgListView *pThis)
+{
+ struct inner {
+ static void appendItem (GtkWidget *menu, const char *_label,
+ const char *tooltip, const char *stock, bool sensitive,
+ void (& callback) (GtkMenuItem *item, YGtkPkgListView *pThis), YGtkPkgListView *pThis)
+ {
+ GtkWidget *item;
+ std::string label;
+ if (_label)
+ label = YGUtils::mapKBAccel (_label);
+ if (stock) {
+ if (_label) {
+ item = gtk_image_menu_item_new_with_mnemonic (label.c_str());
+ GtkWidget *image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+ }
+ else
+ item = gtk_image_menu_item_new_from_stock (stock, NULL);
+ }
+ else
+ item = gtk_menu_item_new_with_mnemonic (label.c_str());
+ if (tooltip)
+ gtk_widget_set_tooltip_markup (item, tooltip);
+ gtk_widget_set_sensitive (item, sensitive);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (callback), pThis);
+ }
+ static void install_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { pThis->getSelected().install(); }
+ static void reinstall_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { reinstall (pThis->getSelected().get(0)); }
+ static void remove_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { pThis->getSelected().remove(); }
+ static void undo_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { pThis->getSelected().undo(); }
+ static void lock_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { pThis->getSelected().lock (true); }
+ static void unlock_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { pThis->getSelected().lock (false); }
+ static void select_all_cb (GtkMenuItem *item, YGtkPkgListView *pThis)
+ { pThis->selectAll(); }
+
+ static bool hasReinstall (Ypp::Selectable sel)
+ {
+ if (sel.hasInstalledVersion()) {
+ Ypp::Version installedVersion = sel.installed();
+ for (int i = 0; i < sel.totalVersions(); i++) {
+ Ypp::Version version = sel.version (i);
+ if (!version.isInstalled() && version == installedVersion)
+ return true;
+ }
+ }
+ return false;
+ }
+ static void reinstall (Ypp::Selectable sel)
+ {
+ Ypp::Version installedVersion = sel.installed();
+ for (int i = 0; i < sel.totalVersions(); i++) {
+ Ypp::Version version = sel.version (i);
+ if (!version.isInstalled() && version == installedVersion) {
+ sel.setCandidate (version);
+ sel.install();
+ break;
+ }
+ }
+ }
+ };
+
+ GtkWidget *menu = gtk_menu_new();
+ Ypp::List list = pThis->getSelected();
+ Ypp::Selectable::Type type = Ypp::Selectable::PACKAGE;
+ if (list.size() > 0)
+ type = list.get(0).type();
+
+ if (!outreach) {
+ Ypp::ListProps props (list);
+
+ bool canLock = props.canLock(), unlocked = props.isUnlocked();
+ bool modified = props.toModify();
+ bool locked = !unlocked && canLock;
+ if (props.isNotInstalled() && !modified)
+ inner::appendItem (menu, _("&Install"), 0, GTK_STOCK_SAVE,
+ !locked, inner::install_cb, pThis);
+ if (props.hasUpgrade() && !modified)
+ inner::appendItem (menu, _("&Upgrade"), 0, GTK_STOCK_GO_UP,
+ !locked, inner::install_cb, pThis);
+ if (type == Ypp::Selectable::PACKAGE && list.size() == 1 && inner::hasReinstall (list.get(0)) && !modified)
+ inner::appendItem (menu, _("&Re-install"), 0, GTK_STOCK_REFRESH,
+ !locked, inner::reinstall_cb, pThis);
+ if (props.isInstalled() && !modified)
+ inner::appendItem (menu, _("&Remove"), 0, GTK_STOCK_DELETE,
+ !locked && props.canRemove(), inner::remove_cb, pThis);
+ if (modified)
+ inner::appendItem (menu, _("&Undo"), 0, GTK_STOCK_UNDO,
+ true, inner::undo_cb, pThis);
+ if (canLock) {
+ static const char *lock_tooltip =
+ "<b>Package lock:</b> prevents the package status from being modified by "
+ "the dependencies resolver.";
+ if (props.isLocked())
+ inner::appendItem (menu, _("&Unlock"), _(lock_tooltip),
+ GTK_STOCK_DIALOG_AUTHENTICATION, true, inner::unlock_cb, pThis);
+ if (unlocked)
+ inner::appendItem (menu, _("&Lock"), _(lock_tooltip),
+ GTK_STOCK_DIALOG_AUTHENTICATION, !modified,
+ inner::lock_cb, pThis);
+ }
+ }
+
+ if (type == Ypp::Selectable::PACKAGE || type == Ypp::Selectable::PATCH) {
+ GList *items = gtk_container_get_children (GTK_CONTAINER (menu));
+ g_list_free (items);
+
+ if (items != NULL) /* add separator if there are other items */
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new());
+ inner::appendItem (menu, NULL, NULL, GTK_STOCK_SELECT_ALL,
+ true, inner::select_all_cb, pThis);
+ ygtk_tree_view_append_show_columns_item (YGTK_TREE_VIEW (pThis->impl->view), menu);
+ }
+ ygtk_tree_view_popup_menu (YGTK_TREE_VIEW (pThis->impl->view), menu);
+}
+
+static void selection_changed_cb (GtkTreeSelection *selection, YGtkPkgListView *pThis)
+{
+ if (GTK_WIDGET_REALIZED (pThis->impl->view) && pThis->impl->listener)
+ pThis->impl->listener->selectionChanged();
+}
+
+static void row_activated_cb (GtkTreeView *view, GtkTreePath *path,
+ GtkTreeViewColumn *column, YGtkPkgListView *pThis)
+{
+ YGUI::ui()->busyCursor();
+ if (YGPackageSelector::get()->yield()) return;
+
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ Ypp::Selectable *sel = ygtk_zypp_model_get_sel (model, path);
+ if (sel->toModify())
+ sel->undo();
+ else if (sel->isInstalled())
+ sel->remove();
+ else
+ sel->install();
+
+ YGUI::ui()->normalCursor();
+}
+
+static void check_toggled_cb (GtkCellRendererToggle *renderer, gchar *path_str,
+ YGtkPkgListView *pThis)
+{
+ YGUI::ui()->busyCursor();
+ if (YGPackageSelector::get()->yield()) return;
+
+ GtkTreeView *view = GTK_TREE_VIEW (pThis->impl->view);
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ Ypp::Selectable *sel = ygtk_zypp_model_get_sel (model, path_str);
+
+ gboolean active = gtk_cell_renderer_toggle_get_active (renderer);
+ if (sel->toModify())
+ sel->undo();
+ else
+ active ? sel->remove() : sel->install();
+
+ YGUI::ui()->normalCursor();
+}
+
+static void upgrade_toggled_cb (YGtkCellRendererButton *renderer, gchar *path_str,
+ YGtkPkgListView *pThis)
+{
+ YGUI::ui()->busyCursor();
+ if (YGPackageSelector::get()->yield()) return;
+
+ GtkTreeView *view = GTK_TREE_VIEW (pThis->impl->view);
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ Ypp::Selectable *sel = ygtk_zypp_model_get_sel (model, path_str);
+ sel->toInstall() ? sel->undo() : sel->install();
+
+ YGUI::ui()->normalCursor();
+}
+
+static void undo_toggled_cb (YGtkCellRendererButton *renderer, gchar *path_str,
+ YGtkPkgListView *pThis)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (pThis->impl->view);
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ Ypp::Selectable *sel = ygtk_zypp_model_get_sel (model, path_str);
+ sel->undo();
+}
+
+static void action_button_toggled_cb (YGtkCellRendererButton *renderer, gchar *path_str,
+ YGtkPkgListView *pThis)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (pThis->impl->view);
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ Ypp::Selectable *sel = ygtk_zypp_model_get_sel (model, path_str);
+ if (sel->toModify())
+ sel->undo();
+ else if (sel->isInstalled())
+ sel->remove();
+ else
+ sel->install();
+}
+
+static gboolean query_tooltip_cb (GtkWidget *widget, gint x, gint y,
+ gboolean keyboard_mode, GtkTooltip *tooltip, YGtkPkgListView *pThis)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (widget);
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ if (gtk_tree_view_get_tooltip_context (view,
+ &x, &y, keyboard_mode, &model, &path, &iter)) {
+ gtk_tree_view_set_tooltip_row (view, tooltip, path);
+
+ Ypp::Selectable *sel = ygtk_zypp_model_get_sel (model, path);
+ gtk_tree_path_free (path);
+ std::string text;
+ text.reserve (256);
+ const char *icon = 0;
+
+ GtkTreeViewColumn *column;
+ int bx, by;
+ gtk_tree_view_convert_widget_to_bin_window_coords (
+ view, x, y, &bx, &by);
+ gtk_tree_view_get_path_at_pos (
+ view, x, y, NULL, &column, NULL, NULL);
+
+ GtkIconSize icon_size = GTK_ICON_SIZE_MENU;
+ if (column == ygtk_tree_view_get_column (YGTK_TREE_VIEW (view), 0)) {
+ text = getStatusSummary (*sel);
+ icon = getStatusStockIcon (*sel);
+ }
+ else if (pThis->impl->descriptiveTooltip) {
+ text = std::string ("<b>") + sel->name() + "</b>\n\n";
+ text += sel->description (false);
+ switch (sel->type()) {
+ case Ypp::Selectable::PATTERN: {
+ ZyppPattern pattern = castZyppPattern (sel->zyppSel()->theObj());
+ icon = pattern->icon().asString().c_str();
+ if (!(*icon))
+ icon = "pattern-generic";
+ break;
+ }
+ case Ypp::Selectable::PACKAGE:
+ icon = getStatusStockIcon (*sel);
+ break;
+ default: break;
+ }
+ icon_size = GTK_ICON_SIZE_DIALOG;
+ }
+
+ if (text.empty())
+ return FALSE;
+ gtk_tooltip_set_markup (tooltip, text.c_str());
+ if (icon)
+ gtk_tooltip_set_icon_from_icon_name (tooltip, icon, icon_size);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void column_clicked_cb (GtkTreeViewColumn *column, YGtkPkgListView *pThis)
+{
+ int attrb = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (column), "attrb"));
+ bool ascendent = true;
+ if (gtk_tree_view_column_get_sort_indicator (column))
+ ascendent = gtk_tree_view_column_get_sort_order (column) == GTK_SORT_DESCENDING;
+ pThis->impl->setList (pThis->impl->list, attrb, ascendent, true, pThis->impl->m_keywords);
+}
+
+static void set_sort_column (YGtkPkgListView *pThis, GtkTreeViewColumn *column, int property)
+{
+ int attrb = -1;
+ switch (property) {
+ case INSTALLED_CHECK_PROP: attrb = Ypp::List::IS_INSTALLED_SORT; break;
+ case NAME_PROP: case ACTION_NAME_PROP: case NAME_SUMMARY_PROP:
+ attrb = Ypp::List::NAME_SORT; break;
+ case REPOSITORY_PROP: attrb = Ypp::List::REPOSITORY_SORT; break;
+ case SUPPORT_PROP: attrb = Ypp::List::SUPPORT_SORT; break;
+ case SIZE_PROP: attrb = Ypp::List::SIZE_SORT; break;
+ }
+
+ gtk_tree_view_column_set_clickable (column, true);
+ g_object_set_data (G_OBJECT (column), "attrb", GINT_TO_POINTER (attrb));
+ if (attrb != -1)
+ g_signal_connect (G_OBJECT (column), "clicked",
+ G_CALLBACK (column_clicked_cb), pThis);
+}
+
+YGtkPkgListView::YGtkPkgListView (bool descriptiveTooltip, int default_sort, bool indentAuto, bool colorModified, bool variableHeight)
+: impl (new Impl (descriptiveTooltip, default_sort, indentAuto, colorModified))
+{
+ impl->scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (impl->scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (impl->scroll),
+ GTK_SHADOW_IN);
+
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view = ygtk_tree_view_new (_("No matches.")));
+ if (!variableHeight)
+ gtk_tree_view_set_fixed_height_mode (view, TRUE);
+ gtk_tree_view_set_headers_visible (view, FALSE);
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_changed_cb), this);
+
+ g_signal_connect (G_OBJECT (view), "row-activated",
+ G_CALLBACK (row_activated_cb), this);
+ g_signal_connect (G_OBJECT (view), "right-click",
+ G_CALLBACK (right_click_cb), this);
+ gtk_widget_set_has_tooltip (impl->view, TRUE);
+ g_signal_connect (G_OBJECT (view), "query-tooltip",
+ G_CALLBACK (query_tooltip_cb), this);
+
+ gtk_container_add (GTK_CONTAINER (impl->scroll), impl->view);
+ gtk_widget_show_all (impl->scroll);
+}
+
+YGtkPkgListView::~YGtkPkgListView()
+{ delete impl; }
+
+GtkWidget *YGtkPkgListView::getWidget()
+{ return impl->scroll; }
+
+GtkWidget *YGtkPkgListView::getView()
+{ return impl->view; }
+
+void YGtkPkgListView::setQuery (Ypp::Query &query)
+{ setList (Ypp::List (query)); }
+
+void YGtkPkgListView::setList (Ypp::List list)
+{
+ std::list std::string keywords;
+ impl->setList (list, impl->sort_attrb, impl->ascendent, false, keywords);
+}
+
+void YGtkPkgListView::setHighlight (const std::list std::string &keywords)
+{
+ impl->setHighlight (keywords);
+
+ int index = keywords.size() == 1 ? impl->list.find (keywords.front()) : -1;
+ if (index != -1) {
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ GtkTreePath *path = gtk_tree_path_new_from_indices (index, -1);
+ gtk_tree_view_scroll_to_cell (view, path, NULL, TRUE, .5, 0);
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+ }
+ else if (GTK_WIDGET_REALIZED (impl->view))
+ gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (impl->view), -1, 0);
+}
+
+void YGtkPkgListView::addTextColumn (const char *header, int property, bool visible, int size)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ if (header)
+ gtk_tree_view_set_headers_visible (view, TRUE);
+ GtkTreeViewColumn *column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column, header);
+
+ GtkCellRenderer *renderer;
+ if (property == REPOSITORY_PROP) {
+ renderer = gtk_cell_renderer_pixbuf_new();
+ if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
+ gtk_tree_view_column_pack_end (column, renderer, FALSE);
+ else
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "icon-name", REPOSITORY_STOCK_PROP, NULL);
+ }
+
+ if (property == VERSION_PROP) {
+ renderer = ygtk_cell_renderer_side_button_new();
+ g_object_set (G_OBJECT (renderer), "stock-id", GTK_STOCK_GO_UP, NULL);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (upgrade_toggled_cb), this);
+ }
+ else
+ renderer = ygtk_cell_renderer_text_new();
+
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "markup", property, "sensitive", IS_LOCKED_PROP, NULL);
+
+ if (impl->colorModified)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "cell-background", BACKGROUND_PROP);
+ if (impl->indentAuto) {
+ gtk_tree_view_column_add_attribute (column, renderer, "xpad", XPAD_PROP);
+ gtk_tree_view_column_add_attribute (column, renderer, "foreground", FOREGROUND_PROP);
+ }
+
+ PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_END;
+ if (size >= 0 && property != NAME_SUMMARY_PROP)
+ ellipsize = PANGO_ELLIPSIZE_MIDDLE;
+ g_object_set (G_OBJECT (renderer), "ellipsize", ellipsize, NULL);
+
+ if (property == VERSION_PROP) {
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "button-visible", HAS_UPGRADE_PROP);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "active", TO_UPGRADE_PROP);
+ }
+
+ if (size != -1) // on several columns
+ gtk_tree_view_set_rules_hint (view, TRUE);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ if (size >= 0)
+ gtk_tree_view_column_set_fixed_width (column, size);
+ else
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_column_set_visible (column, visible);
+ set_sort_column (this, column, property);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
+}
+
+void YGtkPkgListView::addCheckColumn (int property)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (NULL,
+ renderer, "active", property, "sensitive", IS_LOCKED_PROP, NULL);
+ if (impl->colorModified)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "cell-background", BACKGROUND_PROP);
+ if (property == INSTALLED_CHECK_PROP)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "activatable", CAN_TOGGLE_INSTALL_PROP);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (check_toggled_cb), this);
+
+ // it seems like GtkCellRendererToggle has no width at start, so fixed doesn't work
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_fixed_width (column, 25);
+ set_sort_column (this, column, property);
+ gtk_tree_view_append_column (view, column);
+}
+
+void YGtkPkgListView::addImageColumn (const char *header, int property, bool onlyManualModified)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
+ header, renderer, "icon-name", property, NULL);
+ if (impl->colorModified)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "cell-background", BACKGROUND_PROP);
+ if (onlyManualModified)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "visible", MANUAL_MODIFY_PROP);
+
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ int height = MAX (32, YGUtils::getCharsHeight (impl->view, 1));
+ gtk_cell_renderer_set_fixed_size (renderer, -1, height);
+ gtk_tree_view_column_set_fixed_width (column, 38);
+ gtk_tree_view_append_column (view, column);
+}
+
+void YGtkPkgListView::addButtonColumn (const char *header, int property)
+{
+ GtkCellRenderer *renderer = ygtk_cell_renderer_button_new();
+ GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (
+ header, renderer, "sensitive", IS_LOCKED_PROP, NULL);
+ if (impl->colorModified)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "cell-background", BACKGROUND_PROP);
+
+ gboolean show_icon;
+ g_object_get (G_OBJECT (gtk_settings_get_default()), "gtk-button-images", &show_icon, NULL);
+
+ const char *text;
+ if (property == UNDO_BUTTON_PROP) { // static property (always "Undo")
+ text = _("Undo");
+ g_object_set (G_OBJECT (renderer), "text", text, NULL);
+ if (show_icon)
+ g_object_set (G_OBJECT (renderer), "stock-id", GTK_STOCK_UNDO, NULL);
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "visible", MANUAL_MODIFY_PROP);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (undo_toggled_cb), this);
+ }
+ else {
+ text = "xxxxxxxxxx";
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "text", property);
+ if (show_icon)
+ gtk_tree_view_column_add_attribute (column, renderer,
+ "stock-id", ACTION_ICON_PROP);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (action_button_toggled_cb), this);
+ }
+
+ PangoRectangle rect;
+ int width = 0;
+ PangoLayout *layout = gtk_widget_create_pango_layout (impl->view,
+ strlen (header) > strlen (text) ? header : text);
+ pango_layout_get_pixel_extents (layout, NULL, &rect);
+ width = MAX (width, rect.width);
+ g_object_unref (G_OBJECT (layout));
+ width += 18;
+ if (show_icon) {
+ int icon_width;
+ gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (impl->view),
+ GTK_ICON_SIZE_MENU, &icon_width, NULL);
+ width += icon_width;
+ }
+
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_fixed_width (column, width);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (impl->view), column);
+}
+
+void YGtkPkgListView::setListener (YGtkPkgListView::Listener *listener)
+{ impl->listener = listener; }
+
+Ypp::List YGtkPkgListView::getList()
+{ return impl->list; }
+
+Ypp::List YGtkPkgListView::getSelected()
+{
+ GtkTreeModel *model;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ GList *rows = gtk_tree_selection_get_selected_rows (selection, &model);
+
+ Ypp::List list (g_list_length (rows));
+ for (GList *i = rows; i; i = i->next) {
+ GtkTreeIter iter;
+ GtkTreePath *path = (GtkTreePath *) i->data;
+ gtk_tree_model_get_iter (model, &iter, path);
+
+ Ypp::Selectable *sel;
+ gtk_tree_model_get (model, &iter, PTR_PROP, &sel, -1);
+ gtk_tree_path_free (path);
+ list.append (*sel);
+ }
+ g_list_free (rows);
+ return list;
+}
+
+void YGtkPkgListView::selectAll()
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ gtk_tree_selection_select_all (selection);
+}
+
+// utilities
+
+const char *getStatusAction (Ypp::Selectable *sel)
+{
+ const char *action = 0;
+ if (sel->toInstall()) {
+ action = _("install");
+ if (sel->type() == Ypp::Selectable::PACKAGE) {
+ if (sel->isInstalled()) {
+ Ypp::Version candidate = sel->candidate(), installed = sel->installed();
+ if (candidate > installed)
+ action = _("upgrade");
+ else if (candidate < installed)
+ action = _("downgrade");
+ else
+ action = _("re-install");
+ }
+ }
+ }
+ else if (sel->toRemove())
+ action = _("remove");
+ else //if (sel->toModify())
+ action = _("modify"); // generic for locked and so on
+ return action;
+}
+
+std::string getStatusSummary (Ypp::Selectable &sel)
+{
+ std::string text;
+ if (sel.isLocked())
+ text = _("locked: right-click to unlock");
+ else if (sel.toInstall()) {
+ Ypp::Version candidate = sel.candidate();
+ text = _("To install") + std::string (" ") + candidate.number();
+ }
+ else if (sel.toRemove())
+ text = _("To remove");
+ else if (sel.isInstalled()) {
+ text = _("Installed");
+ if (sel.hasUpgrade()) {
+ text += " ";
+ text += _("(upgrade available)");
+ }
+ }
+ else
+ text = _("Not installed");
+ if (sel.toModifyAuto()) {
+ text += "\n<i>";
+ text += _("status changed by the dependencies resolver");
+ text += "</i>";
+ }
+ return text;
+}
+
+const char *getStatusStockIcon (Ypp::Selectable &sel)
+{
+ const char *icon;
+ if (sel.isLocked())
+ icon = GTK_STOCK_DIALOG_AUTHENTICATION;
+ else if (sel.toInstall()) {
+ icon = GTK_STOCK_ADD;
+ if (sel.type() == Ypp::Selectable::PACKAGE) {
+ Ypp::Version candidate = sel.candidate();
+ if (sel.isInstalled()) {
+ Ypp::Version installed = sel.installed();
+ if (candidate > installed)
+ icon = GTK_STOCK_GO_UP;
+ else if (candidate < installed)
+ icon = GTK_STOCK_GO_DOWN;
+ else // if (candidate == installed)
+ icon = GTK_STOCK_REFRESH;
+ }
+ }
+ }
+ else if (sel.toRemove())
+ icon = GTK_STOCK_REMOVE;
+ else if (sel.isInstalled())
+ icon = GTK_STOCK_HARDDISK;
+ else
+ icon = "package";
+ return icon;
+}
+
+std::string getRepositoryLabel (Ypp::Repository &repo)
+{
+ std::string name (repo.name()), url, str;
+ url = repo.isSystem() ? _("Installed packages") : repo.url();
+ str.reserve (name.size() + url.size() + 64);
+ str = name + "\n";
+ str += "";
+ str += "<small>" + url + "</small>";
+ str += "</span>";
+ return str;
+}
+
+const char *getRepositoryStockIcon (const std::string &url)
+{
+ if (url.empty())
+ return GTK_STOCK_MISSING_IMAGE;
+ if (url.compare (0, 2, "cd", 2) == 0 || url.compare (0, 3, "dvd", 3) == 0)
+ return GTK_STOCK_CDROM;
+ if (url.compare (0, 3, "iso", 3) == 0)
+ return GTK_STOCK_FILE;
+ if (url.find ("KDE") != std::string::npos)
+ return "pattern-kde";
+ if (url.find ("GNOME") != std::string::npos)
+ return "pattern-gnome";
+ if (url.find ("update") != std::string::npos)
+ return "yast-update";
+ if (url.find ("home") != std::string::npos)
+ return "yast-users";
+ return GTK_STOCK_NETWORK;
+}
+
+const char *getRepositoryStockIcon (Ypp::Repository &repo)
+{
+ if (repo.isSystem())
+ return "yast-host";
+ return getRepositoryStockIcon (repo.url());
+}
+
+void highlightMarkup (std::string &text, const std::list std::string &keywords,
+ const char *openTag, const char *closeTag, int openTagLen, int closeTagLen)
+{
+ if (keywords.empty()) return;
+ text.reserve ((openTagLen + closeTagLen + 2) * 6);
+ const char *i = text.c_str();
+ while (*i) {
+ std::list std::string::const_iterator it;
+ for (it = keywords.begin(); it != keywords.end(); it++) {
+ const std::string &keyword = *it;
+ int len = keyword.size();
+ if (strncasecmp (i, keyword.c_str(), len) == 0) {
+ int pos = i - text.c_str();
+ text.insert (pos+len, closeTag);
+ text.insert (pos, openTag);
+ i = text.c_str() + pos + len + openTagLen + closeTagLen - 2;
+ break;
+ }
+ }
+ if (it == keywords.end())
+ i++;
+ }
+}
+
+void highlightMarkupSpan (std::string &text, const std::list std::string &keywords)
+{
+ static const char openTag[] = "";
+ static const char closeTag[] = "</span>";
+ highlightMarkup (text, keywords, openTag, closeTag, sizeof (openTag), sizeof (closeTag));
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkglistview.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,68 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* A view for Ypp's query results.
+*/
+
+#ifndef YGTK_PKG_LIST_VIEW_H
+#define YGTK_PKG_LIST_VIEW_H
+
+#include "yzyppwrapper.h"
+#include
+
+enum Property {
+ INSTALLED_CHECK_PROP, NAME_PROP, ACTION_NAME_PROP, NAME_SUMMARY_PROP,
+ VERSION_PROP, SINGLE_VERSION_PROP, REPOSITORY_PROP, SUPPORT_PROP,
+ SIZE_PROP, STATUS_ICON_PROP, ACTION_BUTTON_PROP, UNDO_BUTTON_PROP, TOTAL_PROPS
+};
+
+struct YGtkPkgListView {
+ YGtkPkgListView (bool descriptiveTooltip, int default_sort /* -1 to disable */,
+ bool indentAuto, bool colorModified, bool variableHeight = false);
+ ~YGtkPkgListView();
+
+ GtkWidget *getWidget();
+ GtkWidget *getView();
+
+ void setQuery (Ypp::Query &query);
+ void setList (Ypp::List list);
+
+ void setHighlight (const std::list std::string &keywords);
+
+ void addTextColumn (const char *header, int property, bool visible, int size);
+ void addCheckColumn (int checkProperty);
+ void addImageColumn (const char *header, int property, bool onlyManualModified = false);
+ void addButtonColumn (const char *header, int property);
+
+ Ypp::List getList();
+
+ struct Listener {
+ virtual void selectionChanged() = 0;
+ };
+ void setListener (Listener *listener);
+
+ Ypp::List getSelected();
+ void selectAll();
+
+ struct Impl;
+ Impl *impl;
+};
+
+// some utilities:
+
+const char *getStatusAction (Ypp::Selectable *sel);
+std::string getStatusSummary (Ypp::Selectable &sel);
+const char *getStatusStockIcon (Ypp::Selectable &sel);
+
+std::string getRepositoryLabel (Ypp::Repository &repo);
+const char *getRepositoryStockIcon (Ypp::Repository &repo);
+const char *getRepositoryStockIcon (const std::string &url);
+
+void highlightMarkup (std::string &text, const std::list std::string &keywords,
+ const char *openTag, const char *closeTag, int openTagLen, int closeTagLen);
+
+void highlightMarkupSpan (std::string &text, const std::list std::string &keywords);
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,766 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgMenuBar, menu bar */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGDialog.h"
+#include "YGUtils.h"
+#include "ygtkpkgmenubar.h"
+#include
+#include
+#include
+#include
+#include "yzyppwrapper.h"
+#include "YGPackageSelector.h"
+
+// flags handling
+
+#define YAST_GTK_SYSCONFIG "/etc/sysconfig/yast2-gtk"
+
+struct Flags {
+ Flags() {
+ keys = g_key_file_new();
+ g_key_file_load_from_file (keys, YAST_GTK_SYSCONFIG, G_KEY_FILE_NONE, NULL);
+ modified = false;
+ }
+
+ ~Flags() {
+ if (modified)
+ writeFile();
+ g_key_file_free (keys);
+ }
+
+ bool hasKey (const char *variable) {
+ return g_key_file_has_key (keys, "zypp", variable, NULL);
+ }
+
+ bool getBool (const char *variable) {
+ return g_key_file_get_boolean (keys, "zypp", variable, NULL);
+ }
+
+ void setBool (const char *variable, bool value) {
+ g_key_file_set_boolean (keys, "zypp", variable, value);
+ modified = true;
+ }
+
+ private:
+ void writeFile() {
+ FILE *out = fopen (YAST_GTK_SYSCONFIG, "w");
+ if (out) {
+ gsize size;
+ gchar *data = g_key_file_to_data (keys, &size, NULL);
+ fwrite (data, sizeof (char), size, out);
+ g_free (data);
+ fclose (out);
+ }
+ }
+
+ GKeyFile *keys;
+ bool modified;
+};
+
+// utilities
+
+static GtkWidget *append_menu_item (GtkWidget *menu, const char *_text,
+ const char *stock, GCallback callback, gpointer callback_data)
+{
+ std::string text;
+ if (_text)
+ text = YGUtils::mapKBAccel (_text);
+ GtkWidget *item;
+ if (stock && _text) {
+ GtkWidget *icon = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
+ item = gtk_image_menu_item_new_with_mnemonic (text.c_str());
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon);
+ }
+ else if (_text)
+ item = gtk_menu_item_new_with_mnemonic (text.c_str());
+ else if (stock)
+ item = gtk_image_menu_item_new_from_stock (stock, NULL);
+ else
+ item = gtk_separator_menu_item_new();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ if (callback)
+ g_signal_connect (G_OBJECT (item), "activate", callback, callback_data);
+ return item;
+}
+
+static void errorMsg (const std::string &message)
+{
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("Error"));
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
+ "%s", message.c_str());
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+// callback implementations
+// code from yast2-qt
+
+#include
+#include
+#include
+#include
+#include
+#include <fstream>
+
+using zypp::ui::S_Protected;
+using zypp::ui::S_Taboo;
+using zypp::ui::S_Del;
+using zypp::ui::S_Update;
+using zypp::ui::S_Install;
+using zypp::ui::S_AutoDel;
+using zypp::ui::S_AutoUpdate;
+using zypp::ui::S_AutoInstall;
+using zypp::ui::S_KeepInstalled;
+using zypp::ui::S_NoInst;
+typedef zypp::ui::Selectable::Ptr ZyppSel;
+typedef zypp::ui::Status ZyppStatus;
+typedef zypp::ResPoolProxy::const_iterator ZyppPoolIterator;
+typedef zypp::ResPoolProxy ZyppPool;
+//inline ZyppPool zyppPool() { return zypp::getZYpp()->poolProxy(); }
+template<class T> ZyppPoolIterator zyppBegin() { return zyppPool().byKindBegin<T>(); }
+template<class T> ZyppPoolIterator zyppEnd() { return zyppPool().byKindEnd<T>(); }
+inline ZyppPoolIterator zyppPkgBegin() { return zyppBeginzypp::Package(); }
+inline ZyppPoolIterator zyppPkgEnd() { return zyppEndzypp::Package(); }
+inline ZyppPoolIterator zyppPatternsBegin() { return zyppBeginzypp::Pattern(); }
+inline ZyppPoolIterator zyppPatternsEnd() { return zyppEndzypp::Pattern(); }
+
+#define DEFAULT_EXPORT_FILE_NAME "user-packages.xml"
+
+static void
+importSelectable( ZyppSel selectable,
+ bool isWanted,
+ const char * kind )
+{
+ ZyppStatus oldStatus = selectable->status();
+ ZyppStatus newStatus = oldStatus;
+
+ if ( isWanted )
+ {
+ //
+ // Make sure this selectable does not get installed
+ //
+
+ switch ( oldStatus )
+ {
+ case S_Install:
+ case S_AutoInstall:
+ case S_KeepInstalled:
+ case S_Protected:
+ case S_Update:
+ case S_AutoUpdate:
+ newStatus = oldStatus;
+ break;
+
+ case S_Del:
+ case S_AutoDel:
+ newStatus = S_KeepInstalled;
+ yuiDebug() << "Keeping " << kind << " " << selectable->name() << endl;
+ break;
+
+ case S_NoInst:
+ case S_Taboo:
+
+ if ( selectable->hasCandidateObj() )
+ {
+ newStatus = S_Install;
+ yuiDebug() << "Adding " << kind << " " << selectable->name() << endl;
+ }
+ else
+ {
+ yuiDebug() << "Can't add " << kind << " " << selectable->name()
+ << ": No candidate" << endl;
+ }
+ break;
+ }
+ }
+ else // ! isWanted
+ {
+ //
+ // Make sure this selectable does not get installed
+ //
+
+ switch ( oldStatus )
+ {
+ case S_Install:
+ case S_AutoInstall:
+ case S_KeepInstalled:
+ case S_Protected:
+ case S_Update:
+ case S_AutoUpdate:
+ newStatus = S_Del;
+ yuiDebug() << "Deleting " << kind << " " << selectable->name() << endl;
+ break;
+
+ case S_Del:
+ case S_AutoDel:
+ case S_NoInst:
+ case S_Taboo:
+ newStatus = oldStatus;
+ break;
+ }
+ }
+
+ if ( oldStatus != newStatus )
+ selectable->setStatus( newStatus );
+}
+
+static void import_file_cb (GtkMenuItem *item)
+{
+ GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import from"),
+ YGDialog::currentWindow(), GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (filter, "*.xml");
+ gtk_file_filter_add_pattern (filter, "*.xml");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+ filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (filter, "*");
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), DEFAULT_EXPORT_FILE_NAME);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ int ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ if ( ret == GTK_RESPONSE_ACCEPT )
+ {
+ char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ yuiMilestone() << "Importing package list from " << filename << endl;
+
+ try
+ {
+ std::ifstream importFile( filename );
+ zypp::syscontent::Reader reader( importFile );
+
+ //
+ // Put reader contents into maps
+ //
+
+ typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
+ typedef std::pair ImportMapPair;
+
+ map importPkg;
+ map importPatterns;
+
+ for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
+ it != reader.end();
+ ++ it )
+ {
+ string kind = it->kind();
+
+ if ( kind == "package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
+ else if ( kind == "pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
+ }
+
+ yuiDebug() << "Found " << importPkg.size()
+ <<" packages and " << importPatterns.size()
+ << " patterns in " << filename
+ << endl;
+
+
+ //
+ // Set status of all patterns and packages according to import map
+ //
+
+ for ( ZyppPoolIterator it = zyppPatternsBegin();
+ it != zyppPatternsEnd();
+ ++it )
+ {
+ ZyppSel selectable = *it;
+ importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(), "pattern" );
+ }
+
+ for ( ZyppPoolIterator it = zyppPkgBegin();
+ it != zyppPkgEnd();
+ ++it )
+ {
+ ZyppSel selectable = *it;
+ importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(), "package" );
+ }
+
+ YGPackageSelector::get()->popupChanges();
+ }
+ catch (const zypp::Exception & exception)
+ {
+ yuiWarning() << "Error reading package list from " << filename << endl;
+ std::string str (_("Could not open:"));
+ str += " "; str += filename;
+ errorMsg (str);
+ }
+
+ g_free (filename);
+ Ypp::runSolver();
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void export_file_cb (GtkMenuItem *item)
+{
+ GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Export to"),
+ YGDialog::currentWindow(), GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (filter, "*.xml");
+ gtk_file_filter_add_pattern (filter, "*.xml");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+ filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (filter, "*");
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), DEFAULT_EXPORT_FILE_NAME);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ int ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (ret == GTK_RESPONSE_ACCEPT) {
+ char *filename;
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ zypp::syscontent::Writer writer;
+ const zypp::ResPool & pool = zypp::getZYpp()->pool();
+
+ // The ZYPP obfuscated C++ contest proudly presents:
+
+ for_each( pool.begin(), pool.end(),
+ boost::bind( &zypp::syscontent::Writer::addIf,
+ boost::ref( writer ),
+ _1 ) );
+ // Yuck. What a mess.
+ //
+ // Does anybody seriously believe this kind of thing is easier to read,
+ // let alone use? Get real. This is an argument in favour of all C++
+ // haters. And it's one that is really hard to counter.
+ //
+ // -sh 2006-12-13
+
+ try
+ {
+ std::ofstream exportFile( filename );
+ exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
+ exportFile << writer;
+
+ yuiMilestone() << "Package list exported to " << filename << endl;
+ }
+ catch ( std::exception & exception )
+ {
+ yuiWarning() << "Error exporting package list to " << filename << endl;
+
+ // The export might have left over a partially written file.
+ // Try to delete it. Don't care if it doesn't exist and unlink() fails.
+ g_remove (filename);
+
+ // Post error popup
+ std::string str (_("Could not save to:"));
+ str += " "; str += filename;
+ errorMsg (str);
+ }
+
+ g_free (filename);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void create_solver_testcase_cb (GtkMenuItem *item)
+{
+ const char *dirname = "/var/log/YaST2/solverTestcase";
+ std::string msg (_("Use this to generate extensive logs to help tracking "
+ "down bugs in the dependencies resolver."));
+ msg += "\n"; msg += _("The logs will be saved to the directory:");
+ msg += " "; msg += dirname;
+
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK_CANCEL,
+ // Translators: if there is no direct translation to Dependencies Resolver, then translate it to e.g. Dependencies Manager
+ "%s", _("Generate Dependencies Resolver Testcase"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", msg.c_str());
+ int ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ if (ret == GTK_RESPONSE_OK) {
+ bool success;
+ yuiMilestone() << "Generating solver test case START" << endl;
+ success = zypp::getZYpp()->resolver()->createSolverTestcase (dirname);
+ yuiMilestone() << "Generating solver test case END" << endl;
+
+ if (success) {
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO, "%s", _("Success"));
+ msg = _("Dependencies resolver test case written to:");
+ msg += " <tt>";
+ msg += dirname;
+ msg += "</tt>\n";
+ msg += _("Also create a <tt>y2logs.tgz</tt> tar archive to attach to bugzilla?");
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
+ "%s", msg.c_str());
+ ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ if (ret == GTK_RESPONSE_YES)
+ YGUI::ui()->askSaveLogs();
+ }
+ else {
+ msg = _("Failed to create dependencies resolver testcase.\n"
+ "Please check disk space and permissions for:");
+ msg += " <tt>"; msg += dirname; msg += "</tt>";
+ errorMsg (msg.c_str());
+ }
+ }
+}
+
+static void repoManager()
+{
+ yuiMilestone() << "Closing PackageSelector with \"RepoManager\"" << endl;
+ YGUI::ui()->sendEvent( new YMenuEvent( "repo_mgr" ) );
+}
+
+static void onlineUpdateConfiguration()
+{
+ yuiMilestone() << "Closing PackageSelector with \"OnlineUpdateConfiguration\"" << endl;
+ YGUI::ui()->sendEvent( new YMenuEvent( "online_update_configuration" ) );
+}
+
+static void webpinSearch()
+{
+ yuiMilestone() << "Closing PackageSelector with \"webpin\"" << endl;
+ YGUI::ui()->sendEvent( new YMenuEvent( "webpin" ) );
+}
+
+static void manualResolvePackageDependencies()
+{ Ypp::runSolver (true); }
+
+// check menu item flags
+
+struct CheckMenuFlag {
+ CheckMenuFlag (GtkWidget *menu, const char *text) {
+ m_item = gtk_check_menu_item_new_with_mnemonic (text);
+ g_object_set_data_full (G_OBJECT (m_item), "this", this, destructor);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), m_item);
+ }
+
+ void init (Flags *flags) {
+ bool check = getZyppValue();
+
+ const char *var = variable();
+ if (flags->hasKey (var)) {
+ bool c = flags->getBool (var);
+ if (c != check)
+ setZyppValue (c);
+ check = c;
+ }
+
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (m_item), check);
+ g_signal_connect_after (G_OBJECT (m_item), "toggled", G_CALLBACK (toggled_cb), this);
+ }
+
+ virtual const char *variable() = 0;
+ virtual bool getZyppValue() = 0;
+ virtual void setZyppValue (bool on) = 0;
+ virtual void runtimeSync() {}
+
+ void writeFile (bool on) {
+ Flags flags;
+ flags.setBool (variable(), on);
+ }
+
+ static void toggled_cb (GtkCheckMenuItem *item, CheckMenuFlag *pThis) {
+ bool on = gtk_check_menu_item_get_active (item);
+ pThis->setZyppValue (on);
+ pThis->runtimeSync();
+ pThis->writeFile (on);
+ }
+
+ static void destructor (gpointer data) {
+ delete ((CheckMenuFlag *) data);
+ }
+
+ GtkWidget *m_item;
+};
+
+struct AutoCheckItem : public CheckMenuFlag {
+ AutoCheckItem (GtkWidget *menu, const char *text, Flags *flags)
+ : CheckMenuFlag (menu, text) { init (flags); }
+ virtual const char *variable() { return "auto-check"; }
+ virtual bool getZyppValue() { return Ypp::isSolverEnabled(); }
+ virtual void setZyppValue (bool on) { Ypp::setEnableSolver (on); }
+};
+
+struct ShowDevelCheckItem : public CheckMenuFlag {
+ ShowDevelCheckItem (GtkWidget *menu, const char *text, Flags *flags)
+ : CheckMenuFlag (menu, text) { init (flags); }
+ virtual const char *variable() { return "show-devel"; }
+ virtual bool getZyppValue() { return true; }
+ virtual void setZyppValue (bool on)
+ { YGPackageSelector::get()->filterPkgSuffix ("-devel", !on); }
+};
+
+struct ShowDebugCheckItem : public CheckMenuFlag {
+ ShowDebugCheckItem (GtkWidget *menu, const char *text, Flags *flags)
+ : CheckMenuFlag (menu, text) { init (flags); }
+ virtual const char *variable() { return "show-debug"; }
+ virtual bool getZyppValue() { return true; }
+ virtual void setZyppValue (bool on) {
+ YGPackageSelector::get()->filterPkgSuffix ("-debuginfo", !on);
+ YGPackageSelector::get()->filterPkgSuffix ("-debugsource", !on);
+ }
+};
+
+struct SystemVerificationCheckItem : public CheckMenuFlag {
+ SystemVerificationCheckItem (GtkWidget *menu, const char *text, Flags *flags)
+ : CheckMenuFlag (menu, text) { init (flags); }
+ virtual const char *variable() { return "system-verification"; }
+ virtual bool getZyppValue() {
+ return zypp::getZYpp()->resolver()->systemVerification();
+ }
+ virtual void setZyppValue (bool on) {
+ zypp::getZYpp()->resolver()->setSystemVerification (on);
+ }
+ virtual void runtimeSync() {}
+};
+
+#if ZYPP_VERSION > 6031004
+
+struct CleanupDepsCheckItem : public CheckMenuFlag {
+ CleanupDepsCheckItem (GtkWidget *menu, const char *text, Flags *flags)
+ : CheckMenuFlag (menu, text) { init (flags); }
+ virtual const char *variable() { return "cleanup-deps"; }
+ virtual bool getZyppValue() {
+ return zypp::getZYpp()->resolver()->cleandepsOnRemove();
+ }
+ virtual void setZyppValue (bool on) {
+ zypp::getZYpp()->resolver()->setCleandepsOnRemove( on );
+ }
+ virtual void runtimeSync() { Ypp::runSolver(); }
+};
+
+struct AllowVendorChangeCheckItem : public CheckMenuFlag {
+ AllowVendorChangeCheckItem (GtkWidget *menu, const char *text, Flags *flags)
+ : CheckMenuFlag (menu, text) { init (flags); }
+ virtual const char *variable() { return "allow-vendor-change"; }
+ virtual bool getZyppValue() {
+ return zypp::getZYpp()->resolver()->allowVendorChange();
+ }
+ virtual void setZyppValue (bool on) {
+ zypp::getZYpp()->resolver()->setAllowVendorChange( on );
+ }
+ virtual void runtimeSync() { Ypp::runSolver(); }
+};
+
+#endif
+
+static void installSubPkgs (std::string suffix)
+{
+ // Find all matching packages and put them into a QMap
+
+ std::map subPkgs;
+
+ for ( ZyppPoolIterator it = zyppPkgBegin(); it != zyppPkgEnd(); ++it )
+ {
+ std::string name = (*it)->name();
+
+ if (YGUtils::endsWith (name, suffix))
+ {
+ subPkgs[ name ] = *it;
+ yuiDebug() << "Found subpackage: " << name << endl;
+ }
+ }
+
+
+ // Now go through all packages and look if there is a corresponding subpackage in the QMap
+
+ for ( ZyppPoolIterator it = zyppPkgBegin(); it != zyppPkgEnd(); ++it )
+ {
+ std::string name = (*it)->name();
+
+ std::string subPkgName( name + suffix );
+ if ( subPkgs.find( subPkgName ) != subPkgs.end() )
+ {
+ ZyppSel subPkg = subPkgs[ subPkgName ];
+
+ switch ( (*it)->status() )
+ {
+ case S_AutoDel:
+ case S_NoInst:
+ case S_Protected:
+ case S_Taboo:
+ case S_Del:
+ // Don't install the subpackage
+ yuiMilestone() << "Ignoring unwanted subpackage " << subPkgName << endl;
+ break;
+
+ case S_AutoInstall:
+ case S_Install:
+ case S_KeepInstalled:
+
+ // Install the subpackage, but don't try to update it
+
+ if ( ! subPkg->installedObj() )
+ {
+ subPkg->setStatus( S_Install );
+ yuiMilestone() << "Installing subpackage " << subPkgName << endl;
+ }
+ break;
+
+
+ case S_Update:
+ case S_AutoUpdate:
+
+ // Install or update the subpackage
+
+ if ( ! subPkg->installedObj() )
+ {
+ subPkg->setStatus( S_Install );
+ yuiMilestone() << "Installing subpackage " << subPkgName << endl;
+ }
+ else
+ {
+ subPkg->setStatus( S_Update );
+ yuiMilestone() << "Updating subpackage " << subPkgName << endl;
+ }
+ break;
+
+ // Intentionally omitting 'default' branch so the compiler can
+ // catch unhandled enum states
+ }
+ }
+ }
+
+ Ypp::runSolver();
+ YGPackageSelector::get()->popupChanges();
+}
+
+static void install_all_devel_pkgs_cb()
+{ installSubPkgs ("-devel"); }
+
+static void install_all_debug_info_pkgs_cb()
+{ installSubPkgs ("-debuginfo"); }
+
+static void install_all_debug_source_pkgs_cb()
+{ installSubPkgs ("-debugsource"); }
+
+static void show_pkg_changes_cb()
+{ YGPackageSelector::get()->popupChanges(); }
+
+static void show_log_changes_cb()
+{ YGPackageSelector::get()->showHistoryDialog(); }
+
+#ifdef HAS_VESTIGIAL_DIALOG
+static void show_vestigial_packages_cb()
+{ YGPackageSelector::get()->showVestigialDialog(); }
+#endif
+
+static void reset_ignored_dependency_conflicts_cb()
+{ zypp::getZYpp()->resolver()->undo(); }
+
+#include "ygtkpkgproductdialog.h"
+
+static void show_products_cb()
+{
+ YGtkPkgProductDialog dialog;
+ dialog.popup();
+}
+
+static void accept_item_cb (GtkMenuItem *item, YGPackageSelector *selector)
+{ selector->apply(); }
+
+static void reject_item_cb (GtkMenuItem *item, YGPackageSelector *selector)
+{ selector->cancel(); }
+
+YGtkPkgMenuBar::YGtkPkgMenuBar()
+{
+ YGPackageSelector *selector = YGPackageSelector::get();
+ m_menu = gtk_menu_bar_new();
+ Flags flags;
+
+ GtkWidget *menu_bar = m_menu, *item, *submenu;
+ item = append_menu_item (menu_bar, _("F&ile"), NULL, NULL, NULL);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
+ append_menu_item (submenu, _("&Import..."), NULL,
+ G_CALLBACK (import_file_cb), this);
+ append_menu_item (submenu, _("&Export..."), NULL,
+ G_CALLBACK (export_file_cb), this);
+ append_menu_item (submenu, NULL, NULL, NULL, NULL);
+ append_menu_item (submenu, NULL, GTK_STOCK_APPLY, G_CALLBACK (accept_item_cb), selector);
+ append_menu_item (submenu, NULL, GTK_STOCK_QUIT, G_CALLBACK (reject_item_cb), selector);
+ if (selector->repoMgrEnabled()) {
+ item = append_menu_item (menu_bar, _("&Configuration"), NULL, NULL, NULL);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
+ append_menu_item (submenu, _("&Repositories..."), NULL,
+ G_CALLBACK (repoManager), this);
+ if (selector->onlineUpdateMode())
+ append_menu_item (submenu, _("&Online Update..."), NULL,
+ G_CALLBACK (onlineUpdateConfiguration), this);
+ else
+ append_menu_item (submenu, _("Search Packages on &Web..."), NULL,
+ G_CALLBACK (webpinSearch), this);
+ }
+ item = append_menu_item (menu_bar, _("&Dependencies"), NULL, NULL, NULL);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
+ append_menu_item (submenu, _("&Check Now"), NULL,
+ G_CALLBACK (manualResolvePackageDependencies), this);
+ new AutoCheckItem (submenu, _("&Autocheck"), &flags);
+
+ if (!selector->onlineUpdateMode()) {
+ item = append_menu_item (menu_bar, _("&Options"), NULL, NULL, NULL);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
+ // Translators: don't translate the "-devel"
+ new ShowDevelCheckItem (submenu, _("Show -de&vel Packages"), &flags);
+ // Translators: don't translate the "-debuginfo/-debugsource" part
+ new ShowDebugCheckItem (submenu, _("Show -&debuginfo/-debugsource Packages"), &flags);
+ new SystemVerificationCheckItem (submenu, _("&System Verification Mode"), &flags);
+ new CleanupDepsCheckItem (submenu, _("&Cleanup when deleting packages"), &flags);
+ new AllowVendorChangeCheckItem (submenu, _("&Allow vendor change"), &flags);
+ }
+
+ item = append_menu_item (menu_bar, _("E&xtras"), NULL, NULL, NULL);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
+ append_menu_item (submenu, _("Show &Products"), NULL,
+ G_CALLBACK (show_products_cb), this);
+ append_menu_item (submenu, _("Show &Changes"), NULL,
+ G_CALLBACK (show_pkg_changes_cb), this);
+ if (!selector->onlineUpdateMode()) {
+ append_menu_item (submenu, _("Show &History"), NULL,
+ G_CALLBACK (show_log_changes_cb), this);
+#ifdef HAS_VESTIGIAL_DIALOG
+ append_menu_item (submenu, _("Show &Unneeded Dependencies"), NULL,
+ G_CALLBACK (show_vestigial_packages_cb), this);
+#endif
+ }
+ append_menu_item (submenu, NULL, NULL, NULL, NULL);
+ // Translators: keep "-_devel" untranslated
+ append_menu_item (submenu, _("Install All Matching -&devel Packages"), NULL,
+ G_CALLBACK (install_all_devel_pkgs_cb), this);
+ // Translators: keep "-debug-_info" untranslated
+ append_menu_item (submenu, _("Install All Matching -debug-&sinfo Packages"), NULL,
+ G_CALLBACK (install_all_debug_info_pkgs_cb), this);
+ // Translators: keep "-debug-_source" untranslated
+ append_menu_item (submenu, _("Install All Matching -debug-&source Packages"), NULL,
+ G_CALLBACK (install_all_debug_source_pkgs_cb), this);
+ append_menu_item (submenu, NULL, NULL, NULL, NULL);
+ append_menu_item (submenu, _("Generate Dependencies Resolver &Testcase"), NULL,
+ G_CALLBACK (create_solver_testcase_cb), this);
+ append_menu_item (submenu, _("Reset &Ignored Dependencies Conflicts"), NULL,
+ G_CALLBACK (reset_ignored_dependency_conflicts_cb), this);
+
+ //** TEMP: work-around global-menubar-applet: see bug 595560
+ //** will call show_all() at YGPackageSelector.cc
+ //gtk_widget_show_all (m_menu);
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgmenubar.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,24 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* A menu bar identical to that from yast2-qt.
+*/
+
+#ifndef YGTK_PKG_MENU_BAR_H
+#define YGTK_PKG_MENU_BAR_H
+
+#include
+
+struct YGtkPkgMenuBar
+{
+ YGtkPkgMenuBar();
+
+ GtkWidget *getWidget() { return m_menu; }
+
+ private:
+ GtkWidget *m_menu;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,540 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgPatternList, pattern and language list implementations */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGUtils.h"
+#include "ygtkpkgpatternview.h"
+#include "ygtktreeview.h"
+#include "ygtkcellrenderertext.h"
+#include
+
+#define GRAY_COLOR "#727272"
+
+enum Column {
+ HAS_CHECK_COLUMN, CHECK_COLUMN, HAS_ICON_COLUMN, ICON_COLUMN,
+ TEXT_COLUMN, ORDER_COLUMN, POINTER_COLUMN, TOTAL_COLUMNS
+};
+
+struct YGtkPkgPatternView::Impl : public Ypp::SelListener {
+ GtkWidget *scroll, *view;
+
+ Impl()
+ { Ypp::addSelListener (this); }
+ ~Impl()
+ {
+ Ypp::removeSelListener (this);
+ if (!g_object_get_data (G_OBJECT (getModel()), "patterns"))
+ gtk_tree_model_foreach (getModel(), free_foreach_cb, this);
+ }
+
+ GtkTreeModel *getModel()
+ { return gtk_tree_view_get_model (GTK_TREE_VIEW (view)); }
+
+ static gboolean free_foreach_cb (GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer data)
+ {
+ gpointer _data;
+ gtk_tree_model_get (model, iter, POINTER_COLUMN, &_data, -1);
+ g_free (_data);
+ return FALSE;
+ }
+
+ static gboolean update_foreach_cb (GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer data)
+ {
+ gpointer _data;
+ gtk_tree_model_get (model, iter, POINTER_COLUMN, &_data, -1);
+ if (_data) {
+ ZyppSelectablePtr zsel = (ZyppSelectablePtr) _data;
+ Ypp::Selectable sel (zsel);
+
+ GtkTreeStore *store = GTK_TREE_STORE (model);
+ gtk_tree_store_set (store, iter, CHECK_COLUMN,
+ sel.isInstalled() || sel.toInstall(), -1);
+ }
+ return FALSE;
+ }
+
+ virtual void selectableModified()
+ { gtk_tree_model_foreach (getModel(), update_foreach_cb, this); }
+};
+
+static Ypp::Selectable get_iter_selectable (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ if (g_object_get_data (G_OBJECT (model), "patterns")) {
+ ZyppSelectablePtr zsel;
+ gtk_tree_model_get (model, iter, POINTER_COLUMN, &zsel, -1);
+ return Ypp::Selectable (zsel);
+ }
+ else {
+ gchar *code;
+ gtk_tree_model_get (model, iter, POINTER_COLUMN, &code, -1);
+ zypp::Locale locale (code);
+ g_free (code);
+ return Ypp::Selectable (locale);
+ }
+}
+
+static void set_row (
+ GtkTreeStore *store, GtkTreeIter *iter, Ypp::Selectable &sel, ZyppPattern pattern)
+{
+ std::string order;
+ GdkPixbuf *pixbuf = 0;
+ gpointer ptr;
+ if (pattern) {
+ std::string filename (pattern->icon().asString());
+ if (filename == zypp::Pathname("yast-system").asString() || filename.empty())
+ filename = "pattern-generic";
+ if (filename.compare (0, 2, "./", 2) == 0)
+ filename.erase (0, 2);
+ filename = zypp::str::form ("%s/icons/%dx%d/apps/%s.png",
+ THEMEDIR, 32, 32, filename.c_str());
+ pixbuf = YGUtils::loadPixbuf (filename);
+/*
+ if (pixbuf && !sel.isInstalled()) {
+ GdkPixbuf *_pixbuf = pixbuf;
+ pixbuf = YGUtils::setOpacity (_pixbuf, 50, true);
+ g_object_unref (_pixbuf);
+ }
+*/
+ order = pattern->order();
+ ptr = get_pointer (sel.zyppSel());
+ }
+ else
+ ptr = g_strdup (sel.zyppLocale().code().c_str());
+
+ gtk_tree_store_set (store, iter, HAS_CHECK_COLUMN, TRUE,
+ CHECK_COLUMN, sel.isInstalled() || sel.toInstall(), HAS_ICON_COLUMN, TRUE,
+ ICON_COLUMN, pixbuf, TEXT_COLUMN, (sel.name() + '\n').c_str(),
+ ORDER_COLUMN, order.c_str(),
+ POINTER_COLUMN, ptr, -1);
+
+ if (pixbuf)
+ g_object_unref (G_OBJECT (pixbuf));
+}
+
+static gboolean set_rows_cb (GtkTreeModel *model,
+ GtkTreePath *path, GtkTreeIter *iter, gpointer data)
+{
+ gpointer _data;
+ gtk_tree_model_get (model, iter, POINTER_COLUMN, &_data, -1);
+ if (!_data) return FALSE;
+
+ Ypp::Selectable sel (get_iter_selectable (model, iter));
+
+ int installed, total;
+ Ypp::Collection (sel).stats (&installed, &total);
+ gchar *text = g_strdup_printf ("%s\n<small>Installed %d of %d</small></span>",
+ sel.name().c_str(), installed, total);
+
+ GtkTreeStore *store = GTK_TREE_STORE (model);
+ gtk_tree_store_set (store, iter, TEXT_COLUMN, text, -1);
+ g_free (text);
+ return FALSE;
+}
+
+static gboolean set_rows_idle (gpointer data)
+{
+ gtk_tree_model_foreach (GTK_TREE_MODEL (data), set_rows_cb, NULL);
+ return FALSE;
+}
+
+static bool find_name (GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter, const std::string &name)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ bool done = false;
+ if (gtk_tree_model_iter_children (model, iter, parent))
+ do {
+ gchar *value;
+ gtk_tree_model_get (model, iter, TEXT_COLUMN, &value, -1);
+ if (name == value)
+ done = true;
+ g_free (value);
+ if (done)
+ return true;
+ } while (gtk_tree_model_iter_next (model, iter));
+ return false;
+}
+
+static bool find_place (GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter, const std::string &order)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ bool done = false;
+ if (gtk_tree_model_iter_children (model, iter, parent))
+ do {
+ gchar *value;
+ gtk_tree_model_get (model, iter, ORDER_COLUMN, &value, -1);
+ if (order < value)
+ done = true;
+ g_free (value);
+ if (done) return true;
+ } while (gtk_tree_model_iter_next (model, iter));
+ return false;
+}
+
+static void insert_node (GtkTreeStore *store, GtkTreeIter *parent, GtkTreeIter *iter, const std::string &order)
+{
+ if (find_place (store, parent, iter, order)) {
+ GtkTreeIter sibling = *iter;
+ gtk_tree_store_insert_before (store, iter, parent, &sibling);
+ }
+ else
+ gtk_tree_store_append (store, iter, parent);
+}
+
+static void insert_pattern (
+ GtkTreeStore *store, GtkTreeIter *parent, Ypp::Selectable &sel, ZyppPattern pattern)
+{
+ GtkTreeIter iter;
+ insert_node (store, parent, &iter, pattern->order());
+ set_row (store, &iter, sel, pattern);
+}
+
+static void insert_category (GtkTreeStore *store, Ypp::Selectable &sel, ZyppPattern pattern)
+{
+ GtkTreeIter iter;
+ std::string text ("<big><b>" + pattern->category() + "</b></big>");
+
+ if (!find_name (store, NULL, &iter, text)) {
+ insert_node (store, NULL, &iter, pattern->order());
+ gtk_tree_store_set (store, &iter, HAS_CHECK_COLUMN, FALSE,
+ CHECK_COLUMN, FALSE, HAS_ICON_COLUMN, FALSE, ICON_COLUMN, NULL,
+ TEXT_COLUMN, text.c_str(),
+ ORDER_COLUMN, pattern->order().c_str(), POINTER_COLUMN, NULL, -1);
+ }
+ insert_pattern (store, &iter, sel, pattern);
+}
+
+static void insert_language (GtkTreeStore *store, Ypp::Selectable &sel)
+{
+ std::string name (sel.name());
+ bool done = false;
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ GtkTreeIter iter;
+ if (gtk_tree_model_iter_children (model, &iter, NULL))
+ do {
+ gchar *value;
+ gtk_tree_model_get (model, &iter, TEXT_COLUMN, &value, -1);
+ if (g_utf8_collate (name.c_str(), value) < 0)
+ done = true;
+ g_free (value);
+ if (done) break;
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ if (done) {
+ GtkTreeIter sibling = iter;
+ gtk_tree_store_insert_before (store, &iter, NULL, &sibling);
+ }
+ else
+ gtk_tree_store_append (store, &iter, NULL);
+
+ set_row (store, &iter, sel, NULL);
+}
+
+static void install_cb (GtkWidget *widget, ZyppSelectablePtr zsel)
+{ Ypp::Selectable (zsel).install(); }
+static void undo_cb (GtkWidget *widget, ZyppSelectablePtr zsel)
+{ Ypp::Selectable (zsel).undo(); }
+static void remove_cb (GtkWidget *widget, ZyppSelectablePtr zsel)
+{ Ypp::Selectable (zsel).remove(); }
+
+static GtkWidget *menu_item_append (GtkWidget *menu, const char *_label, const char *stock, bool sensitive)
+{
+ std::string label;
+ if (_label)
+ label = YGUtils::mapKBAccel (_label);
+ GtkWidget *item;
+ if (_label) {
+ item = gtk_image_menu_item_new_with_mnemonic (label.c_str());
+ if (stock) {
+ GtkWidget *icon = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon);
+ }
+ }
+ else
+ item = gtk_image_menu_item_new_from_stock (stock, NULL);
+ gtk_widget_set_sensitive (item, sensitive);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ return item;
+}
+
+static void right_click_cb (YGtkTreeView *yview, gboolean outreach, YGtkPkgPatternView *pThis)
+{
+ if (!outreach) {
+ GtkTreeView *view = GTK_TREE_VIEW (yview);
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ ZyppSelectablePtr zsel;
+ gtk_tree_model_get (model, &iter, POINTER_COLUMN, &zsel, -1);
+ Ypp::Selectable sel (zsel);
+
+ GtkWidget *menu = gtk_menu_new(), *item;
+ if (sel.toModify()) {
+ item = menu_item_append (menu, NULL, GTK_STOCK_UNDO, true);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (undo_cb), zsel);
+ }
+ else {
+ if (sel.isInstalled()) {
+ if (sel.canRemove()) {
+ item = menu_item_append (menu, _("&Remove"), GTK_STOCK_REMOVE, true);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (remove_cb), zsel);
+ }
+ else
+ menu_item_append (menu, _("Remove: cannot remove patterns"), NULL, false);
+ }
+ else {
+ item = menu_item_append (menu, _("&Install"), GTK_STOCK_ADD, true);
+ g_signal_connect (G_OBJECT (item), "activate",
+ G_CALLBACK (install_cb), zsel);
+ }
+ }
+
+ ygtk_tree_view_popup_menu (yview, menu);
+ }
+ }
+}
+
+static void toggle_iter (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ Ypp::Selectable sel (get_iter_selectable (model, iter));
+ sel.toModify() ? sel.undo() : sel.install();
+}
+
+static void row_activated_cb (GtkTreeView *view,
+ GtkTreePath *path, GtkTreeViewColumn *column, YGtkPkgPatternView *pThis)
+{
+ GtkTreeModel *model = pThis->impl->getModel();
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter (model, &iter, path))
+ toggle_iter (model, &iter);
+}
+
+static void toggled_cb (GtkCellRendererToggle *renderer, gchar *path, YGtkPkgPatternView *pThis)
+{
+ GtkTreeModel *model = pThis->impl->getModel();
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter_from_string (model, &iter, path))
+ toggle_iter (model, &iter);
+}
+
+static gboolean can_tree_select_cb (GtkTreeSelection *selection,
+ GtkTreeModel *model, GtkTreePath *path, gboolean path_selected, gpointer data)
+{
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gpointer _data;
+ gtk_tree_model_get (model, &iter, POINTER_COLUMN, &_data, -1);
+ return _data != NULL;
+}
+
+static void selection_changed_cb (GtkTreeSelection *selection, YGtkPkgPatternView *pThis)
+{ pThis->notify(); }
+
+static gboolean query_tooltip_cb (GtkWidget *widget, gint x, gint y,
+ gboolean keyboard_mode, GtkTooltip *tooltip, YGtkPkgPatternView *pThis)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (widget);
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ if (gtk_tree_view_get_tooltip_context (view,
+ &x, &y, keyboard_mode, &model, &path, &iter)) {
+ gtk_tree_view_set_tooltip_row (view, tooltip, path);
+ gtk_tree_path_free (path);
+
+ GtkTreeViewColumn *column;
+ int bx, by;
+ gtk_tree_view_convert_widget_to_bin_window_coords (
+ view, x, y, &bx, &by);
+ gtk_tree_view_get_path_at_pos (
+ view, x, y, NULL, &column, NULL, NULL);
+
+ ZyppSelectablePtr zsel;
+ gtk_tree_model_get (model, &iter, POINTER_COLUMN, &zsel, -1);
+ if (zsel) {
+ Ypp::Selectable sel (zsel);
+
+ if (column == ygtk_tree_view_get_column (YGTK_TREE_VIEW (view), 0)) { // check-marks
+ if (sel.isInstalled())
+ gtk_tooltip_set_text (tooltip,
+ _("Installed: cannot remove a pattern.\n\n"
+ "You must manually remove the individual packages you no "
+ "longer want to keep."));
+ else
+ gtk_tooltip_set_text (tooltip, _("Not installed"));
+ }
+ else {
+ std::string text (YGUtils::escapeMarkup (sel.description (false)));
+ gtk_tooltip_set_text (tooltip, text.c_str());
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+YGtkPkgPatternView::YGtkPkgPatternView (Ypp::Selectable::Type type)
+: impl (new Impl())
+{
+ assert (type == Ypp::Selectable::LANGUAGE || type == Ypp::Selectable::PATTERN);
+
+ GtkTreeStore *store = gtk_tree_store_new (TOTAL_COLUMNS, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_POINTER);
+
+ if (type == Ypp::Selectable::LANGUAGE) {
+ Ypp::LangQuery query;
+ Ypp::List list (query);
+ list.sort (Ypp::List::NAME_SORT, true);
+ for (int i = 0; i < list.size(); i++)
+ insert_language (store, list.get(i));
+ }
+ else {
+ // HACK: in opensuse 11.2, zypp crashes when re-iterating patterns
+#if 1 // zypp::PoolQuery is crashing on me when using Patterns
+ Ypp::PoolQuery query (type);
+ while (query.hasNext()) {
+ Ypp::Selectable sel = query.next();
+ ZyppPattern pattern = castZyppPattern (sel.zyppSel()->theObj());
+ if (pattern->userVisible())
+ insert_category (store, sel, pattern);
+ }
+/* static Ypp::List list (0);
+ if (list.size() == 0) {
+ Ypp::PoolQuery query (type);
+ list = Ypp::List (query);
+ }
+ for (int i = 0; i < list.size(); i++) {
+ Ypp::Selectable &sel = list.get (i);
+ ZyppPattern pattern = castZyppPattern (sel.zyppSel()->theObj());
+ if (pattern->userVisible())
+ insert_category (store, sel, pattern);
+ }*/
+#else
+ for (zypp::ResPoolProxy::const_iterator it =
+ zypp::getZYpp()->poolProxy().byKindBegin zypp::Pattern();
+ it != zypp::getZYpp()->poolProxy().byKindEnd zypp::Pattern();
+ it++) {
+ Ypp::Selectable sel (*it);
+ ZyppPattern pattern = castZyppPattern (sel.zyppSel()->theObj());
+ if (pattern->userVisible())
+ insert_category (store, sel, pattern);
+ }
+#endif
+ g_object_set_data (G_OBJECT (store), "patterns", GINT_TO_POINTER (1));
+ }
+
+ impl->view = ygtk_tree_view_new (NULL);
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
+ g_object_unref (G_OBJECT (store));
+ gtk_tree_view_set_headers_visible (view, FALSE);
+ gtk_tree_view_set_search_column (view, TEXT_COLUMN);
+ gtk_tree_view_expand_all (view);
+ gtk_tree_view_set_show_expanders (view, FALSE);
+ gtk_widget_set_has_tooltip (impl->view, TRUE);
+ g_signal_connect (G_OBJECT (view), "query-tooltip",
+ G_CALLBACK (query_tooltip_cb), this);
+ g_signal_connect (G_OBJECT (view), "right-click",
+ G_CALLBACK (right_click_cb), this);
+ g_signal_connect (G_OBJECT (view), "row-activated",
+ G_CALLBACK (row_activated_cb), this);
+
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "active", CHECK_COLUMN, "visible", HAS_CHECK_COLUMN, NULL);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (toggled_cb), this);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
+
+ bool reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title (column, NULL);
+ gtk_tree_view_column_set_spacing (column, 4);
+
+ GtkCellRenderer *pix_renderer = gtk_cell_renderer_pixbuf_new();
+ if (!reverse)
+ gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
+
+ renderer = ygtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "markup", TEXT_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+
+ if (reverse)
+ gtk_tree_view_column_pack_start (column, pix_renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, pix_renderer,
+ "pixbuf", ICON_COLUMN, "visible", HAS_ICON_COLUMN, NULL);
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ ygtk_tree_view_append_column (YGTK_TREE_VIEW (view), column);
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ gtk_tree_selection_set_select_function (selection, can_tree_select_cb, NULL, NULL);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_changed_cb), this);
+ clearSelection();
+
+ impl->scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (impl->scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (impl->scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (impl->scroll), impl->view);
+ gtk_widget_show_all (impl->scroll);
+
+ g_idle_add_full (G_PRIORITY_LOW, set_rows_idle, store, NULL);
+}
+
+YGtkPkgPatternView::~YGtkPkgPatternView()
+{ delete impl; }
+
+GtkWidget *YGtkPkgPatternView::getWidget()
+{ return impl->scroll; }
+
+void YGtkPkgPatternView::clearSelection()
+{
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb, this);
+ gtk_tree_selection_unselect_all (selection);
+ g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb, this);
+}
+
+bool YGtkPkgPatternView::writeQuery (Ypp::PoolQuery &query)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ Ypp::Selectable sel (get_iter_selectable (model, &iter));
+ Ypp::Collection collection (sel);
+ query.addCriteria (new Ypp::FromCollectionMatch (collection));
+ return true;
+ }
+ return false;
+}
+
+bool isPatternsPoolEmpty()
+{ return zyppPool().empty zypp::Pattern(); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgpatternview.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,33 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Pattern and language list boxes.
+*/
+
+#ifndef YGTK_PKG_PATTERN_LIST_H
+#define YGTK_PKG_PATTERN_LIST_H
+
+#include "ygtkpkgquerywidget.h"
+#include
+
+struct YGtkPkgPatternView : public YGtkPkgQueryWidget
+{
+ YGtkPkgPatternView (Ypp::Selectable::Type type);
+ virtual ~YGtkPkgPatternView();
+ virtual GtkWidget *getWidget();
+
+ virtual bool begsUpdate() { return false; }
+ virtual void updateList (Ypp::List list) {}
+
+ virtual void clearSelection();
+ virtual bool writeQuery (Ypp::PoolQuery &query);
+
+ struct Impl;
+ Impl *impl;
+};
+
+bool isPatternsPoolEmpty();
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,181 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgMenuBar, menu bar */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGDialog.h"
+#include "YGUtils.h"
+#include "ygtkpkgproductdialog.h"
+#include
+#include "ygtkrichtext.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef zypp::ResPoolProxy ZyppPool;
+typedef zypp::ResPoolProxy::const_iterator ZyppPoolIterator;
+inline ZyppPool zyppPool() { return zypp::getZYpp()->poolProxy(); }
+template<class T> ZyppPoolIterator zyppBegin() { return zyppPool().byKindBegin<T>(); }
+template<class T> ZyppPoolIterator zyppEnd() { return zyppPool().byKindEnd<T>(); }
+inline ZyppPoolIterator zyppProductsBegin() { return zyppBeginzypp::Product(); }
+inline ZyppPoolIterator zyppProductsEnd() { return zyppEndzypp::Product(); }
+typedef zypp::ui::Selectable::Ptr ZyppSel;
+typedef zypp::ResObject::constPtr ZyppObj;
+typedef zypp::Product::constPtr ZyppProduct;
+inline ZyppProduct tryCastToZyppProduct( ZyppObj zyppObj )
+{ return zypp::dynamic_pointer_cast<const zypp::Product>( zyppObj ); }
+
+enum {
+ INSTALLED_COLUMN, TEXT_COLUMN, VERSION_COLUMN, VENDOR_COLUMN, DESCRIPTION_COLUMN, TOTAL_COLUMNS
+};
+
+static void selection_changed_cb (GtkTreeSelection *selection, YGtkRichText *description)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ char *text;
+ gtk_tree_model_get (model, &iter, DESCRIPTION_COLUMN, &text, -1);
+ ygtk_rich_text_set_text (description, text);
+ g_free (text);
+ }
+ else
+ ygtk_rich_text_set_plain_text (description, "");
+}
+
+YGtkPkgProductDialog::YGtkPkgProductDialog()
+{
+ GtkListStore *store = gtk_list_store_new (TOTAL_COLUMNS, G_TYPE_BOOLEAN,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ for (ZyppPoolIterator it = zyppProductsBegin(); it != zyppProductsEnd(); it++) {
+ ZyppSel sel = *it;
+ ZyppProduct prod = tryCastToZyppProduct( sel->theObj() );
+
+ std::string text (sel->name() + "\n<small>" + prod->summary() + "</small>");
+
+ ZyppObj available = sel->candidateObj();
+ ZyppObj installed = sel->installedObj();
+
+ std::string version;
+ if (!!available && !!installed && (available->edition() != installed->edition())) {
+ version = available->edition().asString() + "\n<small>";
+ version += installed->edition().asString() + "</small>";
+ }
+ else if (!!available)
+ version = available->edition().asString();
+ else if (!!installed)
+ version = installed->edition().asString();
+
+ std::string description;
+ if (!!available) {
+ description += std::string ("<p><b>") + _("Candidate provides:") + " </b>";
+ description += available->dep (zypp::Dep::PROVIDES).begin()->asString();
+ }
+ if (!!installed) {
+ description += std::string ("<p><b>") + _("Installed provides:") + " </b>";
+ description += installed->dep (zypp::Dep::PROVIDES).begin()->asString();
+ }
+
+
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, INSTALLED_COLUMN,
+ sel->candidateObj().isSatisfied() || sel->hasInstalledObj(),
+ TEXT_COLUMN, text.c_str(), VERSION_COLUMN, version.c_str(),
+ VENDOR_COLUMN, prod->vendor().c_str(), DESCRIPTION_COLUMN,
+ description.c_str(), -1);
+ }
+
+ GtkWidget *description = ygtk_rich_text_new();
+ GtkWidget *description_scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (description_scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (description_scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (description_scroll), description);
+
+ GtkWidget *view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ GtkTreeView *tview = GTK_TREE_VIEW (view);
+ g_object_unref (G_OBJECT (store));
+ gtk_tree_view_set_search_column (tview, TEXT_COLUMN);
+ gtk_tree_view_set_rules_hint (tview, TRUE);
+
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "active", INSTALLED_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "sensitive", FALSE, NULL);
+ gtk_tree_view_append_column (tview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Name"), renderer, "markup", TEXT_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (tview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Version"), renderer, "markup", VERSION_COLUMN, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (tview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Vendor"), renderer, "text", VENDOR_COLUMN, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (tview, column);
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (tview);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_changed_cb), description);
+
+ GtkWidget *scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (scroll), view);
+
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ // Translators: same as "Listing of Products"
+ GtkDialogFlags (0), GTK_MESSAGE_OTHER, GTK_BUTTONS_CLOSE, _("Products Listing"));
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 500);
+
+ GtkWidget *vpaned = gtk_vpaned_new();
+ gtk_paned_pack1 (GTK_PANED (vpaned), scroll, TRUE, FALSE);
+ gtk_paned_pack2 (GTK_PANED (vpaned), description_scroll, FALSE, TRUE);
+ YGUtils::setPaneRelPosition (vpaned, .70);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vpaned);
+
+ gtk_widget_show_all (dialog);
+ m_dialog = dialog;
+}
+
+YGtkPkgProductDialog::~YGtkPkgProductDialog()
+{ gtk_widget_destroy (m_dialog); }
+
+void YGtkPkgProductDialog::popup()
+{ gtk_dialog_run (GTK_DIALOG (m_dialog)); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgproductdialog.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,25 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Show zypp::Product list.
+*/
+
+#ifndef YGTK_PKG_PRODUCT_DIALOG_H
+#define YGTK_PKG_PRODUCT_DIALOG_H
+
+#include
+
+struct YGtkPkgProductDialog
+{
+ YGtkPkgProductDialog();
+ ~YGtkPkgProductDialog();
+
+ void popup();
+
+private:
+ GtkWidget *m_dialog;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,109 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgQueryCombo, an umbrella for any group of QueryWidget widgets */
+// check the header file for information about this widget
+
+/*
+ Textdomain "yast2-gtk"
+ */
+
+#define YUILogComponent "gtk-pkg"
+#include "YGi18n.h"
+#include "config.h"
+#include "YGUtils.h"
+#include "ygtkpkgquerycombo.h"
+#include
+
+struct YGtkPkgQueryCombo::Impl {
+ GtkWidget *vbox, *combo, *content;
+ Factory *factory;
+ YGtkPkgQueryWidget *child;
+
+ Impl (Factory *factory) : factory (factory), child (NULL) {}
+
+ ~Impl()
+ { delete child; }
+};
+
+static void set_child (YGtkPkgQueryCombo *pThis, int index)
+{
+ if (pThis->impl->child)
+ delete pThis->impl->child;
+ YGtkPkgQueryWidget *child = pThis->impl->factory->createQueryWidget (pThis, index);
+ pThis->impl->child = child;
+ child->setListener (pThis->listener);
+
+ GtkWidget *cur_child = gtk_bin_get_child (GTK_BIN (pThis->impl->content));
+ if (cur_child)
+ gtk_container_remove (GTK_CONTAINER (pThis->impl->content), cur_child);
+ gtk_container_add (GTK_CONTAINER (pThis->impl->content), child->getWidget());
+ gtk_widget_grab_focus (child->getWidget());
+}
+
+static void combo_changed_cb (GtkComboBox *combo, YGtkPkgQueryCombo *pThis)
+{
+ Ypp::Busy busy (0);
+ set_child (pThis, gtk_combo_box_get_active (combo));
+ pThis->notify();
+}
+
+YGtkPkgQueryCombo::YGtkPkgQueryCombo (Factory *factory)
+: impl (new Impl (factory))
+{
+ impl->combo = gtk_combo_box_new_text();
+ gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (impl->combo),
+ YGUtils::empty_row_is_separator_cb, GINT_TO_POINTER (0), NULL);
+ g_signal_connect_after (G_OBJECT (impl->combo), "changed",
+ G_CALLBACK (combo_changed_cb), this);
+ impl->content = gtk_event_box_new();
+ impl->vbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (impl->vbox), impl->combo, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (impl->vbox), impl->content, TRUE, TRUE, 0);
+}
+
+YGtkPkgQueryCombo::~YGtkPkgQueryCombo()
+{ delete impl; }
+
+GtkWidget *YGtkPkgQueryCombo::getWidget()
+{ return impl->vbox; }
+
+void YGtkPkgQueryCombo::add (const char *title)
+{
+ GtkComboBox *combo = GTK_COMBO_BOX (impl->combo);
+ gtk_combo_box_append_text (combo, title);
+}
+
+void YGtkPkgQueryCombo::setActive (int index)
+{
+ GtkComboBox *combo = GTK_COMBO_BOX (impl->combo);
+ if (gtk_combo_box_get_active (combo) != index) {
+ g_signal_handlers_block_by_func (combo, (gpointer) combo_changed_cb, this);
+ gtk_combo_box_set_active (combo, index);
+ g_signal_handlers_unblock_by_func (combo, (gpointer) combo_changed_cb, this);
+ set_child (this, index);
+ }
+}
+
+bool YGtkPkgQueryCombo::begsUpdate()
+{ return impl->child->begsUpdate(); }
+
+void YGtkPkgQueryCombo::updateList (Ypp::List list)
+{ return impl->child->updateList (list); }
+
+void YGtkPkgQueryCombo::clearSelection()
+{ return impl->child->clearSelection(); }
+
+bool YGtkPkgQueryCombo::writeQuery (Ypp::PoolQuery &query)
+{ return impl->child->writeQuery (query); }
+
+void YGtkPkgQueryCombo::setListener (Listener *listener)
+{
+ YGtkPkgQueryWidget::setListener (listener);
+ if (impl->child)
+ impl->child->setListener (listener);
+}
+
+GtkWidget *YGtkPkgQueryCombo::createToolbox()
+{ return impl->child->createToolbox(); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerycombo.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,44 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Comprises several QueryWidget widgets.
+ You probably want to use this in cooperation with YGtkPkgFilerBox.
+*/
+
+#ifndef YGTK_PKG_QUERY_COMBO_H
+#define YGTK_PKG_QUERY_COMBO_H
+
+#include "ygtkpkgquerywidget.h"
+#include
+
+struct YGtkPkgQueryCombo : public YGtkPkgQueryWidget
+{
+ struct Factory {
+ virtual YGtkPkgQueryWidget *createQueryWidget (
+ YGtkPkgQueryCombo *combo, int index) = 0;
+ };
+
+ YGtkPkgQueryCombo (Factory *factory);
+ virtual ~YGtkPkgQueryCombo();
+ virtual GtkWidget *getWidget();
+
+ void add (const char *title);
+ void setActive (int index);
+
+ virtual bool begsUpdate();
+ virtual void updateList (Ypp::List list);
+
+ virtual void clearSelection();
+ virtual bool writeQuery (Ypp::PoolQuery &query);
+
+ virtual GtkWidget *createToolbox();
+
+ virtual void setListener (Listener *listener);
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerywidget.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerywidget.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerywidget.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgquerywidget.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,64 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Abstract for widgets that support query.
+*/
+
+#ifndef YGTK_PKG_QUERY_WIDGET_H
+#define YGTK_PKG_QUERY_WIDGET_H
+
+#include
+#include "yzyppwrapper.h"
+
+struct YGtkPkgQueryWidget
+{
+ virtual ~YGtkPkgQueryWidget() {}
+ virtual GtkWidget *getWidget() = 0;
+
+ // if begsUpdate is true, the current List without this filter applied
+ // will be passed to updateList() so you can e.g. avoid presenting
+ // entries for which there is no match.
+ virtual bool begsUpdate() = 0;
+ virtual void updateList (Ypp::List list) = 0;
+
+ virtual void clearSelection() = 0;
+ virtual bool writeQuery (Ypp::PoolQuery &query) = 0;
+
+ virtual GtkWidget *createToolbox() { return NULL; }
+
+ struct Listener {
+ virtual void refreshQuery() = 0;
+ };
+
+ virtual void setListener (Listener *listener) { this->listener = listener; }
+ Listener *listener;
+
+ bool modified; // flag for internal use
+
+ //protected:
+ void notify() { if (listener) listener->refreshQuery(); }
+
+ void notifyDelay (int delay)
+ {
+ static guint timeout_id = 0;
+ struct inner {
+ static gboolean timeout_cb (gpointer data)
+ {
+ YGtkPkgQueryWidget *pThis = (YGtkPkgQueryWidget *) data;
+ timeout_id = 0;
+ pThis->notify();
+ return FALSE;
+ }
+ };
+ if (timeout_id) g_source_remove (timeout_id);
+ timeout_id = g_timeout_add_full (
+ G_PRIORITY_LOW, delay, inner::timeout_cb, this, NULL);
+ }
+
+protected:
+ YGtkPkgQueryWidget() : listener (NULL) {}
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,165 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgRpmGroupsView, rpm-groups tree-view */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "YGUI.h"
+#include "config.h"
+#include "YGUtils.h"
+#include "ygtkpkgrpmgroupsview.h"
+#include "ygtkpkglistview.h"
+#include
+
+enum {
+ TEXT_COLUMN, DATA_COLUMN, TOTAL_COLUMNS
+};
+
+static void addNode (GtkTreeStore *store, GtkTreeIter *parent, const YStringTreeItem *item)
+{
+ if (!item) return;
+
+ GtkTreeIter iter;
+ gtk_tree_store_append (store, &iter, parent);
+ gtk_tree_store_set (store, &iter,
+ TEXT_COLUMN, item->value().translation().c_str(), DATA_COLUMN, item, -1);
+
+ addNode (store, &iter, item->firstChild());
+ addNode (store, parent, item->next());
+}
+
+struct YGtkPkgRpmGroupsModel {
+ GtkTreeStore *store;
+ YRpmGroupsTree *tree;
+
+ GtkTreeModel *getModel()
+ { return GTK_TREE_MODEL (store); }
+
+ YGtkPkgRpmGroupsModel()
+ {
+ store = gtk_tree_store_new (TOTAL_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
+ tree = new YRpmGroupsTree();
+
+ zypp::sat::LookupAttr rpmgroups (zypp::sat::SolvAttr::group);
+ for (zypp::sat::LookupAttr::iterator it = rpmgroups.begin();
+ it != rpmgroups.end(); it++)
+ tree->addRpmGroup (it.asString());
+
+ GtkTreeIter iter;
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ TEXT_COLUMN, _("All packages"), DATA_COLUMN, NULL, -1);
+
+ addNode (store, NULL, tree->root()->firstChild());
+ }
+
+ ~YGtkPkgRpmGroupsModel()
+ {
+ delete tree;
+ g_object_unref (G_OBJECT (store));
+ }
+
+ bool writeQuery (Ypp::PoolQuery &query, GtkTreeIter *iter)
+ {
+ gpointer data;
+ gtk_tree_model_get (getModel(), iter, DATA_COLUMN, &data, -1);
+ if (data) {
+ YStringTreeItem *group = (YStringTreeItem *) data;
+ std::string rpm_group (tree->rpmGroup (group));
+ query.addCriteria (new Ypp::RpmGroupMatch (rpm_group));
+ return true;
+ }
+ return false;
+ }
+};
+
+
+struct YGtkPkgRpmGroupsView::Impl {
+ GtkWidget *scroll, *view;
+ YGtkPkgRpmGroupsModel *model;
+
+ Impl (YGtkPkgRpmGroupsModel *model) : model (model) {}
+ ~Impl() { delete model; }
+};
+
+static void selection_changed_cb (GtkTreeSelection *selection, YGtkPkgRpmGroupsView *pThis)
+{
+ if (gtk_tree_selection_get_selected (selection, NULL, NULL))
+ pThis->notify();
+}
+
+YGtkPkgRpmGroupsView::YGtkPkgRpmGroupsView()
+: YGtkPkgQueryWidget(), impl (new Impl (new YGtkPkgRpmGroupsModel()))
+{
+ impl->view = gtk_tree_view_new_with_model (impl->model->getModel());
+
+ GtkTreeView *view = GTK_TREE_VIEW (impl->view);
+ gtk_tree_view_set_headers_visible (view, FALSE);
+ gtk_tree_view_set_search_column (view, TEXT_COLUMN);
+ gtk_tree_view_set_enable_tree_lines (view, TRUE);
+ gtk_tree_view_expand_all (view);
+
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (
+ NULL, renderer, "text", TEXT_COLUMN, NULL);
+ g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_append_column (view, column);
+
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_changed_cb), this);
+ clearSelection();
+
+ impl->scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (impl->scroll),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (impl->scroll), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (impl->scroll), impl->view);
+ gtk_widget_show_all (impl->scroll);
+}
+
+YGtkPkgRpmGroupsView::~YGtkPkgRpmGroupsView()
+{ delete impl; }
+
+GtkWidget *YGtkPkgRpmGroupsView::getWidget()
+{ return impl->scroll; }
+
+void YGtkPkgRpmGroupsView::clearSelection()
+{
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb, this);
+ {
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter_first (impl->model->getModel(), &iter);
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+ g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb, this);
+}
+
+bool YGtkPkgRpmGroupsView::writeQuery (Ypp::PoolQuery &query)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->view));
+ if (gtk_tree_selection_get_selected (selection, &model, &iter))
+ return impl->model->writeQuery (query, &iter);
+ else {
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ g_signal_handlers_block_by_func (selection, (gpointer) selection_changed_cb, this);
+ gtk_tree_selection_select_iter (selection, &iter);
+ g_signal_handlers_unblock_by_func (selection, (gpointer) selection_changed_cb, this);
+ }
+ }
+ return false;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgrpmgroupsview.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,31 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Good-old RPM-groups tree-view.
+*/
+
+#ifndef YGTK_PKG_RPM_GROUP_VIEW_H
+#define YGTK_PKG_RPM_GROUP_VIEW_H
+
+#include "ygtkpkgquerywidget.h"
+#include
+
+struct YGtkPkgRpmGroupsView : public YGtkPkgQueryWidget
+{
+ YGtkPkgRpmGroupsView();
+ virtual ~YGtkPkgRpmGroupsView();
+ virtual GtkWidget *getWidget();
+
+ virtual bool begsUpdate() { return false; }
+ virtual void updateList (Ypp::List list) {}
+
+ virtual void clearSelection();
+ virtual bool writeQuery (Ypp::PoolQuery &query);
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,310 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgSearchEntry, zypp query string attributes */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGUtils.h"
+#include "ygtkpkgsearchentry.h"
+#include "YGPackageSelector.h"
+#include
+
+struct YGtkPkgSearchEntry::Impl {
+ GtkWidget *box, *entry, *combo;
+};
+
+static void entry_icons_sync (GtkWidget *widget)
+{
+ static GdkColor yellow = { 0, 0xf7f7, 0xf7f7, 0xbdbd };
+ static GdkColor black = { 0, 0, 0, 0 };
+
+ GtkEntry *entry = GTK_ENTRY (widget); // show clear icon if text
+ const gchar *name = gtk_entry_get_text (entry);
+ bool showIcon = *name;
+ if (showIcon != gtk_entry_get_icon_activatable (entry, GTK_ENTRY_ICON_SECONDARY)) {
+ gtk_entry_set_icon_activatable (entry,
+ GTK_ENTRY_ICON_SECONDARY, showIcon);
+ gtk_entry_set_icon_from_stock (entry,
+ GTK_ENTRY_ICON_SECONDARY, showIcon ? GTK_STOCK_CLEAR : NULL);
+
+ if (showIcon) {
+ gtk_entry_set_icon_tooltip_text (entry,
+ GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+ gtk_widget_modify_base (widget, GTK_STATE_NORMAL, &yellow);
+ gtk_widget_modify_text (widget, GTK_STATE_NORMAL, &black);
+ }
+ else { // revert
+ gtk_widget_modify_base (widget, GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_text (widget, GTK_STATE_NORMAL, NULL);
+ }
+ }
+}
+
+static void entry_changed_cb (GtkEditable *editable, YGtkPkgSearchEntry *pThis)
+{
+ int item = gtk_combo_box_get_active (GTK_COMBO_BOX (pThis->impl->combo));
+ pThis->notifyDelay (item == 0 ? 150 : 500);
+ entry_icons_sync (GTK_WIDGET (editable));
+}
+
+static void combo_changed_cb (GtkComboBox *combo, YGtkPkgSearchEntry *pThis)
+{
+ const gchar *name = gtk_entry_get_text (GTK_ENTRY (pThis->impl->entry));
+ if (*name) // unless entry has text, no need to refresh query
+ pThis->notify();
+ gtk_editable_select_region (GTK_EDITABLE (pThis->impl->entry), 0, -1);
+ gtk_widget_grab_focus (pThis->impl->entry);
+}
+
+static void icon_press_cb (GtkEntry *entry, GtkEntryIconPosition pos,
+ GdkEvent *event, YGtkPkgSearchEntry *pThis)
+{
+ if (pos == GTK_ENTRY_ICON_PRIMARY)
+ gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+ else
+ gtk_entry_set_text (entry, "");
+ gtk_widget_grab_focus (GTK_WIDGET (entry));
+}
+
+static void activate_cb (GtkEntry *entry, GtkWidget *widget)
+{ gtk_widget_grab_focus (widget); }
+
+YGtkPkgSearchEntry::YGtkPkgSearchEntry()
+: YGtkPkgQueryWidget(), impl (new Impl())
+{
+ impl->entry = gtk_entry_new();
+ gtk_widget_set_size_request (impl->entry, 180, -1);
+ g_signal_connect (G_OBJECT (impl->entry), "realize", // grab focus at start
+ G_CALLBACK (gtk_widget_grab_focus), NULL);
+ g_signal_connect (G_OBJECT (impl->entry), "changed",
+ G_CALLBACK (entry_changed_cb), this);
+ g_signal_connect (G_OBJECT (impl->entry), "icon-press",
+ G_CALLBACK (icon_press_cb), this);
+ gtk_widget_set_tooltip_markup (impl->entry,
+ _("<b>Package search:</b> Use spaces to separate your keywords.\n"
+ "(usage example: a name search for \"yast dhcp\" would match yast dhcpd tool)"));
+
+ gtk_entry_set_icon_from_stock (GTK_ENTRY (impl->entry),
+ GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_FIND);
+ gtk_entry_set_icon_activatable (GTK_ENTRY (impl->entry), GTK_ENTRY_ICON_PRIMARY, TRUE);
+
+ std::string label_str (YGUtils::mapKBAccel (_("&Find:")));
+ GtkWidget *label = gtk_label_new_with_mnemonic (label_str.c_str());
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->entry);
+
+ impl->combo = gtk_combo_box_new_text();
+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->combo), _("Name & Summary"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->combo), _("Description"));
+ if (!YGPackageSelector::get()->onlineUpdateMode()) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->combo), _("File name"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->combo), "RPM Provides");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->combo), "RPM Requires");
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (impl->combo), 0);
+ YGUtils::shrinkWidget (impl->combo);
+ g_signal_connect (G_OBJECT (impl->combo), "changed",
+ G_CALLBACK (combo_changed_cb), this);
+ gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (impl->combo),
+ YGUtils::empty_row_is_separator_cb, GINT_TO_POINTER (0), NULL);
+
+ impl->box = gtk_hbox_new (FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (impl->box), label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (impl->box), impl->entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (impl->box), gtk_label_new (_("by")), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (impl->box), impl->combo, TRUE, TRUE, 0);
+ gtk_widget_show_all (impl->box);
+}
+
+YGtkPkgSearchEntry::~YGtkPkgSearchEntry()
+{ delete impl; }
+
+GtkWidget *YGtkPkgSearchEntry::getWidget()
+{ return impl->box; }
+
+void YGtkPkgSearchEntry::clearSelection()
+{ setText (Ypp::PoolQuery::NAME, ""); }
+
+bool YGtkPkgSearchEntry::writeQuery (Ypp::PoolQuery &query)
+{
+ const gchar *text = gtk_entry_get_text (GTK_ENTRY (impl->entry));
+ if (*text) {
+ int item = gtk_combo_box_get_active (GTK_COMBO_BOX (impl->combo));
+ if (item >= 0 && item <= 1) {
+ int attrbs;
+ switch (item) {
+ case 0: // name & summary
+ attrbs = Ypp::StrMatch::NAME | Ypp::StrMatch::SUMMARY;
+ break;
+ case 1: // description
+ attrbs = Ypp::StrMatch::DESCRIPTION;
+ break;
+ }
+
+ Ypp::StrMatch *match = new Ypp::StrMatch (attrbs);
+ const gchar delimiter[2] = { ' ', '\0' };
+ gchar **keywords = g_strsplit (text, delimiter, -1);
+ for (gchar **i = keywords; *i; i++)
+ match->add (*i);
+ g_strfreev (keywords);
+
+ query.addCriteria (match);
+ }
+ else {
+ query.setStringMode (false, Ypp::PoolQuery::CONTAINS);
+
+ switch (item) {
+ case 2: // filelist
+ query.addStringAttribute (Ypp::PoolQuery::PROVIDES);
+ query.addStringAttribute (Ypp::PoolQuery::FILELIST);
+ break;
+ case 3: // provides
+ query.addStringAttribute (Ypp::PoolQuery::PROVIDES);
+ break;
+ case 4: // requires
+ query.addStringAttribute (Ypp::PoolQuery::REQUIRES);
+ break;
+ }
+
+ query.addStringOr (text);
+ }
+ return true;
+ }
+ return false;
+}
+
+static gboolean patterns_link_cb (GtkLabel *label, gchar *uri, YGtkPkgSearchEntry *pThis)
+{ YGPackageSelector::get()->showFilterWidget (uri); return TRUE; }
+
+static bool any_pattern_contains (const char *name)
+{
+ if (strstr (name, " ")) return false;
+
+ // roll on some criteria to find whole-word match (the zypp one doesnt cut it)
+ struct WholeWordMatch : public Ypp::Match {
+ WholeWordMatch (const char *word)
+ : word (word), len (strlen (word)) {}
+
+ virtual bool match (Ypp::Selectable &sel) {
+ std::string name (sel.name());
+ const char *i = name.c_str();
+ while ((i = strcasestr (i, word))) {
+ bool starts = (i == word) || (i[-1] != ' ');
+ bool ends = (i[len+1] == '\0') || (i[len+1] != ' ');
+ if (starts && ends)
+ return true;
+ i += len;
+ }
+ return false;
+ }
+ private: const char *word; int len;
+ };
+
+ Ypp::PoolQuery query (Ypp::Selectable::PATTERN);
+ query.addCriteria (new WholeWordMatch (name));
+ //query.addStringOr (name);
+ return query.hasNext();
+}
+
+GtkWidget *YGtkPkgSearchEntry::createToolbox()
+{
+ const gchar *text = gtk_entry_get_text (GTK_ENTRY (impl->entry));
+ int item = gtk_combo_box_get_active (GTK_COMBO_BOX (impl->combo));
+ if (*text)
+ switch (item) {
+ case 0:
+ if (any_pattern_contains (text)) {
+ char *_text = g_strdup_printf (_("%sPatterns are available%s"
+ " that correspond to your search criteria."),
+ "", "</a>");
+ GtkWidget *label = gtk_label_new (_text);
+ g_free (_text);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
+ g_signal_connect (G_OBJECT (label), "activate-link",
+ G_CALLBACK (patterns_link_cb), this);
+ GtkWidget *icon = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_BUTTON);
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ return hbox;
+ }
+ break;
+ case 2: {
+ GtkWidget *label = gtk_label_new (
+ _("Search by file name only reliable for installed packages."));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
+ GtkWidget *icon = gtk_image_new_from_stock (
+ GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_BUTTON);
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+ return hbox;
+ }
+ }
+ return NULL;
+}
+
+void YGtkPkgSearchEntry::setText (Ypp::PoolQuery::StringAttribute attrb, const std::string &text)
+{
+ int index = 0;
+ switch (attrb) {
+ case Ypp::PoolQuery::NAME: case Ypp::PoolQuery::SUMMARY: break;
+ case Ypp::PoolQuery::DESCRIPTION: index = 1; break;
+ case Ypp::PoolQuery::FILELIST: index = 2; break;
+ case Ypp::PoolQuery::PROVIDES: index = 3; break;
+ case Ypp::PoolQuery::REQUIRES: index = 4; break;
+ }
+
+ g_signal_handlers_block_by_func (impl->entry, (gpointer) entry_changed_cb, this);
+ g_signal_handlers_block_by_func (impl->combo, (gpointer) combo_changed_cb, this);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (impl->combo), index);
+ gtk_entry_set_text (GTK_ENTRY (impl->entry), text.c_str());
+ entry_icons_sync (impl->entry);
+ g_signal_handlers_unblock_by_func (impl->entry, (gpointer) entry_changed_cb, this);
+ g_signal_handlers_unblock_by_func (impl->combo, (gpointer) combo_changed_cb, this);
+}
+
+void YGtkPkgSearchEntry::setActivateWidget (GtkWidget *widget)
+{
+ g_signal_connect (G_OBJECT (impl->entry), "activate",
+ G_CALLBACK (activate_cb), widget);
+}
+
+Ypp::PoolQuery::StringAttribute YGtkPkgSearchEntry::getAttribute()
+{
+ int item = gtk_combo_box_get_active (GTK_COMBO_BOX (impl->combo));
+ switch (item) {
+ case 0: return Ypp::PoolQuery::NAME; break;
+ case 1: return Ypp::PoolQuery::DESCRIPTION; break;
+ case 2: return Ypp::PoolQuery::FILELIST; break;
+ case 3: return Ypp::PoolQuery::PROVIDES; break;
+ case 4: return Ypp::PoolQuery::REQUIRES; break;
+ }
+ return (Ypp::PoolQuery::StringAttribute) 0;
+}
+
+std::list std::string YGtkPkgSearchEntry::getText()
+{
+ std::list std::string keywords;
+ const char *text = gtk_entry_get_text (GTK_ENTRY (impl->entry));
+ const gchar delimiter[2] = { ' ', '\0' };
+ gchar **_keywords = g_strsplit (text, delimiter, -1);
+ for (gchar **i = _keywords; *i; i++)
+ if (**i)
+ keywords.push_back (*i);
+ g_strfreev (_keywords);
+ return keywords;
+}
+
+std::string YGtkPkgSearchEntry::getTextStr()
+{ return gtk_entry_get_text (GTK_ENTRY (impl->entry)); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgsearchentry.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,41 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Zypp search query interface..
+*/
+
+#ifndef YGTK_PKG_SEARCH_ENTRY_H
+#define YGTK_PKG_SEARCH_ENTRY_H
+
+#include "ygtkpkgquerywidget.h"
+#include "ygtkpkglistview.h"
+
+struct YGtkPkgSearchEntry : public YGtkPkgQueryWidget
+{
+ YGtkPkgSearchEntry();
+ virtual ~YGtkPkgSearchEntry();
+
+ virtual GtkWidget *getWidget();
+
+ virtual bool begsUpdate() { return false; }
+ virtual void updateList (Ypp::List list) {}
+
+ virtual void clearSelection();
+ virtual bool writeQuery (Ypp::PoolQuery &query);
+
+ virtual GtkWidget *createToolbox();
+
+ void setText (Ypp::PoolQuery::StringAttribute attribute, const std::string &text);
+ void setActivateWidget (GtkWidget *widget);
+
+ Ypp::PoolQuery::StringAttribute getAttribute();
+ std::list std::string getText();
+ std::string getTextStr();
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,309 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgStatusBar, a status-bar */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGUI.h"
+#include "ygtkpkgstatusbar.h"
+#include "YGPackageSelector.h"
+#include "YGUtils.h"
+#include "ygtkpkglistview.h"
+#include "ygtkpkgundolist.h"
+#include "yzyppwrapper.h"
+#include
+
+static void enlarge_width_size_request_cb (GtkWidget *widget, GtkRequisition *req)
+{ req->width += 4; }
+
+struct LastChange {
+ GtkWidget *hbox, *icon, *text, *undo_button;
+
+ GtkWidget *getWidget() { return hbox; }
+
+ LastChange()
+ {
+ icon = gtk_image_new();
+ gtk_widget_set_size_request (icon, 16, 16);
+
+ text = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (text), 0, .5);
+ undo_button = gtk_button_new_from_stock (GTK_STOCK_UNDO);
+ YGUtils::shrinkWidget (undo_button);
+ g_signal_connect (G_OBJECT (undo_button), "size-request",
+ G_CALLBACK (enlarge_width_size_request_cb), NULL);
+ g_signal_connect (G_OBJECT (undo_button), "clicked",
+ G_CALLBACK (undo_clicked_cb), this);
+ gchar *str = g_strdup_printf ("(%s</a>)", _("view all changes"));
+ GtkWidget *more = gtk_label_new (str);
+ g_free (str);
+ gtk_label_set_use_markup (GTK_LABEL (more), TRUE);
+ gtk_label_set_track_visited_links (GTK_LABEL (more), FALSE);
+ g_signal_connect (G_OBJECT (more), "activate-link",
+ G_CALLBACK (more_link_cb), this);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), text, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), undo_button, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), more, FALSE, TRUE, 0);
+ }
+
+ void undoChanged (YGtkPkgUndoList *list)
+ {
+ int auto_count;
+ Ypp::Selectable *sel = list->front (&auto_count);
+ if (sel) {
+ const char *stock = getStatusStockIcon (*sel);
+ GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
+ stock, 16, GtkIconLookupFlags (0), NULL);
+ //GdkPixbuf *_pixbuf = YGUtils::setGray (pixbuf);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (icon), pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+
+ const char *action = getStatusAction (sel);
+ gchar *str;
+ if (sel->toModifyAuto())
+ str = g_strdup_printf (_("<b>%s</b> %d preselected packages"), action, auto_count);
+ else {
+ if (auto_count == 0)
+ str = g_strdup_printf ("<b>%s</b> %s", action, sel->name().c_str());
+ else {
+ char *deps;
+ if (auto_count == 1)
+ deps = g_strdup (_("plus 1 dependency"));
+ else
+ deps = g_strdup_printf (_("plus %d dependencies"), auto_count);
+ str = g_strdup_printf ("<b>%s</b> %s, %s", action, sel->name().c_str(), deps);
+ g_free (deps);
+ }
+ }
+
+ gtk_label_set_markup (GTK_LABEL (text), str);
+ gtk_label_set_attributes (GTK_LABEL (text), NULL);
+ gtk_widget_set_sensitive (undo_button, TRUE);
+ g_free (str);
+ }
+ else {
+ gtk_image_clear (GTK_IMAGE (icon));
+ gtk_label_set_text (GTK_LABEL (text), _("No changes to perform"));
+
+ PangoAttrList *attrs = pango_attr_list_new();
+ pango_attr_list_insert (attrs, pango_attr_foreground_new (110<<8, 110<<8, 110<<8));
+ pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_ITALIC));
+ gtk_label_set_attributes (GTK_LABEL (text), attrs);
+ pango_attr_list_unref (attrs);
+
+ gtk_widget_set_sensitive (undo_button, FALSE);
+ }
+ set_ellipsize (text);
+ }
+
+ static gboolean more_link_cb (GtkLabel *label, gchar *uri, LastChange *pThis)
+ { YGPackageSelector::get()->popupChanges(); return TRUE; }
+
+ static void undo_clicked_cb (GtkButton *button, LastChange *pThis)
+ {
+ Ypp::Selectable *sel = YGPackageSelector::get()->undoList()->front (NULL);
+ if (sel) sel->undo();
+ }
+
+ void set_ellipsize (GtkWidget *label)
+ {
+ GtkWidget *hbox = gtk_widget_get_parent (this->hbox);
+ if (GTK_WIDGET_REALIZED (hbox)) {
+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
+
+ GtkRequisition req;
+ gtk_widget_size_request (hbox, &req);
+ GtkWidget *window = gtk_widget_get_toplevel (hbox);
+ bool ellipsize = req.width > window->allocation.width - 10;
+
+ PangoEllipsizeMode mode = ellipsize ? PANGO_ELLIPSIZE_MIDDLE : PANGO_ELLIPSIZE_NONE;
+ gtk_label_set_ellipsize (GTK_LABEL (label), mode);
+ gtk_box_set_child_packing (GTK_BOX (this->hbox), label, ellipsize, TRUE, 0, GTK_PACK_START);
+ }
+ }
+};
+
+#if 0
+struct StatChange {
+ GtkWidget *hbox, *to_install, *to_upgrade, *to_remove;
+
+ GtkWidget *getWidget() { return hbox; }
+
+ StatChange()
+ {
+ to_install = gtk_label_new ("");
+ gtk_label_set_selectable (GTK_LABEL (to_install), TRUE);
+ to_upgrade = gtk_label_new ("");
+ gtk_label_set_selectable (GTK_LABEL (to_upgrade), TRUE);
+ to_remove = gtk_label_new ("");
+ gtk_label_set_selectable (GTK_LABEL (to_remove), TRUE);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("To install:")), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), to_install, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_vseparator_new(), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("To upgrade:")), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), to_upgrade, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_vseparator_new(), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("To remove:")), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), to_remove, FALSE, TRUE, 0);
+ }
+
+ void undoChanged (YGtkPkgUndoList *undo)
+ {
+ int toInstall = 0, toUpgrade = 0, toRemove = 0;
+ Ypp::List list (undo->getList());
+ for (int i = 0; i < list.size(); i++) {
+ Ypp::Selectable &sel = list.get (i);
+ if (sel.toInstall()) {
+ if (sel.isInstalled())
+ toUpgrade++;
+ else
+ toInstall++;
+ }
+ else if (sel.toRemove())
+ toInstall++;
+ }
+
+ label_set_int (to_install, toInstall);
+ label_set_int (to_upgrade, toUpgrade);
+ label_set_int (to_remove, toRemove);
+ }
+
+ static void label_set_int (GtkWidget *label, int value)
+ {
+ gchar *str = g_strdup_printf ("%d", value);
+ gtk_label_set_text (GTK_LABEL (label), str);
+ g_free (str);
+ }
+};
+#endif
+
+#define MIN_FREE_MB_WARN 400
+#define MIN_PERCENT_WARN 90
+
+struct DiskChange {
+ GtkWidget *hbox, *combo, *text;
+
+ GtkWidget *getWidget() { return hbox; }
+
+ DiskChange()
+ {
+ GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
+ std::vector std::string partitions = Ypp::getPartitionList();
+ int active = -1;
+ for (unsigned int i = 0; i < partitions.size(); i++) {
+ const std::string &part = partitions[i];
+ if (part == "/usr" || part == "/usr/")
+ active = i;
+ else if (active == -1 && part == "/")
+ active = i;
+
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, part.c_str(), -1);
+ }
+
+ combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (G_OBJECT (store));
+ YGUtils::shrinkWidget (combo);
+ gtk_widget_set_name (combo, "small-widget");
+ gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (combo), FALSE);
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer, "text", 0, NULL);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), active);
+ g_signal_connect (G_OBJECT (combo), "changed",
+ G_CALLBACK (combo_changed_cb), this);
+
+ text = gtk_label_new ("");
+ YGUtils::setWidgetFont (text, PANGO_STYLE_ITALIC,
+ PANGO_WEIGHT_NORMAL, PANGO_SCALE_MEDIUM);
+ gtk_label_set_selectable (GTK_LABEL (text), TRUE);
+
+ hbox = gtk_hbox_new (FALSE, 4);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Space available:")), FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), text, FALSE, TRUE, 0);
+ }
+
+ void undoChanged (YGtkPkgUndoList *undo)
+ {
+ GtkTreeIter iter;
+ gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);
+ GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+ gchar *mount_point;
+ gtk_tree_model_get (model, &iter, 0, &mount_point, -1);
+ const ZyppDu part = Ypp::getPartition (mount_point);
+ g_free (mount_point);
+
+ int percent = part.total_size ? ((100 * part.pkg_size) / part.total_size) : 0;
+ long long free = (part.total_size - part.pkg_size) * 1024 * 1024;
+
+ const char *format = "%s";
+ if (percent > MIN_PERCENT_WARN && free < MIN_FREE_MB_WARN)
+ format = "<b><b>%s<b></span></b>";
+ char *str = g_strdup_printf (format, part.freeAfterCommit().asString().c_str());
+ gtk_label_set_markup (GTK_LABEL (text), str);
+ g_free (str);
+ }
+
+ static void combo_changed_cb (GtkComboBox *combo, DiskChange *pThis)
+ { pThis->undoChanged (YGPackageSelector::get()->undoList()); }
+};
+
+struct YGtkPkgStatusBar::Impl : public YGtkPkgUndoList::Listener {
+ GtkWidget *box;
+ LastChange *last;
+ DiskChange *disk;
+
+ GtkWidget *getWidget() { return box; }
+
+ Impl (YGtkPkgUndoList *undo)
+ {
+ last = new LastChange();
+ disk = new DiskChange();
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), last->getWidget(), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), disk->getWidget(), FALSE, TRUE, 0);
+ box = hbox;
+ gtk_widget_show_all (box);
+
+ undoChanged (undo);
+ undo->addListener (this);
+ }
+
+ ~Impl()
+ {
+ delete last;
+ delete disk;
+ YGPackageSelector::get()->undoList()->removeListener (this);
+ }
+
+ virtual void undoChanged (YGtkPkgUndoList *list)
+ {
+ last->undoChanged (list);
+ disk->undoChanged (list);
+ }
+};
+
+YGtkPkgStatusBar::YGtkPkgStatusBar (YGtkPkgUndoList *undo)
+: impl (new Impl (undo))
+{}
+
+YGtkPkgStatusBar::~YGtkPkgStatusBar()
+{ delete impl; }
+
+GtkWidget *YGtkPkgStatusBar::getWidget()
+{ return impl->getWidget(); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgstatusbar.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,27 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Status bar, showing the changes to apply.
+*/
+
+#ifndef YGTK_PKG_STATUS_BAR_H
+#define YGTK_PKG_STATUS_BAR_H
+
+#include
+
+struct YGtkPkgUndoList;
+
+struct YGtkPkgStatusBar
+{
+ YGtkPkgStatusBar (YGtkPkgUndoList *undo);
+ ~YGtkPkgStatusBar();
+
+ GtkWidget *getWidget();
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,318 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgUndoList, list of changes */
+// check the header file for information about this utility
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGDialog.h"
+#include "YGUtils.h"
+#include "ygtkpkgundolist.h"
+#include
+
+struct YGtkPkgUndoList::Impl : public Ypp::SelListener
+{
+ YGtkPkgUndoList *parent;
+ Ypp::List changes;
+ std::list listeners;
+
+ Impl (YGtkPkgUndoList *parent) : parent (parent), changes (0)
+ { Ypp::addSelListener (this); }
+
+ ~Impl()
+ { Ypp::removeSelListener (this); }
+
+ virtual void selectableModified()
+ {
+ // remove any previously changed selectable now undone
+ Ypp::List _changes (changes.size());
+ for (int i = 0; i < changes.size(); i++) {
+ Ypp::Selectable &sel = changes.get(i);
+ if (sel.toModify())
+ _changes.append (sel);
+ }
+ changes = _changes;
+
+ // check for any new changed selectable
+ // first, check for user-modified, then for auto ones, to keep them ordered
+ for (int step = 0; step < 2; step++) {
+ Ypp::PoolQuery query (Ypp::Selectable::ALL);
+ query.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::TO_MODIFY));
+ while (query.hasNext()) {
+ Ypp::Selectable sel = query.next();
+ if ((step == 0 && sel.toModifyAuto()) || (step == 1 && !sel.toModifyAuto()))
+ continue;
+ if (changes.find (sel) == -1)
+ changes.append (sel);
+ }
+ }
+
+ for (std::list ::iterator it = listeners.begin();
+ it != listeners.end(); it++)
+ (*it)->undoChanged (parent);
+ }
+};
+
+YGtkPkgUndoList::YGtkPkgUndoList()
+: impl (new Impl (this)) {}
+
+YGtkPkgUndoList::~YGtkPkgUndoList()
+{ delete impl; }
+
+Ypp::Selectable *YGtkPkgUndoList::front (int *autoCount)
+{
+ Ypp::Selectable *sel = 0;
+ if (autoCount)
+ *autoCount = 0;
+ for (int i = impl->changes.size()-1; i >= 0; i--) {
+ sel = &impl->changes.get (i);
+ if (sel->toModifyAuto()) {
+ if (autoCount) (*autoCount)++;
+ }
+ else
+ break;
+ }
+ return sel;
+}
+
+Ypp::List YGtkPkgUndoList::getList()
+{ return impl->changes; }
+
+void YGtkPkgUndoList::addListener (Listener *listener)
+{ impl->listeners.push_back (listener); }
+
+void YGtkPkgUndoList::removeListener (Listener *listener)
+{ impl->listeners.remove (listener); }
+
+#include "YGPackageSelector.h"
+#include "ygtkpkglistview.h"
+
+struct ChangeSizeInfo : public YGtkPkgUndoList::Listener {
+ GtkWidget *vbox, *disk_label, *download_label, *warn_label;
+
+ GtkWidget *getWidget()
+ { return vbox; }
+
+ ChangeSizeInfo()
+ {
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ GtkWidget *line;
+ line = createSizeWidget (_("Disk space required:"), &disk_label);
+ gtk_box_pack_start (GTK_BOX (hbox), line, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new ("/"), FALSE, TRUE, 0);
+ line = createSizeWidget (_("Download size:"), &download_label);
+ gtk_box_pack_start (GTK_BOX (hbox), line, FALSE, TRUE, 0);
+ gtk_widget_show_all (hbox);
+
+ warn_label = gtk_label_new ("");
+ gtk_misc_set_alignment (GTK_MISC (warn_label), 0, .5);
+ gtk_label_set_selectable (GTK_LABEL (warn_label), TRUE);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), warn_label, FALSE, TRUE, 0);
+ gtk_widget_show (vbox);
+
+ undoChanged (YGPackageSelector::get()->undoList());
+ YGPackageSelector::get()->undoList()->addListener (this);
+ }
+
+ ~ChangeSizeInfo()
+ { YGPackageSelector::get()->undoList()->removeListener (this); }
+
+ virtual void undoChanged (YGtkPkgUndoList *undo)
+ {
+ Size_t disk, download;
+ Ypp::List list = undo->getList();
+ for (int i = 0; i < list.size(); i++) {
+ Ypp::Selectable sel = list.get (i);
+ if (sel.toInstall()) {
+ Ypp::Version candidate = sel.candidate();
+ download += candidate.downloadSize();
+ if (sel.isInstalled())
+ disk += candidate.size() - sel.installed().size();
+ else
+ disk += candidate.size();
+ }
+ else if (sel.toRemove())
+ disk -= sel.installed().size();
+ }
+
+ gtk_label_set_text (GTK_LABEL (disk_label), disk.asString().c_str());
+ gtk_label_set_text (GTK_LABEL (download_label), download.asString().c_str());
+
+ gtk_widget_hide (warn_label);
+ ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
+ for (ZyppDuSet::iterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
+ const ZyppDu &point = *it;
+ if (!point.readonly && point.freeAfterCommit() < 0) {
+ // Translators: please keep the %s order intact. They refer to mount_point, needed_space
+ char *over = g_strdup_printf (_("Partition %s is %s over-capacity"),
+ point.dir.c_str(), point.freeAfterCommit().asString().c_str());
+ // Translators: please keep the %s order intact. They refer to used_space, total_space
+ char *fill = g_strdup_printf (_("%s filled out of %s"),
+ point.usedAfterCommit().asString().c_str(),
+ point.totalSize().asString().c_str());
+ char *markup = g_strdup_printf (
+ "<b>%s (%s)</span></b>", over, fill);
+ gtk_label_set_markup (GTK_LABEL (warn_label), markup);
+ g_free (over); g_free (fill); g_free (markup);
+ gtk_widget_show (warn_label);
+ break;
+ }
+ }
+ }
+
+ static GtkWidget *createSizeWidget (const char *label, GtkWidget **widget)
+ {
+ *widget = gtk_label_new ("");
+ YGUtils::setWidgetFont (*widget, PANGO_STYLE_ITALIC,
+ PANGO_WEIGHT_NORMAL, PANGO_SCALE_MEDIUM);
+ gtk_misc_set_alignment (GTK_MISC (*widget), 1, .5);
+ gtk_label_set_selectable (GTK_LABEL (*widget), TRUE);
+
+ GtkWidget *title = gtk_label_new (label);
+ gtk_misc_set_alignment (GTK_MISC (title), 0, .5);
+
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), title, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), *widget, TRUE, TRUE, 0);
+ return hbox;
+ }
+};
+
+#define YAST_SYSCONFIG "/etc/sysconfig/yast2"
+#include
+
+enum { CLOSE_MODE, RESTART_MODE, SUMMARY_MODE };
+
+static int read_PKGMGR_ACTION_AT_EXIT()
+{ // from yast2-ncurses, NCPackageSelector.cc
+ std::map sysconfig =
+ zypp::base::sysconfig::read (YAST_SYSCONFIG);
+ std::map ::const_iterator it =
+ sysconfig.find("PKGMGR_ACTION_AT_EXIT");
+ if (it != sysconfig.end()) {
+ yuiMilestone() << "Read sysconfig's action at pkg mgr exit value: " << it->second << endl;
+ std::string mode (it->second);
+ if (mode == "restart")
+ return RESTART_MODE;
+ else if (mode == "summary")
+ return SUMMARY_MODE;
+ else //if (mode == "close")
+ return CLOSE_MODE;
+ }
+ yuiMilestone() << "Could not read PKGMGR_ACTION_AT_EXIT variable from sysconfig" << endl;
+ return false;
+}
+
+static void write_PKGMGR_ACTION_AT_EXIT (int mode)
+{ // from yast2-ncurses, NCPackageSelector.cc
+ // this is really, really stupid. But we have no other iface for writing sysconfig so far
+ std::string _mode;
+ switch (mode) {
+ case CLOSE_MODE: _mode = "close"; break;
+ case RESTART_MODE: _mode = "restart"; break;
+ case SUMMARY_MODE: _mode = "summary"; break;
+ }
+ int ret = -1;
+ string cmd = "sed -i 's/^[ \t]*PKGMGR_ACTION_AT_EXIT.*$/PKGMGR_ACTION_AT_EXIT=\"" +
+ _mode + "\"/' " + YAST_SYSCONFIG;
+ ret = system(cmd.c_str());
+ yuiMilestone() << "Executing system cmd " << cmd << " returned " << ret << endl;
+}
+
+static void close_when_done_toggled_cb (GtkToggleButton *button)
+{
+ gtk_toggle_button_set_inconsistent (button, FALSE);
+ int mode = gtk_toggle_button_get_active (button) ? CLOSE_MODE : RESTART_MODE;
+ write_PKGMGR_ACTION_AT_EXIT (mode);
+}
+
+static GtkWidget *create_close_when_done_check()
+{
+ GtkWidget *check_box = gtk_check_button_new_with_label (_("Close software manager when done"));
+ int mode = read_PKGMGR_ACTION_AT_EXIT();
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_box), mode == CLOSE_MODE);
+ gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (check_box), mode == SUMMARY_MODE);
+ if (access (YAST_SYSCONFIG, W_OK) != 0) {
+ gtk_widget_set_sensitive (check_box, FALSE);
+ gtk_widget_set_tooltip_text (check_box, "Cannot write to " YAST_SYSCONFIG);
+ }
+ g_signal_connect_after (G_OBJECT (check_box), "toggled",
+ G_CALLBACK (close_when_done_toggled_cb), NULL);
+ gtk_widget_show (check_box);
+ return check_box;
+}
+
+struct YGtkPkgUndoView : public YGtkPkgListView, YGtkPkgUndoList::Listener
+{
+ YGtkPkgUndoView()
+ : YGtkPkgListView (true, -1, true, false, true)
+ {
+ addImageColumn (NULL, STATUS_ICON_PROP, true);
+ addTextColumn (_("Name"), ACTION_NAME_PROP, true, -1);
+ addTextColumn (_("Version"), SINGLE_VERSION_PROP, true, 125);
+ addButtonColumn (_("Revert?"), UNDO_BUTTON_PROP);
+
+ undoChanged (YGPackageSelector::get()->undoList());
+ YGPackageSelector::get()->undoList()->addListener (this);
+ }
+
+ ~YGtkPkgUndoView()
+ { YGPackageSelector::get()->undoList()->removeListener (this); }
+
+ virtual void undoChanged (YGtkPkgUndoList *undo)
+ { setList (undo->getList()); }
+};
+
+#include "ygtkpkghistorydialog.h"
+
+bool YGtkPkgUndoList::popupDialog (bool onApply)
+{
+ GtkMessageType type = onApply ? GTK_MESSAGE_QUESTION : GTK_MESSAGE_OTHER;
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GtkDialogFlags (0), type, GTK_BUTTONS_NONE, _("Summary of changes"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("Review the changes to perform."));
+ if (onApply)
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
+ GTK_STOCK_APPLY, GTK_RESPONSE_YES, NULL);
+ else {
+ GtkWidget *image = gtk_image_new_from_stock (GTK_STOCK_UNDO, GTK_ICON_SIZE_DIALOG);
+ gtk_widget_show (image);
+ gtk_message_dialog_set_image (GTK_MESSAGE_DIALOG (dialog), image);
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("See History"), 1,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_YES, NULL);
+
+ // work-around for GTK bug: when you set a custom icon, it is packed as expanded
+ GtkWidget *hbox = gtk_widget_get_parent (image);
+ gtk_box_set_child_packing (GTK_BOX (hbox), image, FALSE, TRUE, 0, GTK_PACK_START);
+ }
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 500);
+
+ YGtkPkgUndoView view;
+ ChangeSizeInfo change_size;
+
+ GtkWidget *vbox = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), view.getWidget(), TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), change_size.getWidget(), FALSE, TRUE, 0);
+ if (onApply)
+ gtk_box_pack_start (GTK_BOX (vbox), create_close_when_done_check(), FALSE, TRUE, 0);
+ gtk_widget_show (vbox);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
+
+ int ret = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (ret == 1)
+ YGPackageSelector::get()->showHistoryDialog();
+ gtk_widget_destroy (dialog);
+ return ret == GTK_RESPONSE_YES;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgundolist.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,35 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* A Ypp::List that stores only
+*/
+
+#ifndef YGTK_PKG_UNDO_LIST_H
+#define YGTK_PKG_UNDO_LIST_H
+
+#include "yzyppwrapper.h"
+
+struct YGtkPkgUndoList
+{
+ YGtkPkgUndoList();
+ ~YGtkPkgUndoList();
+
+ Ypp::Selectable *front (int *autoCount);
+ Ypp::List getList();
+
+ struct Listener {
+ virtual void undoChanged (YGtkPkgUndoList *list) = 0;
+ };
+
+ void addListener (Listener *listener);
+ void removeListener (Listener *listener);
+
+ bool popupDialog (bool onApply);
+
+ struct Impl;
+ Impl *impl;
+};
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,248 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* YGtkPkgVestigialDialog, dialog */
+// check the header file for information about this widget
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#include "config.h"
+#include "YGDialog.h"
+#include "ygtkpkgvestigialdialog.h"
+#include "ygtkpkglistview.h"
+#include "YGPackageSelector.h"
+#include "yzyppwrapper.h"
+#include
+
+#include
+#define FILENAME "/var/log/zypp/history"
+
+struct ZyppVestigialParser
+{
+ std::set std::string m_dependencies;
+
+ ZyppVestigialParser()
+ {
+ zypp::parser::HistoryLogReader parser (FILENAME, boost::ref (*this));
+ try {
+ parser.readAll();
+ }
+ catch (const zypp::Exception &ex) {
+ yuiWarning () << "Error: Could not load log file" << FILENAME << ": "
+ << ex.asUserHistory() << std::endl;
+ }
+ }
+
+ bool operator() (const zypp::HistoryItem::Ptr &item)
+ {
+ if (item->action.toEnum() == zypp::HistoryActionID::INSTALL_e) {
+ zypp::HistoryItemInstall *_item =
+ static_cast (item.get());
+
+ const std::string &name (_item->name);
+ bool autoreq = _item->reqby.empty();
+ std::string repoName, repoUrl;
+ Ypp::getRepositoryFromAlias (_item->repoalias, repoName, repoUrl);
+ bool update = repoUrl.find ("update") != std::string::npos;
+
+ if (!update) { // updates are ambiguous
+ if (autoreq)
+ m_dependencies.insert (name);
+ else
+ m_dependencies.erase (name);
+ }
+ }
+
+ return true;
+ }
+};
+
+struct YGtkPkgVestigialDialog::Impl : public YGtkPkgListView::Listener
+{
+ GtkWidget *dialog;
+ YGtkPkgListView *view;
+ GtkWidget *progressbar;
+
+ virtual void selectionChanged()
+ {
+ Ypp::List selected (view->getSelected());
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 1, selected.size());
+ }
+
+ void goto_clicked()
+ {
+ Ypp::List selected (view->getSelected());
+ if (selected.size()) {
+ std::string name (selected.get(0).name());
+ YGPackageSelector::get()->searchFor (Ypp::PoolQuery::NAME, name);
+ }
+ gtk_widget_hide (dialog);
+ }
+
+ void remove_all()
+ {
+ view->getList().remove();
+ }
+
+ static void response_cb (GtkDialog *dialog, gint response, Impl *pThis)
+ {
+ switch (response) {
+ case 1: pThis->goto_clicked(); break;
+ case 2: pThis->remove_all(); break;
+ default: gtk_widget_hide (GTK_WIDGET (pThis->dialog)); break;
+ }
+ }
+
+ void set_progress (gdouble fraction)
+ {
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progressbar), fraction);
+ while (g_main_context_iteration (NULL, FALSE)) ;
+ }
+};
+
+static bool testIsNeededDependency (ZyppSelectable zsel)
+{ // pass only installed packages: zsel->status() == S_KeepInstalled
+ zsel->setStatus (zypp::ui::S_Del);
+ zypp::Resolver_Ptr zResolver = zypp::getZYpp()->resolver();
+ bool noProbs = zResolver->resolvePool();
+ zResolver->undo();
+ zsel->setStatus (zypp::ui::S_KeepInstalled);
+ return !noProbs;
+}
+
+static void filterWhenContains (Ypp::Collection &col, std::list <ZyppSelectable> &pkgs)
+{
+ std::list <ZyppSelectable>::iterator it = pkgs.begin();
+ while (it != pkgs.end()) {
+ Ypp::Selectable p (*it);
+ if (col.contains (p))
+ it = pkgs.erase (it);
+ else it++;
+ }
+}
+
+static gboolean fill_list_idle_cb (void *data)
+{
+ YGtkPkgVestigialDialog::Impl *impl = (YGtkPkgVestigialDialog::Impl *) data;
+
+ // 1. get list of packages installed as dependencies
+ ZyppVestigialParser parser;
+ const std::set std::string &deps = parser.m_dependencies;
+ impl->set_progress (.1);
+ // 2. map string names to zypp objects and check whether they are still necessary
+ int size = deps.size(), i = 0;
+ std::list <ZyppSelectable> unneeded;
+ for (std::set std::string::const_iterator it = deps.begin();
+ it != deps.end(); it++) {
+ Ypp::PoolQuery query (Ypp::Selectable::PACKAGE);
+ query.addStringOr (*it);
+ query.addStringAttribute (Ypp::PoolQuery::NAME);
+ query.setStringMode (true, Ypp::PoolQuery::EXACT);
+ if (query.hasNext()) {
+ Ypp::Selectable sel (query.next());
+ ZyppSelectable zsel = sel.zyppSel();
+ if (zsel->status() == zypp::ui::S_KeepInstalled)
+ if (!testIsNeededDependency (zsel))
+ unneeded.push_back (zsel);
+ }
+
+ if ((i % 2) == 0)
+ impl->set_progress (.1 + ((i / (gdouble) size) * .80));
+ i++;
+ }
+ // 3. filter those installed by a container
+ impl->set_progress (.90);
+ Ypp::LangQuery langQuery;
+ size = langQuery.guessSize(); i = 0;
+ while (langQuery.hasNext()) {
+ Ypp::Selectable sel (langQuery.next());
+ if (!sel.isInstalled()) continue;
+ Ypp::Collection col (sel);
+ filterWhenContains (col, unneeded);
+ }
+ impl->set_progress (.95);
+ Ypp::PoolQuery patternQuery (Ypp::Selectable::PATTERN);
+ patternQuery.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::IS_INSTALLED));
+ size = patternQuery.guessSize(); i = 0;
+ while (patternQuery.hasNext()) {
+ Ypp::Selectable sel (patternQuery.next());
+ Ypp::Collection col (sel);
+ filterWhenContains (col, unneeded);
+ }
+
+ Ypp::List list (unneeded.size());
+ for (std::list <ZyppSelectable>::const_iterator it = unneeded.begin();
+ it != unneeded.end(); it++)
+ list.append (*it);
+ impl->view->setList (list);
+
+ gtk_widget_hide (impl->progressbar);
+ gdk_window_set_cursor (impl->dialog->window, NULL);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (impl->dialog), 2, unneeded.size());
+ gtk_window_present (GTK_WINDOW (impl->dialog));
+ return FALSE;
+}
+
+YGtkPkgVestigialDialog::YGtkPkgVestigialDialog()
+{
+ GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_OTHER, GTK_BUTTONS_NONE,
+ _("Show Unneeded Dependencies"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("This is a listing of dependencies no longer used. It is neither "
+ "accurate, nor comprehensive. Use with care."));
+
+ impl = new Impl();
+ GtkWidget *action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
+ impl->progressbar = gtk_progress_bar_new();
+ gtk_widget_set_size_request (impl->progressbar, 0, 0);
+ gtk_container_add (GTK_CONTAINER (action_area), impl->progressbar);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_JUMP_TO, 1);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), _("Remove All"), 2);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 1, FALSE);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 2, FALSE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 650, 600);
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (Impl::response_cb), impl);
+ g_signal_connect (G_OBJECT (dialog), "delete-event",
+ G_CALLBACK (gtk_true), NULL);
+
+ impl->view = new YGtkPkgListView (true, Ypp::List::NAME_SORT, false, true);
+ impl->view->addCheckColumn (INSTALLED_CHECK_PROP);
+ impl->view->addTextColumn (_("Name"), NAME_SUMMARY_PROP, true, -1);
+ impl->view->addTextColumn (_("Version"), VERSION_PROP, true, 125);
+ impl->view->addTextColumn (_("Size"), SIZE_PROP, false, 85);
+ impl->view->addTextColumn (_("Repository"), REPOSITORY_PROP, false, 180);
+ impl->view->addTextColumn (_("Supportability"), SUPPORT_PROP, false, 120);
+ impl->view->setListener (impl);
+
+ GtkWidget *content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_container_add (GTK_CONTAINER (content), impl->view->getWidget());
+
+ gtk_widget_show_all (dialog);
+ impl->dialog = dialog;
+
+ GdkCursor *cursor = gdk_cursor_new (GDK_WATCH);
+ gdk_window_set_cursor (dialog->window, cursor);
+ gdk_cursor_unref (cursor);
+
+ g_idle_add_full (G_PRIORITY_LOW, fill_list_idle_cb, impl, NULL);
+}
+
+YGtkPkgVestigialDialog::~YGtkPkgVestigialDialog()
+{
+ delete impl->view;
+ gtk_widget_destroy (impl->dialog);
+ delete impl;
+}
+
+void YGtkPkgVestigialDialog::popup()
+{ gtk_window_present (GTK_WINDOW (impl->dialog)); }
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtkpkgvestigialdialog.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,28 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* A dialog to help the user track no longer needed dependencies.
+*/
+
+#ifndef YGTK_PKG_VESTIGIAL_DIALOG_H
+#define YGTK_PKG_VESTIGIAL_DIALOG_H
+
+#include
+
+struct YGtkPkgVestigialDialog
+{
+ YGtkPkgVestigialDialog();
+ ~YGtkPkgVestigialDialog();
+
+ void popup();
+
+ struct Impl;
+ Impl *impl;
+};
+
+// you do not want to use this class directly:
+// use YGPackageSelector::get()->showVestigialDialog()
+
+#endif
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,221 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkTreeModel, C++ wrapper for gtk+ */
+// check the header file for information about this wrapper
+
+#include
+#include "ygtktreemodel.h"
+
+#define YGTK_TYPE_WRAP_MODEL (ygtk_wrap_model_get_type ())
+#define YGTK_WRAP_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_WRAP_MODEL, YGtkWrapModel))
+#define YGTK_WRAP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_WRAP_MODEL, YGtkWrapModelClass))
+#define YGTK_IS_WRAP_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), YGTK_TYPE_WRAP_MODEL))
+#define YGTK_IS_WRAP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), YGTK_TYPE_WRAP_MODEL))
+#define YGTK_WRAP_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_WRAP_MODEL, YGtkWrapModelClass))
+
+struct YGtkWrapModel
+{
+ GObject parent;
+ YGtkTreeModel *model;
+ struct Notify;
+ Notify *notify;
+};
+
+struct YGtkWrapModelClass
+{
+ GObjectClass parent_class;
+};
+
+// bridge as we don't want to mix c++ class polymorphism and gobject
+static void ygtk_wrap_model_entry_changed (YGtkWrapModel *model, int row);
+static void ygtk_wrap_model_entry_inserted (YGtkWrapModel *model, int row);
+static void ygtk_wrap_model_entry_deleted (YGtkWrapModel *model, int row);
+
+struct YGtkWrapModel::Notify : public YGtkTreeModel::Listener {
+YGtkWrapModel *model;
+ Notify (YGtkWrapModel *model) : model (model) {}
+ virtual void rowChanged (int row)
+ { ygtk_wrap_model_entry_changed (model, row); }
+ virtual void rowInserted (int row)
+ { ygtk_wrap_model_entry_inserted (model, row); }
+ virtual void rowDeleted (int row)
+ { ygtk_wrap_model_entry_deleted (model, row); }
+};
+
+static void ygtk_wrap_model_tree_model_init (GtkTreeModelIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (YGtkWrapModel, ygtk_wrap_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, ygtk_wrap_model_tree_model_init))
+
+static void ygtk_wrap_model_init (YGtkWrapModel *zmodel)
+{}
+
+static void ygtk_wrap_model_finalize (GObject *object)
+{
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (object);
+ delete ymodel->model;
+ ymodel->model = NULL;
+ delete ymodel->notify;
+ ymodel->notify = NULL;
+ G_OBJECT_CLASS (ygtk_wrap_model_parent_class)->finalize (object);
+}
+
+static GtkTreeModelFlags ygtk_wrap_model_get_flags (GtkTreeModel *model)
+{ return (GtkTreeModelFlags) (GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY); }
+
+static gboolean ygtk_wrap_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreePath *path)
+{ // from Path to Iter
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ gint index = gtk_tree_path_get_indices (path)[0];
+ iter->user_data = GINT_TO_POINTER (index);
+ int rowsNb = ymodel->model->rowsNb();
+ if (!rowsNb && index == 0 && ymodel->model->showEmptyEntry())
+ return TRUE;
+ return index < rowsNb;
+}
+
+static GtkTreePath *ygtk_wrap_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
+{ // from Iter to Path
+ int index = GPOINTER_TO_INT (iter->user_data);
+ GtkTreePath *path = gtk_tree_path_new();
+ gtk_tree_path_append_index (path, index);
+ return path;
+}
+
+static gboolean ygtk_wrap_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
+{
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ int index = GPOINTER_TO_INT (iter->user_data) + 1;
+ iter->user_data = GINT_TO_POINTER (index);
+ int rowsNb = ymodel->model->rowsNb();
+ return index < rowsNb;
+}
+
+static gboolean ygtk_wrap_model_iter_parent (GtkTreeModel *, GtkTreeIter *, GtkTreeIter *)
+{ return FALSE; }
+
+static gboolean ygtk_wrap_model_iter_has_child (GtkTreeModel *, GtkTreeIter *)
+{ return FALSE; }
+
+static gint ygtk_wrap_model_iter_n_children (GtkTreeModel *model, GtkTreeIter *iter)
+{ return 0; }
+
+static gboolean ygtk_wrap_model_iter_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
+ GtkTreeIter *parent, gint index)
+{
+ if (parent) return FALSE;
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ iter->user_data = GINT_TO_POINTER (index);
+ int rowsNb = ymodel->model->rowsNb();
+ if (!rowsNb && index == 0 && ymodel->model->showEmptyEntry())
+ return TRUE;
+ return index < rowsNb;
+}
+
+static gboolean ygtk_wrap_model_iter_children (
+ GtkTreeModel *model, GtkTreeIter *iter, GtkTreeIter *parent)
+{ return ygtk_wrap_model_iter_nth_child (model, iter, parent, 0); }
+
+void ygtk_wrap_model_entry_changed (YGtkWrapModel *model, int row)
+{
+ GtkTreeIter iter;
+ iter.user_data = GINT_TO_POINTER (row);
+ GtkTreePath *path = ygtk_wrap_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+}
+
+void ygtk_wrap_model_entry_inserted (YGtkWrapModel *ymodel, int row)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (ymodel);
+ GtkTreeIter iter;
+ iter.user_data = GINT_TO_POINTER (row);
+ GtkTreePath *path = ygtk_wrap_model_get_path (model, &iter);
+
+ if (row == 0 && ymodel->model->rowsNb() == 1 && ymodel->model->showEmptyEntry())
+ gtk_tree_model_row_changed (model, path, &iter);
+ else
+ gtk_tree_model_row_inserted (model, path, &iter);
+ gtk_tree_path_free (path);
+}
+
+void ygtk_wrap_model_entry_deleted (YGtkWrapModel *ymodel, int row)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (ymodel);
+ GtkTreeIter iter;
+ iter.user_data = GINT_TO_POINTER (row);
+ GtkTreePath *path = ygtk_wrap_model_get_path (model, &iter);
+
+ if (row == 0 && ymodel->model->rowsNb() == 1 && ymodel->model->showEmptyEntry())
+ gtk_tree_model_row_changed (model, path, &iter);
+ else
+ gtk_tree_model_row_deleted (model, path);
+ gtk_tree_path_free (path);
+}
+
+static gint ygtk_wrap_model_get_n_columns (GtkTreeModel *model)
+{
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ return ymodel->model->columnsNb();
+}
+
+static GType ygtk_wrap_model_get_column_type (GtkTreeModel *model, gint column)
+{
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ return ymodel->model->columnType (column);
+}
+
+static void ygtk_wrap_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
+ gint column, GValue *value)
+{
+ int row = GPOINTER_TO_INT (iter->user_data);
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ g_value_init (value, ymodel->model->columnType (column));
+ if (row == 0 && ymodel->model->rowsNb() == 0)
+ row = -1;
+ ymodel->model->getValue (row, column, value);
+}
+
+GtkTreeModel *ygtk_tree_model_new (YGtkTreeModel *model)
+{
+ YGtkWrapModel *ymodel = (YGtkWrapModel *) g_object_new (YGTK_TYPE_WRAP_MODEL, NULL);
+ ymodel->model = model;
+ ymodel->notify = new YGtkWrapModel::Notify (ymodel);
+ model->listener = ymodel->notify;
+ return GTK_TREE_MODEL (ymodel);
+}
+
+YGtkTreeModel *ygtk_tree_model_get_model (GtkTreeModel *model)
+{
+ YGtkWrapModel *ymodel = YGTK_WRAP_MODEL (model);
+ return ymodel->model;
+}
+
+static void ygtk_wrap_model_class_init (YGtkWrapModelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = ygtk_wrap_model_finalize;
+}
+
+static void ygtk_wrap_model_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = ygtk_wrap_model_get_flags;
+ iface->get_n_columns = ygtk_wrap_model_get_n_columns;
+ iface->get_column_type = ygtk_wrap_model_get_column_type;
+ iface->get_iter = ygtk_wrap_model_get_iter;
+ iface->get_path = ygtk_wrap_model_get_path;
+ iface->get_value = ygtk_wrap_model_get_value;
+ iface->iter_next = ygtk_wrap_model_iter_next;
+ iface->iter_children = ygtk_wrap_model_iter_children;
+ iface->iter_has_child = ygtk_wrap_model_iter_has_child;
+ iface->iter_n_children = ygtk_wrap_model_iter_n_children;
+ iface->iter_nth_child = ygtk_wrap_model_iter_nth_child;
+ iface->iter_parent = ygtk_wrap_model_iter_parent;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/ygtktreemodel.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,37 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Wraps GtkTreeModel as a C++ model.
+*/
+
+#ifndef YGTK_TREE_MODEL_H
+#define YGTK_TREE_MODEL_H
+
+#include
+
+struct YGtkTreeModel
+{
+ virtual void getValue (int row, int col, GValue *value) = 0;
+ virtual int rowsNb() = 0;
+ virtual int columnsNb() const = 0;
+ virtual GType columnType (int col) const = 0;
+ // if 'showEmptyEntry' will call getValue(row=-1) for the empty entry
+ virtual bool showEmptyEntry() const = 0;
+
+ struct Listener {
+ virtual void rowChanged (int row) = 0;
+ virtual void rowInserted (int row) = 0;
+ virtual void rowDeleted (int row) = 0;
+ };
+ Listener *listener;
+
+ virtual ~YGtkTreeModel() {}
+};
+
+GtkTreeModel *ygtk_tree_model_new (YGtkTreeModel *model);
+
+YGtkTreeModel *ygtk_tree_model_get_model (GtkTreeModel *model);
+
+#endif /*YGTK_TREE_MODEL_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,139 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* Tags PackageKit translator */
+// check the header file for information about this translator
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "YGi18n.h"
+#define YUILogComponent "gtk-pkg"
+#include
+#include "yzypptags.h"
+#include <string>
+
+/**
+ * translations taken from packagekit
+ **/
+const char *
+zypp_tag_group_enum_to_localised_text (YPkgGroupEnum group)
+{
+ switch (group) {
+ case YPKG_GROUP_EDUCATION: return _( "Education" );
+ case YPKG_GROUP_GAMES: return _( "Games" );
+ case YPKG_GROUP_GRAPHICS: return _( "Graphics" );
+ case YPKG_GROUP_OFFICE: return _( "Office" );
+ case YPKG_GROUP_PROGRAMMING: return _( "Programming" );
+ case YPKG_GROUP_MULTIMEDIA: return _( "Multimedia" );
+ case YPKG_GROUP_SYSTEM: return _( "System" );
+ // Translators: keep translation short
+ case YPKG_GROUP_DESKTOP_GNOME: return _( "Desktop (GNOME)" );
+ // Translators: keep translation short
+ case YPKG_GROUP_DESKTOP_KDE: return _( "Desktop (KDE)" );
+ // Translators: keep translation short
+ case YPKG_GROUP_DESKTOP_XFCE: return _( "Desktop (XFCE)" );
+ // Translators: keep translation short
+ case YPKG_GROUP_DESKTOP_OTHER: return _( "Desktop (Others)" );
+ case YPKG_GROUP_PUBLISHING: return _( "Publishing" );
+ // Translators: keep translation short
+ case YPKG_GROUP_ADMIN_TOOLS: return _( "Admin Tools" );
+ case YPKG_GROUP_LOCALIZATION: return _( "Localization" );
+ case YPKG_GROUP_SECURITY: return _( "Security" );
+ case YPKG_GROUP_COMMUNICATION: return _( "Communication" );
+ case YPKG_GROUP_NETWORK: return _( "Network" );
+ case YPKG_GROUP_DOCUMENTATION: return _( "Documentation" );
+ case YPKG_GROUP_UTILITIES: return _( "Utilities" );
+
+ case YPKG_GROUP_UNKNOWN: return _( "Unknown" );
+ case YPKG_GROUP_SUGGESTED: return _( "Suggested" );
+ case YPKG_GROUP_RECOMMENDED: return _( "Recommended" );
+ // Translators: this refers to packages no longer available in any repository.
+ case YPKG_GROUP_ORPHANED: return _( "Unmaintained" );
+ case YPKG_GROUP_RECENT: return _( "Recent" );
+ case YPKG_GROUP_MULTIVERSION: return _( "Multiversion" );
+ case YPKG_GROUP_TOTAL: break;
+ }
+ return "";
+}
+
+const char *
+zypp_tag_enum_to_icon (YPkgGroupEnum group)
+{
+ // mosts icons are from /usr/share/icons/hicolor/32x32/apps/package*
+ switch (group)
+ {
+ case YPKG_GROUP_EDUCATION: return( "package_edutainment" );
+ case YPKG_GROUP_GAMES: return( "package_games" );
+ case YPKG_GROUP_GRAPHICS: return( "package_graphics" );
+ case YPKG_GROUP_OFFICE: return( "applications-office" );
+ case YPKG_GROUP_PROGRAMMING: return( "package_development" );
+ case YPKG_GROUP_MULTIMEDIA: return( "package_multimedia" );
+ case YPKG_GROUP_SYSTEM: return( "applications-system" );
+ case YPKG_GROUP_DESKTOP_GNOME: return( "pattern-gnome" );
+ case YPKG_GROUP_DESKTOP_KDE: return( "pattern-kde" );
+ case YPKG_GROUP_DESKTOP_XFCE: return( "pattern-xfce" );
+ case YPKG_GROUP_DESKTOP_OTHER: return( "user-desktop" );
+ case YPKG_GROUP_PUBLISHING: return( "package_office_projectmanagement" );
+ case YPKG_GROUP_ADMIN_TOOLS: return( "yast-sysconfig" );
+ case YPKG_GROUP_LOCALIZATION: return( "yast-language" );
+ case YPKG_GROUP_SECURITY: return( "yast-security" );
+ case YPKG_GROUP_COMMUNICATION: return( "yast-modem" );
+ case YPKG_GROUP_NETWORK: return( "package_network" );
+ case YPKG_GROUP_DOCUMENTATION: return( "package_documentation" );
+ case YPKG_GROUP_UTILITIES: return( "package_utilities" );
+
+ case YPKG_GROUP_SUGGESTED: return( "gtk-about" );
+ case YPKG_GROUP_RECOMMENDED: return( "gtk-about" );
+ case YPKG_GROUP_ORPHANED: return( "gtk-missing-image" );
+ case YPKG_GROUP_RECENT: return( "gtk-new" );
+ case YPKG_GROUP_MULTIVERSION: return( "gtk-dnd-multiple" );
+ case YPKG_GROUP_UNKNOWN: return( "package_main" );
+
+ case YPKG_GROUP_TOTAL: break;
+ }
+ return "";
+}
+
+YPkgGroupEnum
+zypp_tag_convert (const std::string &groupu)
+{
+ std::string group (groupu); // lower-case
+ for (unsigned int i = 0; i < group.length(); i++)
+ if (group[i] >= 'A' && group[i] <= 'Z')
+ group[i] = group[i] - 'A' + 'a';
+
+ // yast2-qt: (modified to speed up)
+ if (group.compare (0, 22, "productivity/archiving") == 0) return YPKG_GROUP_ADMIN_TOOLS;
+ if (group.compare (0, 23, "productivity/clustering") == 0) return YPKG_GROUP_ADMIN_TOOLS;
+ if (group.compare (0, 22, "productivity/databases") == 0) return YPKG_GROUP_ADMIN_TOOLS;
+ if (group.compare (0, 17, "system/monitoring") == 0) return YPKG_GROUP_ADMIN_TOOLS;
+ if (group.compare (0, 17, "system/management") == 0) return YPKG_GROUP_ADMIN_TOOLS;
+ if (group.compare (0, 23, "productivity/publishing") == 0) return YPKG_GROUP_PUBLISHING;
+ if (group.compare (0, 22, "productivity/telephony") == 0) return YPKG_GROUP_COMMUNICATION;
+ if (group.compare (0, 19, "amusements/teaching") == 0) return YPKG_GROUP_EDUCATION;
+ if (group.compare (0, 17, "publishing/office") == 0) return YPKG_GROUP_OFFICE;
+ if (group.compare (0, 17, "productivity/text") == 0) return YPKG_GROUP_OFFICE;
+ if (group.compare (0, 20, "productivity/editors") == 0) return YPKG_GROUP_OFFICE;
+ if (group.compare (0, 21, "productivity/graphics") == 0) return YPKG_GROUP_GRAPHICS;
+ if (group.compare (0, 10, "amusements") == 0) return YPKG_GROUP_GAMES;
+ if (group.compare (0, 19, "system/localization") == 0) return YPKG_GROUP_LOCALIZATION;
+ if (group.compare (0, 11, "development") == 0) return YPKG_GROUP_PROGRAMMING;
+ if (group.compare (0, 20, "productivity/network") == 0) return YPKG_GROUP_NETWORK;
+ if (group.compare (0, 21, "productivity/security") == 0) return YPKG_GROUP_SECURITY;
+ if (group.compare (0, 16, "system/gui/gnome") == 0) return YPKG_GROUP_DESKTOP_GNOME;
+ if (group.compare (0, 14, "system/gui/kde") == 0) return YPKG_GROUP_DESKTOP_KDE;
+ if (group.compare (0, 15, "system/gui/xfce") == 0) return YPKG_GROUP_DESKTOP_XFCE;
+ if (group.compare (0, 10, "system/gui") == 0) return YPKG_GROUP_DESKTOP_OTHER;
+ if (group.compare (0, 8, "hardware") == 0) return YPKG_GROUP_SYSTEM;
+ if (group.compare (0, 6, "system") == 0) return YPKG_GROUP_SYSTEM;
+ if (group.find ("scientific") != string::npos) return YPKG_GROUP_EDUCATION;
+ if (group.find ("multimedia") != string::npos) return YPKG_GROUP_MULTIMEDIA;
+
+ // our own:
+ if (group.compare (0, 13, "documentation") == 0) return YPKG_GROUP_DOCUMENTATION;
+ if (group.compare (0, 12, "productivity") == 0) return YPKG_GROUP_UTILITIES;
+ return YPKG_GROUP_UNKNOWN;
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzypptags.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,44 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Converts RPM to PackageKit-like terminology.
+ Code from yast-qt-pkg.
+*/
+
+typedef enum {
+ /* PackageKit values */
+ YPKG_GROUP_OFFICE,
+ YPKG_GROUP_PUBLISHING,
+ YPKG_GROUP_GRAPHICS,
+ YPKG_GROUP_MULTIMEDIA,
+ YPKG_GROUP_EDUCATION,
+ YPKG_GROUP_GAMES,
+ YPKG_GROUP_DESKTOP_GNOME,
+ YPKG_GROUP_DESKTOP_KDE,
+ YPKG_GROUP_DESKTOP_XFCE,
+ YPKG_GROUP_DESKTOP_OTHER,
+ YPKG_GROUP_COMMUNICATION,
+ YPKG_GROUP_NETWORK,
+ YPKG_GROUP_PROGRAMMING,
+ YPKG_GROUP_DOCUMENTATION,
+ YPKG_GROUP_ADMIN_TOOLS,
+ YPKG_GROUP_SECURITY,
+ YPKG_GROUP_LOCALIZATION,
+ YPKG_GROUP_SYSTEM,
+ YPKG_GROUP_UTILITIES,
+ YPKG_GROUP_UNKNOWN,
+ YPKG_GROUP_SUGGESTED,
+ YPKG_GROUP_RECOMMENDED,
+ YPKG_GROUP_ORPHANED,
+ YPKG_GROUP_RECENT,
+ YPKG_GROUP_MULTIVERSION,
+ YPKG_GROUP_TOTAL,
+} YPkgGroupEnum;
+
+
+YPkgGroupEnum zypp_tag_convert (const std::string &rpm_group);
+
+const char *zypp_tag_group_enum_to_localised_text (YPkgGroupEnum group);
+const char *zypp_tag_enum_to_icon (YPkgGroupEnum group);
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,1511 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+/* Ypp, the zypp wrapper */
+// check the header file for information about this wrapper
+
+/*
+ Textdomain "gtk"
+ */
+
+#include "config.h"
+#include "YGi18n.h"
+#define YUILogComponent "gtk-pkg"
+#include
+#include "yzyppwrapper.h"
+#include "YGUtils.h"
+#include <algorithm>
+
+static Ypp::Interface *g_interface = 0;
+static bool g_autoSolver = true;
+
+// Repository
+
+Ypp::Repository::Repository (zypp::Repository repo)
+: m_repo (repo), m_repo_info (repo.info()), m_onlyInfo (false) {}
+
+Ypp::Repository::Repository (zypp::RepoInfo repo)
+: m_repo (NULL), m_repo_info (repo), m_onlyInfo (true) {}
+
+std::string Ypp::Repository::name()
+{ return m_repo_info.name(); }
+
+std::string Ypp::Repository::url()
+{ return m_repo_info.url().asString(); }
+
+bool Ypp::Repository::enabled()
+{ return m_repo_info.enabled(); }
+
+bool Ypp::Repository::isOutdated()
+{ return m_onlyInfo ? false : m_repo.maybeOutdated(); }
+
+bool Ypp::Repository::isSystem()
+{ return m_repo.isSystemRepo(); }
+
+bool Ypp::Repository::operator == (const Ypp::Repository &other) const
+{ return this->m_repo.info().alias() == other.m_repo.info().alias(); }
+
+void Ypp::getRepositoryFromAlias (const std::string &alias, std::string &name, std::string &url)
+{
+ static std::map repos;
+ if (repos.empty()) {
+ zypp::RepoManager manager;
+ std::list zypp::RepoInfo known_repos = manager.knownRepositories();
+ for (std::list zypp::RepoInfo::const_iterator it = known_repos.begin();
+ it != known_repos.end(); it++)
+ repos[it->alias()] = *it;
+ }
+
+ std::map ::iterator it = repos.find (alias);
+ if (it != repos.end()) {
+ zypp::RepoInfo *repo = &it->second;
+ name = repo->name();
+ url = repo->url().asString();
+ }
+ else
+ name = alias; // return alias if repo not currently setup-ed
+}
+
+// Version
+
+Ypp::Version::Version (ZyppResObject zobj)
+: m_zobj (zobj) {}
+
+int Ypp::Version::type()
+{ return Selectable::asType (m_zobj->kind()); }
+
+std::string Ypp::Version::number()
+{ return m_zobj->edition().asString(); }
+
+std::string Ypp::Version::arch()
+{ return m_zobj->arch().asString(); }
+
+Ypp::Repository Ypp::Version::repository()
+{ return Repository (m_zobj->repository()); }
+
+Size_t Ypp::Version::size()
+{ return m_zobj->installSize(); }
+
+Size_t Ypp::Version::downloadSize()
+{ return m_zobj->downloadSize(); }
+
+bool Ypp::Version::isInstalled()
+{
+ zypp::ResStatus status = m_zobj->poolItem().status();
+ switch (type()) {
+ case Ypp::Selectable::PATCH:
+ case Ypp::Selectable::PATTERN:
+ return status.isSatisfied() && !status.isToBeInstalled();
+ default:
+ return status.isInstalled();
+ }
+}
+
+bool Ypp::Version::toModify()
+{
+ zypp::ResStatus status = m_zobj->poolItem().status();
+ return status.transacts();
+}
+
+bool Ypp::Version::operator < (Ypp::Version &other)
+{ return this->m_zobj->edition() < other.m_zobj->edition(); }
+
+bool Ypp::Version::operator > (Ypp::Version &other)
+{ return this->m_zobj->edition() > other.m_zobj->edition(); }
+
+bool Ypp::Version::operator == (Ypp::Version &other)
+{ return this->m_zobj->edition() == other.m_zobj->edition(); }
+
+// Selectable
+
+zypp::ResKind Ypp::Selectable::asKind (Type type)
+{
+ switch (type) {
+ case PATTERN: return zypp::ResKind::pattern;
+ case PATCH: return zypp::ResKind::patch;
+ case PACKAGE: case LANGUAGE: case ALL: break;
+ }
+ return zypp::ResKind::package;
+}
+
+Ypp::Selectable::Type Ypp::Selectable::asType (zypp::ResKind kind)
+{
+ if (kind == zypp::ResKind::patch)
+ return PATCH;
+ if (kind == zypp::ResKind::pattern)
+ return PATTERN;
+ return PACKAGE;
+}
+
+Ypp::Selectable::Selectable (ZyppSelectable sel)
+: m_type (asType (sel->kind())), m_sel (sel)
+{}
+
+Ypp::Selectable::Selectable (zypp::Locale locale)
+: m_type (LANGUAGE), m_locale (locale) {}
+
+Ypp::Selectable::Type Ypp::Selectable::type()
+{ return m_type; }
+
+std::string Ypp::Selectable::name()
+{
+ switch (m_type) {
+ case LANGUAGE: return m_locale.name() + " (" + m_locale.code() + ")";
+ case PATTERN: return m_sel->theObj()->summary();
+ default: break;
+ }
+ return m_sel->name();
+}
+
+std::string Ypp::Selectable::summary()
+{
+ switch (m_type) {
+ case PATTERN:
+ case LANGUAGE: {
+ Collection col (*this);
+ int installed, total;
+ col.stats (&installed, &total);
+ std::ostringstream stream;
+ stream << _("Installed:") << " " << installed << " " << _("of") << " " << total;
+ return stream.str();
+ }
+ default: break;
+ }
+ return m_sel->theObj()->summary();
+}
+
+std::string Ypp::Selectable::description (bool as_html)
+{
+ if (m_type == LANGUAGE)
+ return summary();
+
+ std::string text (m_sel->theObj()->description()), br ("\n");
+ if (as_html) br = "<br />";
+ switch (m_type) {
+ case PACKAGE: {
+ // if it has this header, then it is HTML
+ const char *header = "<!-- DT:Rich -->", header_len = 16;
+ if (!text.compare (0, header_len, header, header_len))
+ ;
+ else {
+ // cut authors block
+ std::string::size_type i = text.find ("\nAuthors:", 0);
+ if (i == std::string::npos)
+ i = text.find ("\nAuthor:", 0);
+ if (i != std::string::npos)
+ text.erase (i);
+ // cut any lines at the end
+ while (text.length() > 0 && text [text.length()-1] == '\n')
+ text.erase (text.length()-1);
+
+ text = YGUtils::escapeMarkup (text);
+ if (as_html) // break every double line
+ YGUtils::replace (text, "\n\n", 2, "<br>");
+ text += br;
+ }
+ break;
+ }
+ case PATCH: {
+ ZyppPatch patch = castZyppPatch (m_sel->theObj());
+ if (patch->rebootSuggested()) {
+ text += br + br + "<b>" + _("Reboot required:") + " </b>";
+ text += _("the system will have to be restarted in order for "
+ "this patch to take effect.");
+ }
+ if (patch->reloginSuggested()) {
+ text += br + br + "<b>" + _("Relogin required:") + " </b>";
+ text += _("you must logout and login again for "
+ "this patch to take effect.");
+ }
+ if (patch->referencesBegin() != patch->referencesEnd()) {
+ text += br + br + "<b>Bugzilla:</b><ul>";
+ for (zypp::Patch::ReferenceIterator it = patch->referencesBegin();
+ it != patch->referencesEnd(); it++)
+ text += "<li>" + it.title() + "</a></li>";
+ text += "</ul>";
+ }
+ break;
+ }
+ case PATTERN: {
+ text += br + br + summary();
+ break;
+ }
+ default: break;
+ }
+ return text;
+}
+
+bool Ypp::Selectable::visible()
+{
+ switch (m_type) {
+ case PATTERN: {
+ ZyppPattern pattern = castZyppPattern (zyppSel()->theObj());
+ return pattern->userVisible();
+ }
+ case PATCH:
+ if (zyppSel()->hasCandidateObj())
+ if (!zyppSel()->candidateObj().isRelevant())
+ return false;
+ return true;
+ default: break;
+ }
+ return true;
+}
+
+bool Ypp::Selectable::isInstalled()
+{
+ switch (m_type) {
+ case PACKAGE:
+ return !m_sel->installedEmpty();
+ case PATTERN:
+ case PATCH:
+ if (hasCandidateVersion())
+ return candidate().isInstalled();
+ return true;
+ case LANGUAGE:
+ return _zyppPool().isRequestedLocale (m_locale);
+ case ALL: break;
+ }
+ return 0;
+}
+
+bool Ypp::Selectable::hasUpgrade()
+{
+ switch (m_type) {
+ case LANGUAGE: break;
+ default: {
+ const ZyppResObject candidate = m_sel->candidateObj();
+ const ZyppResObject installed = m_sel->installedObj();
+ if (!!candidate && !!installed)
+ return zypp::Edition::compare (candidate->edition(), installed->edition()) > 0;
+ }
+ }
+ return false;
+}
+
+bool Ypp::Selectable::isLocked()
+{
+ switch (m_type) {
+ case LANGUAGE: break;
+ default: {
+ zypp::ui::Status status = m_sel->status();
+ return status == zypp::ui::S_Taboo || status == zypp::ui::S_Protected;
+ }
+ }
+ return false;
+}
+
+bool Ypp::Selectable::toInstall()
+{
+ switch (m_type) {
+ case LANGUAGE: break;
+ default: return m_sel->toInstall();
+ }
+ return false;
+}
+
+bool Ypp::Selectable::toRemove()
+{
+ switch (m_type) {
+ case LANGUAGE: break;
+ default: return m_sel->toDelete();
+ }
+ return false;
+}
+
+bool Ypp::Selectable::toModify()
+{
+ switch (m_type) {
+ case LANGUAGE: break;
+ default: return m_sel->toModify();
+ }
+ return false;
+}
+
+bool Ypp::Selectable::toModifyAuto()
+{
+ switch (m_type) {
+ case LANGUAGE: break;
+ default:
+ return m_sel->toModify() && m_sel->modifiedBy() != zypp::ResStatus::USER;
+ }
+ return false;
+}
+
+void Ypp::Selectable::install()
+{
+ if (isLocked())
+ return;
+ switch (m_type) {
+ case LANGUAGE:
+ if (!_zyppPool().isRequestedLocale (m_locale))
+ _zyppPool().addRequestedLocale (m_locale);
+ break;
+ default: {
+ if (!m_sel->hasLicenceConfirmed()) {
+ ZyppResObject obj = m_sel->candidateObj();
+ if (obj && g_interface && g_autoSolver) {
+ const std::string &license = obj->licenseToConfirm();
+ if (!license.empty())
+ if (!g_interface->showLicense (*this, license))
+ return;
+ const std::string &msg = obj->insnotify();
+ if (!msg.empty())
+ if (!g_interface->showMessage (*this, msg))
+ return;
+ }
+ m_sel->setLicenceConfirmed();
+ }
+
+ zypp::ui::Status status = m_sel->status();
+ switch (status) {
+ // not applicable
+ case zypp::ui::S_Protected:
+ case zypp::ui::S_Taboo:
+ case zypp::ui::S_Install:
+ case zypp::ui::S_Update:
+ break;
+ // undo
+ case zypp::ui::S_Del:
+ if (hasInstalledVersion())
+ status = zypp::ui::S_Update;
+ else
+ status = zypp::ui::S_Install;
+ break;
+ // nothing to do about it
+ case zypp::ui::S_AutoDel:
+ break;
+ // action
+ case zypp::ui::S_NoInst:
+ case zypp::ui::S_AutoInstall:
+ status = zypp::ui::S_Install;
+ break;
+ case zypp::ui::S_KeepInstalled:
+ case zypp::ui::S_AutoUpdate:
+ status = zypp::ui::S_Update;
+ break;
+ }
+ m_sel->setStatus (status);
+ break;
+ }
+ }
+
+ if (!runSolver()) undo();
+}
+
+void Ypp::Selectable::remove()
+{
+ switch (m_type) {
+ case LANGUAGE:
+ if (_zyppPool().isRequestedLocale (m_locale))
+ _zyppPool().eraseRequestedLocale (m_locale);
+ break;
+ default: {
+ if (m_sel->hasCandidateObj() && g_interface && g_autoSolver) {
+ ZyppResObject obj = m_sel->candidateObj();
+ const std::string &msg = obj->delnotify();
+ if (!msg.empty())
+ if (!g_interface->showMessage (*this, msg))
+ return;
+ }
+
+ zypp::ui::Status status = m_sel->status();
+ switch (status) {
+ // not applicable
+ case zypp::ui::S_Protected:
+ case zypp::ui::S_Taboo:
+ case zypp::ui::S_NoInst:
+ case zypp::ui::S_Del:
+ break;
+ // nothing to do about it
+ case zypp::ui::S_AutoInstall:
+ case zypp::ui::S_AutoUpdate:
+ break;
+ // undo
+ case zypp::ui::S_Install:
+ case zypp::ui::S_Update:
+ // action
+ case zypp::ui::S_KeepInstalled:
+ case zypp::ui::S_AutoDel:
+ status = zypp::ui::S_Del;
+ break;
+ }
+ m_sel->setStatus (status);
+ break;
+ }
+ }
+
+ if (!runSolver()) undo();
+}
+
+void Ypp::Selectable::undo()
+{
+ // undo not applicable to language type
+
+ zypp::ui::Status status = m_sel->status();
+ zypp::ui::Status prev_status = status;
+ switch (status) {
+ // not applicable
+ case zypp::ui::S_Protected:
+ case zypp::ui::S_Taboo:
+ case zypp::ui::S_NoInst:
+ case zypp::ui::S_KeepInstalled:
+ break;
+ // undo
+ case zypp::ui::S_Install:
+ case zypp::ui::S_AutoInstall:
+ status = zypp::ui::S_NoInst;
+ break;
+ case zypp::ui::S_AutoUpdate:
+ case zypp::ui::S_AutoDel:
+ case zypp::ui::S_Update:
+ case zypp::ui::S_Del:
+ status = zypp::ui::S_KeepInstalled;
+ break;
+ }
+ m_sel->setStatus (status);
+
+ if (!runSolver()) {
+ m_sel->setStatus (prev_status);
+ runSolver();
+ }
+}
+
+void Ypp::Selectable::lock (bool lock)
+{
+ undo();
+ zypp::ui::Status status;
+ if (lock)
+ status = isInstalled() ? zypp::ui::S_Protected : zypp::ui::S_Taboo;
+ else
+ status = isInstalled() ? zypp::ui::S_KeepInstalled : zypp::ui::S_NoInst;
+ m_sel->setStatus (status);
+
+ if (!runSolver()) undo();
+}
+
+bool Ypp::Selectable::canRemove()
+{
+ switch (m_type) {
+ case PACKAGE: case LANGUAGE: return true;
+ default: break;
+ }
+ return false;
+}
+
+bool Ypp::Selectable::canLock()
+{
+ switch (m_type) {
+ case PACKAGE:
+ //case PATCH:
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+int Ypp::Selectable::totalVersions()
+{ return m_sel->installedSize() + m_sel->availableSize(); }
+
+Ypp::Version Ypp::Selectable::version (int n)
+{
+ if (n < (signed) m_sel->installedSize()) {
+ zypp::ui::Selectable::installed_iterator it = m_sel->installedBegin();
+ for (int i = 0; i < n; i++) it++;
+ return Version (*it);
+ }
+ else {
+ n -= m_sel->installedSize();
+ zypp::ui::Selectable::available_iterator it = m_sel->availableBegin();
+ for (int i = 0; i < n; i++) it++;
+ return Version (*it);
+ }
+}
+
+bool Ypp::Selectable::hasCandidateVersion()
+{ return !m_sel->availableEmpty(); }
+
+Ypp::Version Ypp::Selectable::candidate()
+{ return Version (m_sel->candidateObj()); }
+
+void Ypp::Selectable::setCandidate (Ypp::Version &version)
+{
+ m_sel->setCandidate (version.zyppObj());
+ runSolver();
+}
+
+bool Ypp::Selectable::hasInstalledVersion()
+{ return !m_sel->installedEmpty(); }
+
+Ypp::Version Ypp::Selectable::installed()
+{
+ if (m_type == PATCH || m_type == PATTERN) {
+ if (m_sel->candidateObj() && m_sel->candidateObj().isSatisfied())
+ return Ypp::Version (m_sel->candidateObj());
+ }
+ return Ypp::Version (m_sel->installedObj());
+}
+
+Ypp::Version Ypp::Selectable::anyVersion()
+{ return Version (m_sel->theObj()); }
+
+bool Ypp::Selectable::operator == (const Ypp::Selectable &other) const
+{ return this->m_sel == other.m_sel; }
+
+bool Ypp::Selectable::operator != (const Ypp::Selectable &other) const
+{ return this->m_sel != other.m_sel; }
+
+// Collection
+
+Ypp::Collection::Collection (Ypp::Selectable &sel)
+: m_sel (sel) {}
+
+static std::map g_patternsContent;
+static std::map g_languagesContent;
+
+Ypp::List *Ypp::Collection::getContent()
+{ // zypp::Pattern::Contents is expensive to iterate; this makes it cheap
+ if (m_sel.type() == Ypp::Selectable::PATTERN) {
+ ZyppPattern pattern = castZyppPattern (m_sel.zyppSel()->theObj());
+ std::map ::iterator it;
+ if ((it = g_patternsContent.find (pattern)) != g_patternsContent.end())
+ return &it->second;
+
+ zypp::Pattern::Contents c = pattern->contents();
+ Ypp::List list (c.size());
+ for (zypp::Pattern::Contents::Selectable_iterator it = c.selectableBegin();
+ it != c.selectableEnd(); it++)
+ list.append (Selectable (*it));
+ g_patternsContent.insert (std::make_pair (pattern, list));
+ return &g_patternsContent.find (pattern)->second;
+ }
+ else { // Language
+ zypp::Locale locale = m_sel.zyppLocale();
+ std::map ::iterator it;
+ if ((it = g_languagesContent.find (locale)) != g_languagesContent.end())
+ return &it->second;
+
+ zypp::sat::LocaleSupport locale_sup (locale);
+ Ypp::List list (50);
+ for_( it, locale_sup.selectableBegin(), locale_sup.selectableEnd() ) {
+ list.append (Selectable (*it));
+ }
+ g_languagesContent.insert (std::make_pair (locale, list));
+ return &g_languagesContent.find (locale)->second;
+ }
+}
+
+bool Ypp::Collection::contains (Ypp::Selectable &sel)
+{
+ if (m_sel.type() == Ypp::Selectable::PATCH) {
+ if (m_sel.hasCandidateVersion()) {
+ ZyppResObject object = m_sel.zyppSel()->candidateObj();
+ ZyppPatch patch = castZyppPatch (object);
+ zypp::Patch::Contents contents (patch->contents());
+ ZyppSelectable pkg = sel.zyppSel();
+ for (zypp::Patch::Contents::Selectable_iterator it =
+ contents.selectableBegin(); it != contents.selectableEnd(); it++) {
+ if (*it == pkg)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //else
+ Ypp::List *content = getContent();
+ return content->find (sel) != -1;
+}
+
+void Ypp::Collection::stats (int *installed, int *total)
+{
+ Ypp::List *content = getContent();
+ Ypp::ListProps props (*content);
+ *installed = props.isInstalledNb();
+ *total = content->size();
+}
+
+// Package
+
+Ypp::Package::Package (Ypp::Selectable &sel)
+: m_sel (sel) {}
+
+int Ypp::Package::support()
+{
+ ZyppPackage pkg = castZyppPackage (m_sel.zyppSel()->theObj());
+ switch (pkg->vendorSupport()) {
+ case zypp::VendorSupportUnknown: return 0;
+ case zypp::VendorSupportUnsupported: return 1;
+ case zypp::VendorSupportACC: return 2;
+ case zypp::VendorSupportLevel1: return 3;
+ case zypp::VendorSupportLevel2: return 4;
+ case zypp::VendorSupportLevel3: return 5;
+ }
+ return 0;
+}
+
+int Ypp::Package::supportTotal()
+{ return 6; }
+
+static zypp::VendorSupportOption asSupportOpt (int support)
+{
+ switch (support) {
+ case 0: return zypp::VendorSupportUnknown;
+ case 1: return zypp::VendorSupportUnsupported;
+ case 2: return zypp::VendorSupportACC;
+ case 3: return zypp::VendorSupportLevel1;
+ case 4: return zypp::VendorSupportLevel2;
+ case 5: return zypp::VendorSupportLevel3;
+ }
+ return zypp::VendorSupportUnknown;
+}
+
+std::string Ypp::Package::supportSummary (int support)
+{ return zypp::asUserString (asSupportOpt (support)); }
+
+std::string Ypp::Package::supportDescription (int support)
+{ return zypp::asUserStringDescription (asSupportOpt (support)); }
+
+std::string Ypp::Package::url()
+{
+ ZyppPackage package = castZyppPackage (m_sel.zyppSel()->theObj());
+ return package->url();
+}
+
+YPkgGroupEnum Ypp::Package::group()
+{
+ static std::map pkgGroupMap;
+ ZyppPackage pkg = castZyppPackage (m_sel.zyppSel()->theObj());
+ std::map ::iterator it = pkgGroupMap.find (pkg);
+ if (it == pkgGroupMap.end()) {
+ YPkgGroupEnum group = zypp_tag_convert (pkg->group());
+ pkgGroupMap.insert (std::make_pair (pkg, group));
+ return group;
+ }
+ return it->second;
+}
+
+std::string Ypp::Package::rpm_group()
+{
+ ZyppPackage pkg = castZyppPackage (m_sel.zyppSel()->theObj());
+ return pkg->group();
+}
+
+static std::map g_selPatch;
+
+static ZyppSelectable getSelPatch (Ypp::Selectable &sel)
+{
+ std::string name (sel.name());
+ std::map ::iterator it = g_selPatch.find (name);
+ if (it != g_selPatch.end())
+ return it->second;
+
+ Ypp::PoolQuery query (Ypp::Selectable::PATCH);
+ query.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::NOT_INSTALLED));
+ query.addCriteria (new Ypp::CollectionContainsMatch (sel));
+ if (query.hasNext()) {
+ Ypp::Selectable patch = query.next();
+ g_selPatch[name] = patch.zyppSel();
+ }
+ else
+ g_selPatch[name] = NULL;
+ return g_selPatch[name];
+}
+
+bool Ypp::Package::isCandidatePatch()
+{
+ if (m_sel.hasCandidateVersion() && m_sel.hasInstalledVersion()) {
+ Ypp::Version candidate (m_sel.candidate()), installed (m_sel.installed());
+ if (candidate > installed)
+ return getSelPatch (m_sel) != NULL;
+ }
+ return false;
+}
+
+Ypp::Selectable Ypp::Package::getCandidatePatch()
+{ return Selectable (getSelPatch (m_sel)); }
+
+// Patch
+
+Ypp::Patch::Patch (Ypp::Selectable &sel)
+: m_sel (sel) {}
+
+int Ypp::Patch::priority()
+{
+ ZyppPatch patch = castZyppPatch (m_sel.zyppSel()->theObj());
+ switch (patch->categoryEnum()) {
+ case zypp::Patch::CAT_SECURITY: return 0;
+ case zypp::Patch::CAT_RECOMMENDED: return 1;
+ case zypp::Patch::CAT_YAST: return 2;
+ case zypp::Patch::CAT_DOCUMENT: return 3;
+ case zypp::Patch::CAT_OPTIONAL: return 4;
+ case zypp::Patch::CAT_OTHER: return 5;
+ }
+ return 0;
+}
+
+int Ypp::Patch::priorityTotal()
+{ return 6; }
+
+const char *Ypp::Patch::prioritySummary (int priority)
+{
+ switch (priority) {
+ // Translators: this refers to patch priority
+ case 0: return _("Security");
+ // Translators: this refers to patch priority
+ case 1: return _("Recommended");
+ case 2: return "YaST";
+ case 3: return _("Documentation");
+ // Translators: this refers to patch priority
+ case 4: return _("Optional");
+ // Translators: this refers to patch priority
+ case 5: return _("Other");
+ }
+ return 0;
+}
+
+// Disk
+
+std::vector std::string Ypp::getPartitionList()
+{
+ ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
+ std::vector std::string partitions;
+ partitions.reserve (diskUsage.size());
+ for (ZyppDuSet::iterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
+ const ZyppDu &point = *it;
+ if (!point.readonly)
+ partitions.push_back (point.dir);
+ }
+ std::sort (partitions.begin(), partitions.end());
+ return partitions;
+}
+
+const ZyppDu Ypp::getPartition (const std::string &mount_point)
+{
+ ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
+ for (ZyppDuSet::iterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
+ const ZyppDu &point = *it;
+ if (mount_point == point.dir)
+ return point;
+ }
+ return *zypp::getZYpp()->diskUsage().begin(); // error
+}
+
+// Busy
+
+static Ypp::BusyListener *g_busy_listener = 0;
+static bool g_busy_running = false;
+
+void Ypp::setBusyListener (Ypp::BusyListener *listener)
+{ g_busy_listener = listener; }
+
+struct Ypp::Busy::Impl {
+ int cur, size;
+ bool showing;
+ GTimeVal start_t;
+
+ Impl (int size)
+ : cur (0), size (size), showing (false)
+ {
+ g_get_current_time (&start_t);
+ g_busy_running = true;
+ g_busy_listener->loading (0);
+ }
+
+ ~Impl()
+ {
+ g_busy_running = false;
+ g_busy_listener->loading (1);
+ }
+
+ void inc()
+ {
+ cur++;
+#if 0
+ // shows continuous progress only when it takes more than 1 sec to drive 'N' loops
+ if (showing) {
+ if ((cur % 500) == 0)
+ g_busy_listener->loading (cur / (float) size);
+ }
+ else if (cur == 499) {
+ GTimeVal now_t;
+ g_get_current_time (&now_t);
+ if (now_t.tv_usec - start_t.tv_usec >= 35*1000 ||
+ now_t.tv_sec - start_t.tv_sec >= 1) {
+ showing = true;
+ }
+ }
+#else
+ g_busy_listener->loading (cur / (float) size);
+#endif
+ }
+};
+
+Ypp::Busy::Busy (int size) : impl (NULL)
+{
+ if (g_busy_listener && !g_busy_running)
+ impl = new Impl (size);
+}
+
+Ypp::Busy::~Busy()
+{ delete impl; }
+
+void Ypp::Busy::inc()
+{ if (impl) impl->inc(); }
+
+// Interface
+
+std::list g_sel_listeners;
+static bool g_transacting = false;
+
+void Ypp::addSelListener (Ypp::SelListener *listener)
+{ g_sel_listeners.push_back (listener); }
+
+void Ypp::removeSelListener (Ypp::SelListener *listener)
+{ g_sel_listeners.remove (listener); }
+
+void Ypp::notifySelModified()
+{
+ for (std::list ::iterator it = g_sel_listeners.begin();
+ it != g_sel_listeners.end(); it++)
+ (*it)->selectableModified();
+}
+
+void Ypp::setInterface (Ypp::Interface *interface)
+{
+ g_interface = interface;
+}
+
+Ypp::Interface *Ypp::getInterface() { return g_interface; }
+
+Ypp::Problem::Solution *Ypp::Problem::getSolution (int nb)
+{ return (Solution *) g_slist_nth_data ((GSList *) impl, nb); }
+
+bool Ypp::runSolver (bool force)
+{
+ if (g_transacting) return true;
+ if (!g_autoSolver && !force) {
+ notifySelModified();
+ return true;
+ }
+
+ if (g_busy_listener)
+ g_busy_listener->loading (0);
+
+ zypp::Resolver_Ptr zResolver = zypp::getZYpp()->resolver();
+ bool resolved = false;
+ while (true) {
+ if (zResolver->resolvePool()) {
+ resolved = true; // no need for user intervention
+ break;
+ }
+ zypp::ResolverProblemList zProblems = zResolver->problems();
+ if ((resolved = zProblems.empty())) break;
+ if (!g_interface) break;
+
+ std::list problems;
+ for (zypp::ResolverProblemList::iterator it = zProblems.begin();
+ it != zProblems.end(); it++) {
+ Problem *problem = new Problem();
+ problem->description = (*it)->description();
+ problem->details = (*it)->details();
+ GSList *solutions = NULL;
+ zypp::ProblemSolutionList zSolutions = (*it)->solutions();
+ for (zypp::ProblemSolutionList::iterator jt = zSolutions.begin();
+ jt != zSolutions.end(); jt++) {
+ Problem::Solution *solution = new Problem::Solution();
+ solution->description = (*jt)->description();
+ solution->details = (*jt)->details();
+ solution->apply = false;
+ solution->impl = (void *) get_pointer (*jt);
+ solutions = g_slist_append (solutions, solution);
+ }
+ problem->impl = (void *) solutions;
+ problems.push_back (problem);
+ }
+
+ resolved = g_interface->resolveProblems (problems);
+ if (resolved) {
+ zypp::ProblemSolutionList choices;
+ for (std::list ::iterator it = problems.begin();
+ it != problems.end(); it++) {
+ for (int i = 0; (*it)->getSolution (i); i++) {
+ Problem::Solution *solution = (*it)->getSolution (i);
+ if (resolved && solution->apply)
+ choices.push_back ((zypp::ProblemSolution *) solution->impl);
+ delete solution;
+ }
+ g_slist_free ((GSList *) (*it)->impl);
+ delete *it;
+ }
+ zResolver->applySolutions (choices);
+ }
+ else
+ break;
+ }
+ if (!resolved)
+ zResolver->undo();
+
+ notifySelModified();
+ if (g_busy_listener)
+ g_busy_listener->loading (1);
+ return resolved;
+}
+
+void Ypp::setEnableSolver (bool enabled)
+{
+ g_autoSolver = enabled;
+ if (enabled) runSolver();
+}
+
+bool Ypp::isSolverEnabled()
+{ return g_autoSolver; }
+
+bool Ypp::showPendingLicenses (Ypp::Selectable::Type type)
+{
+ const zypp::ResKind &kind = Selectable::asKind (type);
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin(kind);
+ it != zyppPool().byKindEnd(kind); it++) {
+ ZyppSelectable zsel = (*it);
+ switch (zsel->status()) {
+ case zypp::ui::S_Install: case zypp::ui::S_AutoInstall:
+ case zypp::ui::S_Update: case zypp::ui::S_AutoUpdate:
+ if (zsel->candidateObj()) {
+ std::string license = zsel->candidateObj()->licenseToConfirm();
+ if (!license.empty())
+ if (!zsel->hasLicenceConfirmed()) {
+ Selectable sel (zsel);
+ if (!g_interface->showLicense (sel, license))
+ return false;
+ }
+ }
+ default: break;
+ }
+ }
+ return true;
+}
+
+void Ypp::startTransactions()
+{ g_transacting = true; }
+
+bool Ypp::finishTransactions()
+{ g_transacting = false; return runSolver(); }
+
+// Query
+
+struct Ypp::StrMatch::Impl {
+ int attrbs;
+ std::list std::string strings;
+
+ Impl (int attrbs) : attrbs (attrbs) {}
+};
+
+Ypp::StrMatch::StrMatch (int attrbs)
+: impl (new Impl (attrbs)) {}
+
+Ypp::StrMatch::~StrMatch()
+{ delete impl; }
+
+void Ypp::StrMatch::add (const std::string &str)
+{ impl->strings.push_back (str); }
+
+bool Ypp::StrMatch::match (Ypp::Selectable &sel)
+{
+ std::string haystack;
+ haystack.reserve (2048);
+ if (impl->attrbs & NAME)
+ haystack += sel.name();
+ if (impl->attrbs & SUMMARY)
+ haystack += sel.summary();
+ if (impl->attrbs & DESCRIPTION)
+ haystack += sel.description (false);
+
+ for (std::list std::string::iterator it = impl->strings.begin();
+ it != impl->strings.end(); it++) {
+ const std::string &needle = *it;
+ if (!strcasestr (haystack.c_str(), needle.c_str()))
+ return false;
+ }
+ return true;
+}
+
+Ypp::StatusMatch::StatusMatch (Ypp::StatusMatch::Status status)
+: m_status (status) {}
+
+bool Ypp::StatusMatch::match (Selectable &sel)
+{
+ switch (m_status) {
+ case IS_INSTALLED: return sel.isInstalled();
+ case NOT_INSTALLED: return !sel.isInstalled();
+ case HAS_UPGRADE: return sel.hasUpgrade();
+ case IS_LOCKED: return sel.isLocked();
+ case TO_MODIFY: return sel.toModify();
+ }
+ return false;
+}
+
+Ypp::PKGroupMatch::PKGroupMatch (YPkgGroupEnum group)
+: m_group (group) {}
+
+bool Ypp::PKGroupMatch::match (Selectable &sel)
+{
+ ZyppPackage pkg = castZyppPackage (sel.zyppSel()->theObj());
+ switch (m_group) {
+ case YPKG_GROUP_RECOMMENDED: return zypp::PoolItem (pkg).status().isRecommended();
+ case YPKG_GROUP_SUGGESTED: return zypp::PoolItem (pkg).status().isSuggested();
+ case YPKG_GROUP_ORPHANED: return zypp::PoolItem (pkg).status().isOrphaned();
+ case YPKG_GROUP_RECENT:
+ if (sel.hasCandidateVersion()) {
+ time_t build = static_cast (sel.candidate().zyppObj()->buildtime());
+ time_t now = time (NULL);
+ time_t delta = (now - build) / (60*60*24); // in days
+ return delta <= 7;
+ }
+ return false;
+#if ZYPP_VERSION >= 6030004
+ case YPKG_GROUP_MULTIVERSION: return sel.zyppSel()->multiversionInstall();
+#endif
+ default: return Package (sel).group() == m_group;
+ }
+ return false;
+}
+
+Ypp::RpmGroupMatch::RpmGroupMatch (const std::string &group)
+: m_group (group) {}
+
+bool Ypp::RpmGroupMatch::match (Selectable &sel)
+{
+ std::string pkg_group (Package (sel).rpm_group());
+ int len = MIN (m_group.size(), pkg_group.size());
+ return m_group.compare (0, len, pkg_group, 0, len) == 0;
+}
+
+Ypp::FromCollectionMatch::FromCollectionMatch (Collection &col)
+: m_collection (col) {}
+
+bool Ypp::FromCollectionMatch::match (Selectable &sel)
+{ return m_collection.contains (sel); }
+
+Ypp::CollectionContainsMatch::CollectionContainsMatch (Ypp::Selectable &sel)
+: m_contains (sel) {}
+
+bool Ypp::CollectionContainsMatch::match (Ypp::Selectable &sel)
+{
+ Collection collection (sel);
+ return collection.contains (m_contains);
+}
+
+struct Ypp::PoolQuery::Impl {
+ ZyppQuery query;
+ std::list criterias;
+ bool filelist_attrb;
+ ZyppQuery::Selectable_iterator it;
+ bool begin;
+
+ Impl() : filelist_attrb (false), begin (true) {}
+
+ ~Impl()
+ {
+ for (std::list ::iterator it = criterias.begin();
+ it != criterias.end(); it++)
+ delete *it;
+ }
+
+ bool match (Ypp::Selectable &sel)
+ { // exclusive
+ for (std::list ::iterator it = criterias.begin();
+ it != criterias.end(); it++)
+ if (!(*it)->match (sel))
+ return false;
+ return true;
+ }
+
+ ZyppQuery::Selectable_iterator untilMatch (ZyppQuery::Selectable_iterator it)
+ { // iterates until match -- will return argument if it already matches
+ while (it != query.selectableEnd()) {
+ Ypp::Selectable sel (*it);
+ if (sel.visible() && match (sel)) break;
+ it++;
+ }
+ return it;
+ }
+};
+
+Ypp::PoolQuery::PoolQuery (Ypp::Selectable::Type type)
+: impl (new Impl())
+{
+ assert (type != Selectable::LANGUAGE);
+ if (type != Selectable::ALL)
+ impl->query.addKind (Selectable::asKind (type));
+}
+
+Ypp::PoolQuery::~PoolQuery()
+{ delete impl; }
+
+void Ypp::PoolQuery::setStringMode (bool caseSensitive, Ypp::PoolQuery::MatchType match)
+{
+ impl->query.setCaseSensitive (caseSensitive);
+ switch (match) {
+ case CONTAINS: impl->query.setMatchSubstring(); break;
+ case EXACT: impl->query.setMatchExact(); break;
+ case GLOB: impl->query.setMatchGlob(); break;
+ case REGEX: impl->query.setMatchRegex(); break;
+ }
+}
+
+void Ypp::PoolQuery::addStringAttribute (Ypp::PoolQuery::StringAttribute attrb)
+{
+ zypp::sat::SolvAttr _attrb;
+ impl->filelist_attrb = false;
+ switch (attrb) {
+ case NAME: _attrb = ZyppAttribute::name; break;
+ case SUMMARY: _attrb = ZyppAttribute::summary; break;
+ case DESCRIPTION: _attrb = ZyppAttribute::description; break;
+ case FILELIST: _attrb = ZyppAttribute::filelist; impl->filelist_attrb = true; break;
+ case REQUIRES: _attrb = ZyppAttribute ("solvable:requires"); break;
+ case PROVIDES: _attrb = ZyppAttribute ("solvable:provides"); break;
+ }
+ impl->query.addAttribute (_attrb);
+}
+
+void Ypp::PoolQuery::addStringOr (const std::string &str)
+{
+ if (impl->filelist_attrb && !str.empty())
+ impl->query.setFilesMatchFullPath (str[0] == '/');
+ impl->query.addString (str);
+}
+
+void Ypp::PoolQuery::addRepository (Ypp::Repository &repository)
+{ impl->query.addRepo (repository.zyppRepo().info().alias()); }
+
+void Ypp::PoolQuery::addCriteria (Ypp::Match *criteria)
+{ impl->criterias.push_back (criteria); }
+
+bool Ypp::PoolQuery::hasNext()
+{
+ if (impl->begin) {
+ impl->it = impl->untilMatch (impl->query.selectableBegin());
+ impl->begin = false;
+ }
+ return impl->it != impl->query.selectableEnd();
+}
+
+Ypp::Selectable Ypp::PoolQuery::next()
+{
+ Ypp::Selectable sel (*impl->it);
+ impl->it = impl->untilMatch (++impl->it);
+ return sel;
+}
+
+int Ypp::PoolQuery::guessSize()
+{ return impl->query.size(); }
+
+ZyppQuery &Ypp::PoolQuery::zyppQuery()
+{ return impl->query; }
+
+Ypp::Selectable::Type Ypp::PoolQuery::poolType()
+{ return Selectable::asType (*impl->query.kinds().begin()); }
+
+struct Ypp::LangQuery::Impl {
+ zypp::LocaleSet locales;
+ zypp::LocaleSet::const_iterator it;
+
+ Impl() {
+ locales = _zyppPool().getAvailableLocales();
+ it = locales.begin();
+ }
+};
+
+Ypp::LangQuery::LangQuery()
+: impl (new Impl()) {}
+
+Ypp::LangQuery::~LangQuery()
+{ delete impl; }
+
+bool Ypp::LangQuery::hasNext()
+{ return impl->it != impl->locales.end(); }
+
+Ypp::Selectable Ypp::LangQuery::next()
+{ return Ypp::Selectable (*(impl->it++)); }
+
+int Ypp::LangQuery::guessSize()
+{ return impl->locales.size(); }
+
+// List (aggregator)
+
+struct Ypp::List::Impl {
+ std::vector <Selectable> vector;
+ int refcount;
+ Impl() : refcount (1) {}
+};
+
+Ypp::List::List (Ypp::Query &query)
+: impl (new Impl())
+{
+ reserve (query.guessSize());
+ while (query.hasNext())
+ append (query.next());
+}
+
+Ypp::List::List (int size)
+: impl (new Impl())
+{ reserve (size); }
+
+Ypp::List::List (const List &other)
+: impl (other.impl)
+{ impl->refcount++; }
+
+Ypp::List &Ypp::List::operator= (const List &other)
+{
+ if (--impl->refcount <= 0) delete impl;
+ impl = other.impl;
+ impl->refcount++;
+ return *this;
+}
+
+Ypp::List::~List()
+{ if (--impl->refcount <= 0) delete impl; }
+
+Ypp::List Ypp::List::clone()
+{
+ Ypp::List other (size());
+ other.impl->vector = this->impl->vector;
+ return other;
+}
+
+Ypp::Selectable &Ypp::List::get (int index)
+{ return impl->vector[index]; }
+
+int Ypp::List::size()
+{ return impl->vector.size(); }
+
+int Ypp::List::count (Match *match)
+{
+ int count = 0;
+ for (std::vector <Selectable>::iterator it = impl->vector.begin();
+ it != impl->vector.end(); it++)
+ if (match->match (*it))
+ count++;
+ return count;
+}
+
+int Ypp::List::find (const std::string &name)
+{
+ for (unsigned int i = 0; i < impl->vector.size(); i++)
+ if (name == impl->vector[i].name())
+ return i;
+ return -1;
+}
+
+int Ypp::List::find (Selectable &sel)
+{
+ for (unsigned int i = 0; i < impl->vector.size(); i++)
+ if (sel == impl->vector[i])
+ return i;
+ return -1;
+}
+
+void Ypp::List::reserve (int size)
+{ impl->vector.reserve (size); }
+
+void Ypp::List::append (Ypp::Selectable sel)
+{ impl->vector.push_back (sel); }
+
+void Ypp::List::install()
+{
+ startTransactions();
+ for (std::vector <Selectable>::iterator it = impl->vector.begin();
+ it != impl->vector.end(); it++)
+ it->install();
+ if (!finishTransactions())
+ undo();
+}
+
+void Ypp::List::remove()
+{
+ startTransactions();
+ for (std::vector <Selectable>::iterator it = impl->vector.begin();
+ it != impl->vector.end(); it++)
+ it->remove();
+ if (!finishTransactions())
+ undo();
+}
+
+void Ypp::List::lock (bool lock)
+{
+ startTransactions();
+ for (std::vector <Selectable>::iterator it = impl->vector.begin();
+ it != impl->vector.end(); it++)
+ it->lock (lock);
+ if (!finishTransactions())
+ undo();
+}
+
+void Ypp::List::undo()
+{
+ startTransactions();
+ for (std::vector <Selectable>::iterator it = impl->vector.begin();
+ it != impl->vector.end(); it++)
+ it->undo();
+ finishTransactions();
+}
+
+static bool installed_order (Ypp::Selectable &a, Ypp::Selectable &b)
+{ return (a.isInstalled() ? 0 : 1) < (b.isInstalled() ? 0 : 1); }
+
+static bool utf8_name_order (Ypp::Selectable &a, Ypp::Selectable &b)
+{ return g_utf8_collate (a.name().c_str(), b.name().c_str()) < 0; }
+
+static bool name_order (Ypp::Selectable &a, Ypp::Selectable &b)
+{ return strcasecmp (a.name().c_str(), b.name().c_str()) < 0; }
+
+static bool size_order (Ypp::Selectable &a, Ypp::Selectable &b)
+{ return a.anyVersion().size() < b.anyVersion().size(); }
+
+static std::string get_alias (Ypp::Selectable &a)
+{
+ if (a.hasCandidateVersion())
+ return a.candidate().repository().zyppRepo().alias();
+ return "a"; // system
+}
+
+static bool repository_order (Ypp::Selectable &a, Ypp::Selectable &b)
+{ return get_alias (a) < get_alias(b); }
+
+static bool support_order (Ypp::Selectable &a, Ypp::Selectable &b)
+{ return Ypp::Package(a).support() < Ypp::Package(b).support(); }
+
+typedef bool (* order_cb) (Ypp::Selectable &a, Ypp::Selectable &b);
+
+static order_cb _order;
+static bool _ascendent; // proxy between our order callbacks and std::sort's
+static bool proxy_order (const Ypp::Selectable &a, const Ypp::Selectable &b)
+{ return _order ((Ypp::Selectable &) a, (Ypp::Selectable &) b) == _ascendent; }
+
+void Ypp::List::sort (Ypp::List::SortAttribute attrb, bool ascendent)
+{
+ if (impl->vector.empty())
+ return;
+
+ bool unique_criteria = false;
+ switch (attrb) {
+ case IS_INSTALLED_SORT: _order = installed_order; break;
+ case NAME_SORT:
+ // package names are never internationalized, but langs / patterns may be
+ if (impl->vector[0].type() != Selectable::PACKAGE)
+ _order = utf8_name_order;
+ else
+ _order = name_order;
+ unique_criteria = true;
+ break;
+ case SIZE_SORT: _order = size_order; unique_criteria = true; break;
+ case REPOSITORY_SORT: _order = repository_order; break;
+ case SUPPORT_SORT: _order = support_order; break;
+ }
+ _ascendent = ascendent;
+ if (unique_criteria)
+ std::sort (impl->vector.begin(), impl->vector.end(), proxy_order);
+ else // many attributes are equal: maintain previous order in such cases
+ std::stable_sort (impl->vector.begin(), impl->vector.end(), proxy_order);
+}
+
+void Ypp::List::reverse()
+{ std::reverse (impl->vector.begin(), impl->vector.end()); }
+
+bool Ypp::List::operator == (const Ypp::List &other) const
+{ return this->impl == other.impl; }
+bool Ypp::List::operator != (const Ypp::List &other) const
+{ return this->impl != other.impl; }
+
+// ListProps
+
+struct Ypp::ListProps::Impl {
+ int isInstalled, hasUpgrade, toModify, isLocked, size;
+ int canRemove : 2, canLock : 2;
+
+ Impl (List list) {
+ isInstalled = hasUpgrade = toModify = isLocked = canRemove = canLock = 0;
+ size = list.size();
+ for (int i = 0; i < size; i++) {
+ Selectable &sel = list.get (i);
+ if (sel.isInstalled()) {
+ isInstalled++;
+ if (sel.hasUpgrade())
+ hasUpgrade++;
+ }
+ if (sel.toModify())
+ toModify++;
+ if (sel.isLocked())
+ isLocked++;
+ }
+ if (size) {
+ Selectable sel = list.get (0);
+ canRemove = sel.canRemove();
+ canLock = sel.canLock();
+ }
+ }
+};
+
+Ypp::ListProps::ListProps (Ypp::List &list)
+: impl (new Impl (list)) {}
+
+Ypp::ListProps::~ListProps()
+{ delete impl; }
+
+bool Ypp::ListProps::isInstalled() const
+{ return impl->isInstalled == impl->size; }
+bool Ypp::ListProps::isNotInstalled() const
+{ return impl->isInstalled == 0; }
+bool Ypp::ListProps::hasUpgrade() const
+{ return impl->hasUpgrade == impl->size; }
+bool Ypp::ListProps::toModify() const
+{ return impl->toModify == impl->size; }
+bool Ypp::ListProps::isLocked() const
+{ return impl->isLocked == impl->size; }
+bool Ypp::ListProps::isUnlocked() const
+{ return impl->isLocked == 0; }
+bool Ypp::ListProps::canRemove() const
+{ return impl->canRemove; }
+bool Ypp::ListProps::canLock() const
+{ return impl->canLock; }
+
+int Ypp::ListProps::isInstalledNb() const
+{ return impl->isInstalled; }
+int Ypp::ListProps::isNotInstalledNb() const
+{ return impl->size - impl->isInstalled; }
+int Ypp::ListProps::hasUpgradeNb() const
+{ return impl->hasUpgrade; }
+int Ypp::ListProps::isLockedNb() const
+{ return impl->isLocked; }
+int Ypp::ListProps::toModifyNb() const
+{ return impl->toModify; }
+
+// General
+
+void Ypp::init()
+{
+ zyppPool().saveState zypp::Package();
+ zyppPool().saveState zypp::Pattern();
+ zyppPool().saveState ();
+}
+
+bool Ypp::isModified()
+{
+ return zyppPool().diffState zypp::Package() ||
+ zyppPool().diffState zypp::Pattern() ||
+ zyppPool().diffState zypp::Patch();
+}
+
+void Ypp::finish()
+{
+ g_sel_listeners.clear();
+ g_interface = 0;
+ g_transacting = false;
+ g_autoSolver = true;
+ g_busy_listener = 0;
+ g_busy_running = false;
+ g_patternsContent.clear();
+ g_languagesContent.clear();
+ g_selPatch.clear();
+}
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.h?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.h (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/pkg/yzyppwrapper.h Mon Aug 1 09:44:45 2011
@@ -0,0 +1,511 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* Simplifies, unifies and extends libzypp's API.
+
+ Several classes are available to wrap around common Zypp objects
+ in order to simplify or extend them. These methods can be interwined
+ with direct libzypp use, but you should call Ypp::notifySelModified()
+ to broadcast any change to a selectable.
+
+ Use Ypp::QueryPool to iterate through the Selectable pool.
+ It extends zypp::PoolQuery by adding the possibility to add
+ custom criterias for filtering, to be apply endogenously.
+
+ If you need to iterate through it several times, you can create
+ a Ypp::List out of it. This random-access list can be manually
+ manipulated with several available methods such as for sorting.
+ The list is ref-counted so you can easily and freely hold it at
+ several widgets.
+ In order to inspect several common properties of a group of packages,
+ pass a list to Ypp::ListProps.
+
+ Usage example (unlock all packages):
+
+ Ypp::PoolQuery query (Ypp::Selectable::PACKAGE_TYPE);
+ query.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::IS_LOCKED));
+
+ Ypp::List list (query);
+ list.unlock();
+
+ You are advised to register an Ypp::Interface implementation as some
+ transactions are bound by user decisions. Call Ypp::init() and
+ Ypp::finish() when you begin or are done (respectively) using these
+ methods.
+ Use Ypp::addSelListener() to be notified of any 'selectable' change.
+*/
+
+#ifndef ZYPP_WRAPPER_H
+#define ZYPP_WRAPPER_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include <string>
+#include <list>
+#include "yzypptags.h"
+
+typedef zypp::ResPool _ZyppPool;
+typedef zypp::ResPoolProxy ZyppPool;
+inline ZyppPool zyppPool() { return zypp::getZYpp()->poolProxy(); }
+inline _ZyppPool _zyppPool() { return zypp::getZYpp()->pool(); }
+typedef zypp::ResObject::constPtr ZyppResObject;
+typedef zypp::ResObject* ZyppResObjectPtr;
+typedef zypp::ui::Selectable::Ptr ZyppSelectable;
+typedef zypp::ui::Selectable* ZyppSelectablePtr;
+typedef zypp::Package::constPtr ZyppPackage;
+typedef zypp::Patch::constPtr ZyppPatch;
+typedef zypp::Pattern::constPtr ZyppPattern;
+typedef zypp::Repository ZyppRepository;
+typedef zypp::PoolQuery ZyppQuery;
+typedef zypp::sat::SolvAttr ZyppAttribute;
+typedef zypp::ByteCount Size_t;
+typedef zypp::DiskUsageCounter::MountPoint ZyppDu;
+typedef zypp::DiskUsageCounter::MountPointSet ZyppDuSet;
+
+inline ZyppPackage castZyppPackage (ZyppResObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Package> (obj); }
+inline ZyppPatch castZyppPatch (ZyppResObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Patch> (obj); }
+inline ZyppPattern castZyppPattern (ZyppResObject obj)
+{ return zypp::dynamic_pointer_cast <const zypp::Pattern> (obj); }
+
+namespace Ypp
+{
+ struct List;
+
+ // Repositories setup
+
+ struct Repository {
+ // merges zypp::Repository and zypp::RepoInfo -- the first are
+ // the actual repository structure (which includes only the
+ // enabled ones), the others are from the setup file.
+
+ Repository (zypp::Repository repo);
+ Repository (zypp::RepoInfo repo);
+ std::string name();
+ std::string url();
+ bool enabled();
+ bool isOutdated();
+ bool isSystem();
+
+ bool operator == (const Repository &other) const;
+
+ ZyppRepository &zyppRepo() { return m_repo; }
+
+ private:
+ ZyppRepository m_repo;
+ zypp::RepoInfo m_repo_info;
+ bool m_onlyInfo;
+ };
+
+ void getRepositoryFromAlias (const std::string &alias,
+ std::string &name, std::string &url);
+
+ // Selectable & complementory structs
+
+ struct Version {
+ Version (ZyppResObject zobj);
+
+ int type(); // Ypp::Selectable::Type
+
+ std::string number();
+ std::string arch();
+ Repository repository();
+
+ Size_t size();
+ Size_t downloadSize();
+
+ bool isInstalled();
+ bool toModify();
+
+ bool operator < (Version &other);
+ bool operator > (Version &other);
+ bool operator == (Version &other);
+
+ ZyppResObject zyppObj() { return m_zobj; }
+
+ private:
+ ZyppResObject m_zobj;
+ };
+
+ struct Selectable {
+ enum Type {
+ PACKAGE, PATTERN, LANGUAGE, PATCH, ALL
+ };
+ static zypp::ResKind asKind (Type type);
+ static Type asType (zypp::ResKind kind);
+
+ Selectable (ZyppSelectable sel);
+ Selectable (zypp::Locale locale);
+
+ Type type();
+ std::string name();
+ std::string summary();
+ std::string description (bool as_html);
+
+ bool visible();
+
+ bool isInstalled();
+ bool hasUpgrade();
+ bool isLocked();
+
+ bool toInstall();
+ bool toRemove();
+ bool toModify();
+ bool toModifyAuto();
+
+ void install(); // installs candidate
+ void remove();
+ void undo();
+ void lock (bool lock);
+
+ bool canRemove();
+ bool canLock();
+
+ int totalVersions();
+ Version version (int n);
+
+ bool hasCandidateVersion();
+ Version candidate();
+ void setCandidate (Version &version);
+
+ bool hasInstalledVersion();
+ Version installed();
+ Version anyVersion();
+
+ bool operator == (const Selectable &other) const;
+ bool operator != (const Selectable &other) const;
+
+ ZyppSelectable zyppSel() { return m_sel; }
+ zypp::Locale zyppLocale() { return m_locale; }
+
+ private:
+ Type m_type;
+ ZyppSelectable m_sel;
+ zypp::Locale m_locale;
+ };
+
+ struct Collection {
+ Collection (Selectable &sel);
+ bool contains (Selectable &sel);
+ void stats (int *installed, int *total);
+
+ Ypp::List *getContent(); // cached
+
+ Selectable &asSelectable() { return m_sel; }
+
+ private:
+ Selectable m_sel;
+ };
+
+ struct Package {
+ Package (Selectable &sel);
+ int support();
+ static int supportTotal();
+ static std::string supportSummary (int support);
+ static std::string supportDescription (int support);
+
+ std::string url();
+
+ YPkgGroupEnum group();
+ std::string rpm_group();
+
+ bool isCandidatePatch();
+ Selectable getCandidatePatch();
+
+ private:
+ Selectable m_sel;
+ };
+
+ struct Patch {
+ Patch (Selectable &sel);
+ int priority();
+ static int priorityTotal();
+ static const char *prioritySummary (int priority);
+ static const char *priorityIcon (int priority);
+
+ private:
+ Selectable m_sel;
+ };
+
+ struct SelListener {
+ // a selectable modification has ripple effects; we don't bother
+ // detecting them
+ virtual void selectableModified() = 0;
+ };
+
+ void addSelListener (SelListener *listener);
+ void removeSelListener (SelListener *listener);
+
+ // you shouldn't need to call notifySelModified() directly, but instead call
+ // e.g. runSolver()
+ void notifySelModified();
+
+ struct Problem {
+ std::string description, details;
+ struct Solution {
+ std::string description, details;
+ bool apply;
+ void *impl;
+ };
+ Solution *getSolution (int nb);
+ void *impl;
+ };
+
+ // runSolver() gets called automatically when you install/remove/... a
+ // a package using the Ypp::Selectable API
+ bool runSolver (bool force = false); // returns whether succesful
+ void setEnableSolver (bool enabled); // true by default
+ bool isSolverEnabled();
+ bool showPendingLicenses (Ypp::Selectable::Type type);
+
+ // temporarily suspends run-solver while installing/removing a few packages at a time
+ // -- used by Ypp::List
+ void startTransactions();
+ bool finishTransactions(); // returns return of runSolver()
+
+ struct Interface {
+ virtual bool showLicense (Selectable &sel, const std::string &license) = 0;
+ virtual bool showMessage (Selectable &sel, const std::string &message) = 0;
+ // resolveProblems = false to cancel the action that had that effect
+ virtual bool resolveProblems (const std::list &problems) = 0;
+ };
+
+ void setInterface (Interface *interface);
+ Interface *getInterface();
+
+ // Pool selectables
+
+ struct Match {
+ virtual bool match (Selectable &sel) = 0;
+ virtual ~Match() {}
+ };
+
+ struct StrMatch : public Match {
+ // exclusive match -- zypp only supports or'ed strings
+ // you can combine attributes (inclusive)
+ enum Attribute {
+ NAME = 0x1, SUMMARY = 0x2, DESCRIPTION = 0x4
+ }; // use regular zypp methods for other attributes
+ StrMatch (int attrbs);
+ void add (const std::string &str);
+ virtual bool match (Selectable &sel);
+
+ virtual ~StrMatch();
+ struct Impl;
+ Impl *impl;
+ };
+
+ struct StatusMatch : public Match {
+ enum Status {
+ IS_INSTALLED, NOT_INSTALLED, HAS_UPGRADE, IS_LOCKED, TO_MODIFY
+ };
+ StatusMatch (Status status);
+ virtual bool match (Selectable &sel);
+
+ private: Status m_status;
+ };
+
+ struct PKGroupMatch : public Match {
+ PKGroupMatch (YPkgGroupEnum group);
+ virtual bool match (Selectable &sel);
+
+ private: YPkgGroupEnum m_group;
+ };
+
+ struct RpmGroupMatch : public Match {
+ RpmGroupMatch (const std::string &group);
+ virtual bool match (Selectable &sel);
+
+ private: std::string m_group;
+ };
+
+ struct FromCollectionMatch : public Match {
+ FromCollectionMatch (Collection &col);
+ virtual bool match (Selectable &sel);
+
+ private: Collection m_collection;
+ };
+
+ struct CollectionContainsMatch : public Match {
+ CollectionContainsMatch (Selectable &sel);
+ virtual bool match (Selectable &collection);
+
+ private: Selectable m_contains;
+ };
+
+ struct SupportMatch : public Match {
+ SupportMatch (int n) : m_n (n) {}
+ virtual bool match (Selectable &sel)
+ { return Package (sel).support() == m_n; }
+ private: int m_n;
+ }; // we should replace some of these stuff by generic properties
+
+ struct PriorityMatch : public Match {
+ PriorityMatch (int n) : m_n (n) {}
+ virtual bool match (Selectable &sel)
+ { return Patch (sel).priority() == m_n; }
+ private: int m_n;
+ };
+
+ struct Query {
+ virtual void addCriteria (Match *match) = 0; // to be free'd by Query
+ virtual bool hasNext() = 0;
+ virtual Selectable next() = 0;
+ virtual int guessSize() = 0; // only knows for sure after iterating
+ };
+
+ struct PoolQuery : public Query {
+ PoolQuery (Selectable::Type type); // for languages, use LangQuery
+ ~PoolQuery();
+
+ enum MatchType {
+ CONTAINS, EXACT, GLOB, REGEX
+ };
+ enum StringAttribute {
+ NAME, SUMMARY, DESCRIPTION, FILELIST, PROVIDES, REQUIRES,
+ };
+ void setStringMode (bool caseSensitive, MatchType type);
+ void addStringAttribute (StringAttribute attrb);
+ void addStringOr (const std::string &str);
+
+ void addRepository (Repository &repository);
+
+ virtual void addCriteria (Match *match); // exclusive
+
+ virtual bool hasNext(); // only after setup
+ virtual Selectable next();
+ virtual int guessSize();
+
+ ZyppQuery &zyppQuery();
+ Selectable::Type poolType();
+
+ struct Impl;
+ Impl *impl;
+ private: // prevent copy
+ PoolQuery (const PoolQuery&); PoolQuery &operator= (const PoolQuery&);
+ };
+
+ struct LangQuery : public Query {
+ LangQuery();
+ ~LangQuery();
+
+ virtual void addCriteria (Match *match) {} /* not yet supported */
+ virtual bool hasNext();
+ virtual Selectable next();
+ virtual int guessSize();
+
+ struct Impl;
+ Impl *impl;
+
+ private: // prevent copy
+ LangQuery (const LangQuery&); LangQuery &operator= (const LangQuery&);
+ };
+
+ // Aggregators
+
+ struct List {
+ List (Query &query);
+ List (int reserve);
+ ~List();
+ List clone();
+
+ Selectable &get (int index);
+ int size();
+
+ int count (Match *match);
+ int find (const std::string &name);
+ int find (Selectable &sel);
+
+ void reserve (int size);
+ void append (Selectable sel);
+
+ void install();
+ void remove();
+ void lock (bool lock);
+ void undo();
+
+ enum SortAttribute {
+ IS_INSTALLED_SORT, NAME_SORT, SIZE_SORT, REPOSITORY_SORT, SUPPORT_SORT
+ };
+ void sort (SortAttribute attrb, bool ascendent);
+ void reverse();
+
+ bool operator == (const Ypp::List &other) const;
+ bool operator != (const Ypp::List &other) const;
+
+ struct Impl;
+ Impl *impl;
+ List (const List&); // ref-counted
+ List &operator= (const List&);
+ };
+
+ struct ListProps {
+ ListProps (List &list);
+ ~ListProps();
+
+ bool isInstalled() const;
+ bool isNotInstalled() const;
+ bool hasUpgrade() const;
+ bool toModify() const;
+ bool isLocked() const;
+ bool isUnlocked() const;
+ bool canRemove() const;
+ bool canLock() const;
+
+ int isInstalledNb() const;
+ int isNotInstalledNb() const;
+ int hasUpgradeNb() const;
+ int isLockedNb() const;
+ int toModifyNb() const;
+
+ struct Impl;
+ Impl *impl;
+ private: // prevent copy
+ ListProps (const ListProps&); ListProps &operator= (const ListProps&);
+ };
+
+ // Disk
+
+ std::vector std::string getPartitionList();
+ const ZyppDu getPartition (const std::string &mount_point);
+
+ // Misc utilities
+
+ struct Busy {
+ // pass 0 as size to only show busy cursor
+ Busy (int size);
+ ~Busy();
+ void inc();
+
+ struct Impl;
+ Impl *impl;
+ private: // prevent copy
+ Busy (const Busy&); Busy &operator= (const Busy&);
+ };
+
+ struct BusyListener {
+ virtual void loading (float progress) = 0;
+ };
+
+ void setBusyListener (BusyListener *listener);
+
+ void init(); // ensures the floor is clean
+ void finish(); // ensures the floor is clean
+ bool isModified(); // anything changed?
+};
+
+#endif /*ZYPP_WRAPPER_H*/
+
Added: branches/SuSE-Code-11-SP2-Branch/gtk/src/test.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/SuSE-Code-11-SP2-Branch/gtk/src/test.cc?rev=65095&view=auto
==============================================================================
--- branches/SuSE-Code-11-SP2-Branch/gtk/src/test.cc (added)
+++ branches/SuSE-Code-11-SP2-Branch/gtk/src/test.cc Mon Aug 1 09:44:45 2011
@@ -0,0 +1,235 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#define YUILogComponent "gtk"
+#include "config.h"
+#include
+#include
+#include
+#include
+#include "YGUtils.h"
+
+bool testMapKBAccel()
+{
+ fprintf (stderr, "Test map KB accels\t");
+ struct {
+ const char *in;
+ const char *out;
+ } aTests[] = {
+ { "Foo&", "Foo_" },
+ { "B&aa", "B_aa" },
+ { "&Foo", "_Foo" },
+ { "_Foo", "__Foo" },
+// FIXME - unfortunately it seems yast has noescaping policy
+// for labels (hmm) at least judging from the code at
+// ncurses/src/NCstring.cc (getHotKey)
+// { "&&Foo", "&Foo" },
+ { NULL, NULL }
+ };
+ for (int i = 0; aTests[i].in; i++) {
+ string mapped = YGUtils::mapKBAccel(aTests[i].in);
+ if (mapped != aTests[i].out) {
+ fprintf (stderr, "Mis-mapped accel '%s' vs '%s'\n",
+ mapped.c_str(), aTests[i].out);
+ return false;
+ }
+ fprintf (stderr, "%d ", i);
+ }
+ fprintf (stderr, "\n");
+ return true;
+}
+
+#include "ygtkrichtext.h"
+
+bool testParse(const char *xml)
+{
+ GError *error = NULL;
+ GMarkupParser parser = { 0, };
+ GMarkupParseContext *ctx = g_markup_parse_context_new (&parser, GMarkupParseFlags (0), NULL, NULL);
+
+ if (!g_markup_parse_context_parse (ctx, xml, -1, &error))
+ {
+ fprintf (stderr, "Invalid XML: '%s'\n '%s'\n", xml, error->message);
+ return false;
+ }
+ g_markup_parse_context_free (ctx);
+
+ return true;
+}
+
+bool testXHtmlConvert()
+{
+ fprintf (stderr, "Test HTML->XML rewrite \t");
+ struct {
+ const char *in;
+ const char *out;
+ } aTests[] = {
+ // preservation
+ { "<p>foo</p>", "<body><p>foo</p></body>" },
+ // outer tag
+ { "some text", "<body>some text</body>" },
+ // unquoted attributes
+ { "<foo baa=Baz></foo>", "<body></foo></body>" },
+ // break tags
+ { "<br>", "<body><br/></body>" },
+ { "<hr>", "<body><hr/></body>" },
+ // close with different case ...
+ { "<p>Foo</P>", "<body><p>Foo</p></body>" },
+ // unclosed tags
+ { "<p>", "<body><p></p></body>" },
+ { "<b>unclosed", "<body><b>unclosed</b></body>" },
+ { "<b><i>bold</i>", "<body><b><i>bold</i></b></body>" },
+ { "<i><i>bold</i>", "<body><i><i>bold</i></i></body>" },
+ { "<unclosed foo=baa>",
+ "<body>