YaST Commits
Threads by month
- ----- 2024 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
November 2007
- 24 participants
- 864 discussions
Author: rpmcruz
Date: Thu Nov 29 18:26:13 2007
New Revision: 42516
URL: http://svn.opensuse.org/viewcvs/yast?rev=42516&view=rev
Log:
Branching.
Removed:
trunk/gtk/head/
--
To unsubscribe, e-mail: yast-commit+unsubscribe(a)opensuse.org
For additional commands, e-mail: yast-commit+help(a)opensuse.org
1
0
[yast-commit] r42515 - in /trunk/gtk: ./ integrate/ package/ src/ tests/ ycc/
by rpmcruz@svn.opensuse.org 29 Nov '07
by rpmcruz@svn.opensuse.org 29 Nov '07
29 Nov '07
Author: rpmcruz
Date: Thu Nov 29 18:25:41 2007
New Revision: 42515
URL: http://svn.opensuse.org/viewcvs/yast?rev=42515&view=rev
Log:
Branching.
Added:
trunk/gtk/HACKING
trunk/gtk/MAINTAINER
trunk/gtk/Makefile.cvs
trunk/gtk/NEWS
trunk/gtk/POTFILES
trunk/gtk/README
trunk/gtk/RPMNAME
trunk/gtk/SUBDIRS
trunk/gtk/TODO
trunk/gtk/VERSION
trunk/gtk/autogen.sh (with props)
trunk/gtk/configure.in.in
trunk/gtk/gtkize-iso (with props)
trunk/gtk/integrate/
trunk/gtk/integrate/YaST2.call
trunk/gtk/integrate/yast2 (with props)
trunk/gtk/integrate/yast2-funcs
trunk/gtk/package/
trunk/gtk/package/yast2-gtk-rpmlintrc
trunk/gtk/package/yast2-gtk.changes
trunk/gtk/src/
trunk/gtk/src/.cvsignore
trunk/gtk/src/Makefile.am
trunk/gtk/src/Y2CCGtk.cc
trunk/gtk/src/YGBarGraph.cc
trunk/gtk/src/YGComboBox.cc
trunk/gtk/src/YGDialog.cc
trunk/gtk/src/YGDialog.h
trunk/gtk/src/YGDumbTab.cc
trunk/gtk/src/YGFrame.cc
trunk/gtk/src/YGImage.cc
trunk/gtk/src/YGIntField.cc
trunk/gtk/src/YGLabel.cc
trunk/gtk/src/YGLayout.cc
trunk/gtk/src/YGMenuButton.cc
trunk/gtk/src/YGMultiLineEdit.cc
trunk/gtk/src/YGPackageSelector.cc
trunk/gtk/src/YGProgressBar.cc
trunk/gtk/src/YGPushButton.cc
trunk/gtk/src/YGRadioButton.cc
trunk/gtk/src/YGTable.cc
trunk/gtk/src/YGTextEntry.cc
trunk/gtk/src/YGTime.cc
trunk/gtk/src/YGTree.cc
trunk/gtk/src/YGUI.cc
trunk/gtk/src/YGUI.h
trunk/gtk/src/YGUtils.cc
trunk/gtk/src/YGUtils.h
trunk/gtk/src/YGWidget.cc
trunk/gtk/src/YGWidget.h
trunk/gtk/src/YGWizard.cc
trunk/gtk/src/YGi18n.h
trunk/gtk/src/computer.xpm
trunk/gtk/src/dummy.cc
trunk/gtk/src/test.cc
trunk/gtk/src/ygdkmngloader.c
trunk/gtk/src/ygdkmngloader.h
trunk/gtk/src/ygtkbargraph.c
trunk/gtk/src/ygtkbargraph.h
trunk/gtk/src/ygtkcellrendererarrow.c
trunk/gtk/src/ygtkcellrendererarrow.h
trunk/gtk/src/ygtkfieldentry.c
trunk/gtk/src/ygtkfieldentry.h
trunk/gtk/src/ygtkfindentry.c
trunk/gtk/src/ygtkfindentry.h
trunk/gtk/src/ygtkhtmlwrap.c
trunk/gtk/src/ygtkhtmlwrap.h
trunk/gtk/src/ygtkmenubutton.c
trunk/gtk/src/ygtkmenubutton.h
trunk/gtk/src/ygtkratiobox.c
trunk/gtk/src/ygtkratiobox.h
trunk/gtk/src/ygtkrichtext.c
trunk/gtk/src/ygtkrichtext.h
trunk/gtk/src/ygtksteps.c
trunk/gtk/src/ygtksteps.h
trunk/gtk/src/ygtkwizard.c
trunk/gtk/src/ygtkwizard.h
trunk/gtk/test.sh (with props)
trunk/gtk/tests/
trunk/gtk/tests/Cursor.ycp
trunk/gtk/tests/FileDialog.ycp
trunk/gtk/tests/Frame.ycp
trunk/gtk/tests/IconButton.ycp (with props)
trunk/gtk/tests/IconItems-ComboBox.ycp (with props)
trunk/gtk/tests/IconItems-MultiSelectionBox.ycp (with props)
trunk/gtk/tests/IconItems-SelectionBox.ycp (with props)
trunk/gtk/tests/Image.ycp
trunk/gtk/tests/ImageMng.ycp
trunk/gtk/tests/Layout-Align-Weight.ycp (with props)
trunk/gtk/tests/Layout-AlignStretch.ycp
trunk/gtk/tests/Layout-Expand.ycp (with props)
trunk/gtk/tests/Layout-Frame2.ycp (with props)
trunk/gtk/tests/Layout-HVCenter-Align.ycp (with props)
trunk/gtk/tests/Layout-ReplacePoint.ycp (with props)
trunk/gtk/tests/Layout-Split-Split.ycp (with props)
trunk/gtk/tests/Layout-Truncated-Widget.ycp (with props)
trunk/gtk/tests/Layout-Wizard-BackgroundWidget.ycp (with props)
trunk/gtk/tests/Layout-Wizard-OneWidget.ycp (with props)
trunk/gtk/tests/Layout-Wizard3.ycp (with props)
trunk/gtk/tests/MainDialogs.ycp
trunk/gtk/tests/MultiProgressMeterHuge.ycp
trunk/gtk/tests/MultiProgressMeterVer.ycp
trunk/gtk/tests/MultiSelectionBox.ycp
trunk/gtk/tests/PollInput.ycp
trunk/gtk/tests/ProgressPulse.ycp
trunk/gtk/tests/RichText1.ycp
trunk/gtk/tests/RichText2.ycp
trunk/gtk/tests/SelectionBox.ycp (with props)
trunk/gtk/tests/StockIcons.ycp
trunk/gtk/tests/Table3-4.ycp (with props)
trunk/gtk/tests/Tree3.ycp
trunk/gtk/tests/WizardList.ycp
trunk/gtk/tests/image.gif (with props)
trunk/gtk/tests/movie1.mng (with props)
trunk/gtk/tests/movie2.mng (with props)
trunk/gtk/tests/movie3.mng (with props)
trunk/gtk/tests/movie4.mng (with props)
trunk/gtk/tests/movie5.mng (with props)
trunk/gtk/tests/movie6.mng (with props)
trunk/gtk/tests/movie7.mng (with props)
trunk/gtk/tests/movie8.mng (with props)
trunk/gtk/yast2-gtk.spec.in
trunk/gtk/ycc/
trunk/gtk/ycc.sh (with props)
trunk/gtk/ycc/Makefile
trunk/gtk/ycc/ycc.cpp
Added: trunk/gtk/HACKING
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/HACKING?rev=42515&view=auto
==============================================================================
--- trunk/gtk/HACKING (added)
+++ trunk/gtk/HACKING Thu Nov 29 18:25:41 2007
@@ -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 identations, 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: trunk/gtk/MAINTAINER
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/MAINTAINER?rev=42515&view=au…
==============================================================================
--- trunk/gtk/MAINTAINER (added)
+++ trunk/gtk/MAINTAINER Thu Nov 29 18:25:41 2007
@@ -0,0 +1,2 @@
+Ricardo Cruz <rpmcruz(a)alunos.dcc.fc.up.pt> \
+Michael Meeks <michael.meeks(a)novell.com>
Added: trunk/gtk/Makefile.cvs
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/Makefile.cvs?rev=42515&view=…
==============================================================================
--- trunk/gtk/Makefile.cvs (added)
+++ trunk/gtk/Makefile.cvs Thu Nov 29 18:25:41 2007
@@ -0,0 +1,23 @@
+#
+# Makefile.cvs
+#
+
+LIB = $(shell y2tool get-lib)
+
+PREFIX = /usr
+
+configure: all
+ ./configure --prefix=$(PREFIX) --libdir=$(PREFIX)/$(LIB)
+
+all:
+ y2tool y2autoconf
+ y2tool y2automake
+ autoreconf --force --install
+
+install: configure
+ make
+ make install
+
+reconf: all
+ ./config.status --recheck
+ ./config.status
Added: trunk/gtk/NEWS
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/NEWS?rev=42515&view=auto
==============================================================================
--- trunk/gtk/NEWS (added)
+++ trunk/gtk/NEWS Thu Nov 29 18:25:41 2007
@@ -0,0 +1 @@
+No news yet.
\ No newline at end of file
Added: trunk/gtk/POTFILES
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/POTFILES?rev=42515&view=auto
==============================================================================
(empty)
Added: trunk/gtk/README
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/README?rev=42515&view=auto
==============================================================================
--- trunk/gtk/README (added)
+++ trunk/gtk/README Thu Nov 29 18:25:41 2007
@@ -0,0 +1,47 @@
+/* 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):
+
+ yast2-devel yast2-devtools yast2-core-devel libzypp libzypp-devel
+ gettext-devel
+
+ They all are distributed with Suse's CDs.
+
+Building / Installing
+
+ make -f Makefile.cvs
+ 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
+
+ In order to fire up YaST modules, run the ycc.sh script.
+ (You'll need the zenity package installed.)
+
+ 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
Added: trunk/gtk/RPMNAME
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/RPMNAME?rev=42515&view=auto
==============================================================================
--- trunk/gtk/RPMNAME (added)
+++ trunk/gtk/RPMNAME Thu Nov 29 18:25:41 2007
@@ -0,0 +1 @@
+yast2-gtk
Added: trunk/gtk/SUBDIRS
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/SUBDIRS?rev=42515&view=auto
==============================================================================
--- trunk/gtk/SUBDIRS (added)
+++ trunk/gtk/SUBDIRS Thu Nov 29 18:25:41 2007
@@ -0,0 +1 @@
+src
Added: trunk/gtk/TODO
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/TODO?rev=42515&view=auto
==============================================================================
--- trunk/gtk/TODO (added)
+++ trunk/gtk/TODO Thu Nov 29 18:25:41 2007
@@ -0,0 +1,66 @@
+/* List of missing features, actual bugs and other issues */
+
+= Regression testing =
+
+* Setup LDTP to run through all the tests/ and provoke as many
+ code-paths as possible
+
+= Look and feel =
+
+* YGtkWizard: navigation bar (see sysconfig module) should be GtkPaned.
+
+* YGtkWizard: support for skin -- some mockups under mockups/.
+
+* YGBarGraph / RatioBox: let tiny widgets still have some pixels visible
+ for popup menu.
+
+* YGRichText: should use GtkHtml when available, so that we get support for
+ tables.
+
+* RatioBox: Our buttons are too big in some dialogs (eg. run disk.ycp as user).
+ Check where our algorithm differs from yast-core's.
+
+* YGTextEntry / YGMultiLineEdit: Add undo/redo support. The backend code should
+ be shared. We probably want to make an interface for it that is then implemented
+ by those two GTK widgets. Work out a patch for GTK+.
+
+= Package Selector =
+(this little monster diserves a section of its own. =))
+
+* Patch selector (YOU)
+ + we should also list installed patches and maybe a way to remove them
+ (downgrade of version should work for most cases -- check how qt does it).
+ Probably a tab for this?
+
+* Translation support (i18n -- pot files -- gettext!).
+
+* Search syntax: add proper Google syntax support. Consider also adding regex
+ support when Glib ships with it (add radio boxes to entry's context menu).
+
+* Re-work Yast face to Jakub's suggestion; make it configurable.
+
+* We need an easter-egg! :)
+
+= Internal affairs =
+
+* IntField / Slider
+ o to consider: only report value change when the widget is stalled.
+ To use g_idle functionality.
+
+= Yast-Core =
+
+* Stock images for wizard
+ Already patched stock icons supports for regular button (even if not
+ currently being used), but not for wizard ones.
+
+* Button order
+ Should be possible to specify button order. eg: [Ok] [Cancel] vs [Cancel] [Ok]
+ We could hack this through if we had stock images support (may depend
+ on the way they are implemented).
+
+
+** Performance of yast2 package selector:
+ + 95% of the time is spent in zypper,
+ + the filter models (etc.) are doing a fairly good job
+ + unfortunately fetching 'summary' and 'description' is painfully slow
+ + accelerated summary with a hash/cache.
Added: trunk/gtk/VERSION
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/VERSION?rev=42515&view=auto
==============================================================================
--- trunk/gtk/VERSION (added)
+++ trunk/gtk/VERSION Thu Nov 29 18:25:41 2007
@@ -0,0 +1 @@
+2.15.9
Added: trunk/gtk/autogen.sh
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/autogen.sh?rev=42515&view=au…
==============================================================================
--- trunk/gtk/autogen.sh (added)
+++ trunk/gtk/autogen.sh Thu Nov 29 18:25:41 2007
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+echo
+echo "--------------------------------------------------------"
+echo "Warning: please use '$ make -f Makefile.cvs' instead ..."
+echo "--------------------------------------------------------"
+echo
+make -f Makefile.cvs
\ No newline at end of file
Added: trunk/gtk/configure.in.in
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/configure.in.in?rev=42515&vi…
==============================================================================
--- trunk/gtk/configure.in.in (added)
+++ trunk/gtk/configure.in.in Thu Nov 29 18:25:41 2007
@@ -0,0 +1,80 @@
+## custom configure.in.in
+
+## initialize
+@YAST2-INIT-COMMON@
+@YAST2-INIT-PROGRAM@
+
+## some common checks
+@YAST2-CHECKS-COMMON@
+@YAST2-CHECKS-PROGRAM@
+
+dnl AC_MSG_CHECKING(prefix)
+dnl if test "z${prefix}" != "z/usr"; then
+dnl AC_MSG_ERROR(["Only the /usr prefix is supported, sorry. cf. README"])
+dnl fi
+dnl AC_MSG_RESULT(/usr - good)
+
+dnl pkgconfig
+AC_ARG_VAR([PKG_CONFIG_PATH], [where to search for pkg-config files])
+dnl devtools
+dnl ...
+AC_PATH_PROG(PKG_CONFIG, pkg-config)
+if test ! -x "$PKG_CONFIG" ; then
+ AC_MSG_ERROR([
+*** You need the latest pkg-config.
+*** Get the latest version of pkg-config from
+*** <http://www.freedesktop.org/software/pkgconfig/>.])
+fi
+AC_SUBST(PKG_CONFIG)
+
+
+AC_FUNC_ALLOCA
+AC_HEADER_STDC
+
+dnl Try to find the Zypp includes
+AC_MSG_CHECKING([for zypp 3])
+if test -f /usr/include/zypp/SourceManager.h; then
+ AC_DEFINE(PRE_ZYPP_3, 1, [defined if using an older SL10.1 era zypp])
+ AC_MSG_RESULT([pre 3])
+else
+ AC_MSG_RESULT([found])
+fi
+
+PKG_CHECK_MODULES( ZYPP, libzypp )
+AC_SUBST(ZYPP_LIBS)
+
+PKG_CHECK_MODULES( GTK, gtk+-2.0 glib-2.0 gthread-2.0 gobject-2.0 )
+AC_SUBST(GTK_CFLAGS)
+AC_SUBST(GTK_LIBS)
+
+# TODO: we may want to check if GtkHtml is installed and set its flag
+#dnl Check if GtkHtml is installed
+#AC_MSG_CHECKING([for gtkhtml])
+#PKG_CHECK_MODULES( GTKHTML, libgtkhtml-3.14 )
+#AC_SUBST(GTKHTML_CFLAGS)
+#AC_SUBST(GTKHTML_LIBS)
+#AC_DEFINE(USE_GTKHTML, 1, [will use GtkHtml as the HTML renderer])
+
+PKG_CHECK_MODULES( ZYPP, libzypp )
+AC_SUBST(ZYPP_LIBS)
+
+verstxt=`pkg-config --modversion yast2-core`
+yast_vers=`echo "$verstxt" | awk -F. '{ printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+AC_DEFINE_UNQUOTED(YAST2_VERSION, $yast_vers, [yast version for compile conditionals])
+
+dnl new UI library
+AC_MSG_CHECKING([for old libyui])
+PYUI_LIBS='-lpy2UI'
+if test $yast_vers -le 2015006; then
+ PYUI_LIBS='-lyui'
+ AC_MSG_RESULT([found])
+else
+ AC_MSG_RESULT([use new lib])
+fi
+AC_SUBST(PYUI_LIBS)
+
+AC_OUTPUT([Makefile src/Makefile])
+
+echo "
+Hello hacker: please read the README carefully while this builds.
+"
Added: trunk/gtk/gtkize-iso
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/gtkize-iso?rev=42515&view=au…
==============================================================================
--- trunk/gtk/gtkize-iso (added)
+++ trunk/gtk/gtkize-iso Thu Nov 29 18:25:41 2007
@@ -0,0 +1,145 @@
+#!/bin/sh
+
+SUDO=sudo
+MOUNTBASE=/data/tmp
+rootimage=/boot/i386/root
+srcfiles=/opt/yast/public/gtk
+
+copy_file()
+{
+ $SUDO mkdir -p "$1/$2"
+ $SUDO cp -a "$2/$3" "$1/$2"
+}
+
+rewrite()
+{
+ dir=$1
+ yastlib="$dir/usr/lib/YaST2"
+ yastshare="$dir/usr/share/YaST2"
+ echo "Re-writing $1"
+ echo -n " pruning qt..."
+ $SUDO cp -f "$srcfiles/integrate/YaST2.call" \
+ "$yastlib/startup"
+#debugging
+ $SUDO cp -f "$srcfiles/integrate/YaST2.Second-Stage" \
+ "$yastlib/startup"
+ $SUDO cp -f "$srcfiles/integrate/logging.sh" \
+ "$yastlib/startup/common"
+#/debugging
+ $SUDO rm -f "$yastshare/locale/*/LC_MESSAGES/packages-qt.mo"
+ $SUDO rm -f "$yastdir/plugin/libpy2qt*"
+ $SUDO rm -Rf "$dir/usr/lib/qt3"
+ $SUDO rm -f "$dir/usr/lib/libqt-mt*"
+ echo " done"
+
+ echo -n " installing gtk..."
+ $SUDO cp -a /usr/lib/YaST2/plugin/libpy2gtk* "$yastlib/plugin"
+ echo " done"
+
+ # gnome libs
+ for lib in libgtk-x11-2.0.so.0 libgdk-x11-2.0.so.0 libatk-1.0.so.0 libgdk_pixbuf-2.0.so.0 libpangocairo-1.0.so.0 libpango-1.0.so.0 libgmodule-2.0.so.0 libgthread-2.0.so.0 libpangoft2-1.0.so.0; do
+ $SUDO cp -a /opt/gnome/lib/$lib* "$dir/opt/gnome/lib"
+ $SUDO strip $dir/opt/gnome/lib/$lib*
+ done
+
+ # system libs
+ # FIXME - if for same system, use same libzypp ...
+ for lib in libcairo.so.2 libglitz.so.1 libdbus-1.so.2 libzypp.so.1; do
+ $SUDO cp -a /usr/lib/$lib* "$dir/usr/lib"
+ $SUDO strip $dir/usr/lib/$lib*
+ done
+
+ # pango modules
+ copy_file $dir "/opt/gnome/lib/pango/1.4.0/modules" "pango-basic-fc.so"
+ copy_file $dir "/opt/gnome/lib/pango/1.4.0/modules" "pango-indic-fc.so"
+ copy_file $dir "/opt/gnome/lib/pango/1.4.0/modules" "pango-arabic-fc.so"
+ # generate config ...
+ PANGORC=`mktemp $MOUNTBASE/ygtk-pangorc.XXXXXX`
+ PANGO_MODULES=`mktemp $MOUNTBASE/ygtk-modules.XXXXXX`
+echo "[Pango]
+ModulesPath=$dir/opt/gnome/lib/pango/1.4.0/modules
+" > $PANGORC
+ PANGO_RC_FILE=$PANGORC pango-querymodules | sed "s|$dir||g" > $PANGO_MODULES
+ $SUDO mkdir -p "$dir/etc/opt/gnome/pango"
+ $SUDO mv $PANGO_MODULES "$dir/etc/opt/gnome/pango/pango.modules"
+ rm -f $PANGORC
+
+ echo " testing..."
+ if LD_LIBRARY_PATH="$dir/lib:$dir/usr/lib:$dir/opt/gnome/lib" ldd $yastlib/plugin/libpy2gtk.so > /dev/null; then
+ echo "warning: failed to link";
+ fi
+}
+
+printhelp()
+{
+ echo "Usage: $0 [OPTIONS] <source-ISO> <dest-ISO>"
+ echo
+ echo "OPTIONS:"
+ echo " -h, --help: help";
+ echo
+}
+
+if (test "z$1" = 'z-h') || (test "z$1" = 'z--help'); then
+ printhelp; exit 0;
+fi
+
+source=$1
+dest=$2
+
+if (test "z$source" = "z") || (test "z$dest" = "z"); then
+ printhelp; exit 1;
+fi
+
+mkcramfs=`which mkcramfs 2>/dev/null`
+if (test "z$mkcramfs" = "z") || (! test -x $mkcramfs); then
+ echo "Must have cramfs installed."
+ exit 1;
+fi
+
+echo "copy from $source $dest";
+
+ISODIR=`mktemp -d $MOUNTBASE/ygtk-iso.XXXXXX`
+$SUDO mount -o loop $source $ISODIR
+echo "Mounted $source"
+
+ROOTDIR=`mktemp -d $MOUNTBASE/ygtk-oldroot.XXXXXX`
+$SUDO mount -o loop "$ISODIR$rootimage" $ROOTDIR
+echo "Mounted old root"
+
+NEWROOT=`mktemp -d $MOUNTBASE/ygtk-newroot.XXXXXX`
+echo "Creating new root at $NEWROOT"
+echo -n " copying..."
+# do this to preserve hard links
+$SUDO tar -C $ROOTDIR -O -c . | $SUDO tar -x -C $NEWROOT >& /dev/null
+echo " done"
+$SUDO umount $ROOTDIR
+rmdir $ROOTDIR
+
+# Do the interesting work ...
+rewrite $NEWROOT
+# End of interesting work ...
+
+echo -n "Compressing image..."
+NEWROOTFS=`mktemp $MOUNTBASE/ygtk-cramfs.XXXXXX`
+$SUDO $mkcramfs $NEWROOT $NEWROOTFS
+echo " done"
+
+echo -n "Creating new CD image..."
+NEWIMAGE=`mktemp -d $MOUNTBASE/ygtk-newimage.XXXXXX`
+$SUDO cp -a $ISODIR/* $NEWIMAGE
+$SUDO cp -a $NEWROOTFS "$NEWIMAGE$rootimage"
+$SUDO umount $ISODIR
+rmdir $ISODIR
+echo " done"
+
+cd $NEWIMAGE ; $SUDO mkisofs -p "Yast-GTK installer" -publisher "Fools, Inc." \
+ -r -J -f -pad -no-emul-boot -boot-load-size 4 -boot-info-table \
+ -b boot/i386/loader/isolinux.bin -c boot/i386/boot.catalog -hide \
+ boot/i386/boot.catalog -hide-joliet boot/i386/boot.catalog -A \
+ "SUSE-Yast-GTK#0" -V SU1010.001 -o $dest .
+
+echo "Done new iso in $dest."
+echo -n "Cleaning up..."
+$SUDO rm -Rf $NEWROOTFS
+$SUDO rm -Rf $NEWIMAGE
+echo " done."
Added: trunk/gtk/integrate/YaST2.call
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/integrate/YaST2.call?rev=425…
==============================================================================
--- trunk/gtk/integrate/YaST2.call (added)
+++ trunk/gtk/integrate/YaST2.call Thu Nov 29 18:25:41 2007
@@ -0,0 +1,779 @@
+#!/bin/sh
+#================
+# FILE : YaST2.call
+#----------------
+# PROJECT : YaST (Yet another Setup Tool v2)
+# COPYRIGHT : (c) 2004 SUSE Linux AG, Germany. All rights reserved
+# :
+# AUTHORS : Steffen Winterfeldt <snwint(a)suse.de>
+# . Arvin Schnell <arvin(a)suse.de>
+# : Marcus Schaefer <ms(a)suse.de>
+# :
+# BELONGS TO : System installation and Administration
+# :
+# DESCRIPTION : This is the main script to start the YaST2 installer
+# : according to the possible installation environments
+# : These are:
+# : ---
+# : - Standard Installation Qt/X11 or text based
+# : - Via serial line ttyS0/115200 baud, 8N1, RTS/CTS
+# : which is the same as the NCURSES mode
+# : - VNC Installation via browser
+# :
+# :
+# STATUS : $Id: YaST2.call 32688 2006-09-04 14:05:17Z locilka $
+#----------------
+#
+#set -x
+
+. /etc/YaST2/XVersion
+
+#=============================================
+# Functions...
+#---------------------------------------------
+#----[ wait_for_x11 ]----#
+function wait_for_x11() {
+#------------------------------------------------------
+# after a X-Server has been started you can wait until
+# the server is ready for requests using this function
+# ---
+ server_running=0
+ TESTX=/usr/sbin/testX
+ while kill -0 $xserver_pid 2>/dev/null ; do
+ sleep 1
+ if test -e /tmp/.X11-unix/X0 && test -x $TESTX ; then
+ $TESTX "$YaST2color" 2>/dev/null
+ err=$?
+ # exit code 1 -> XOpenDisplay failed...
+ if test $err = 1;then
+ log "\tTestX: XOpenDisplay failed"
+ server_running=0
+ continue
+ fi
+ # exit code 2 -> color or dimensions doesn't fit...
+ if test $err = 2;then
+ log "\tTestX: color or dimensions doesn't fit"
+ kill $xserver_pid
+ server_running=0
+ break;
+ fi
+ server_running=1
+ break
+ fi
+ done
+}
+
+#----[ get_bus_id ]----#
+function get_bus_id () {
+#------------------------------------------------------
+# ask the PCi bus for the location of the first
+# graphics card.
+# ---
+ for line in $(/sbin/lspci -n | grep "Class 0300" | cut -f 1 -d " ");do
+ echo $line |\
+ grep -q -E "^[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]"
+ if [ $? = 0 ];then
+ PCIBus=$(echo $line | cut -f1 -d:);
+ PCISlot=$(echo $line | cut -f2 -d: | cut -f 1 -d.);
+ PCIFunc=$(echo $line | cut -f2 -d.);
+ log "\tFound standard BusID: $PCIBus:$PCISlot:$PCIFunc"
+ printf "PCI:%d@0:%d:%d" \
+ 0x$PCIBus 0x$PCISlot 0x$PCIFunc
+ break
+ else
+ echo $line |\
+ grep -q -E "^[0-9a-f]{4}:[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]"
+ if [ $? = 0 ];then
+ PCIDomain=$(echo $line | cut -f1 -d:);
+ PCIBus=$(echo $line | cut -f2 -d:);
+ PCISlot=$(echo $line | cut -f3 -d: | cut -f 1 -d.);
+ PCIFunc=$(echo $line | cut -f2 -d.);
+ log "\tFound domain BusID: $PCIBus@$PCIDomain:$PCISlot $PCIFunc"
+ printf "PCI:%d@%d:%d:%d" \
+ 0x$PCIBus 0x$PCIDomain 0x$PCISlot 0x$PCIFunc
+ break
+ fi
+ fi
+ done
+}
+
+#----[ count_qt_geometry ]----#
+function count_qt_geometry () {
+ # current X-resolution, display 0
+ XRES=$(/usr/sbin/xquery -d :0 -r)
+
+ log "\t===Qt Geometry==="
+ log "\tResolution: ${XRES}"
+
+ # current X and Y resolution
+ XRES_X=$(echo $XRES | sed 's|[0123456789]\+ \([0123456789]\+\)x[0123456789]\+|\1|') #'
+ XRES_Y=$(echo $XRES | sed 's|[0123456789]\+ [0123456789]\+x\([0123456789]\+\)|\1|') #'
+
+ log "\tX: ${XRES_X}"
+ log "\tY: ${XRES_Y}"
+
+ # default values, minimal window 640x480
+ WINDOW_SIZE_X=640
+ WINDOW_SIZE_Y=480
+ OFFSET_X=0
+ OFFSET_Y=0
+ BACKGROUND_IMAGE=""
+
+ # cannot get any X-resolution
+ if [ "${XRES}" == "" ]; then
+ # cannot find out X resolution
+ WINDOW_SIZE_X=800
+ WINDOW_SIZE_Y=600
+ # reasonable
+ else
+ # FIXME: recount background image
+ BACKGROUND_IMAGE="/usr/lib/YaST2/startup/bkg.png"
+
+ # must be bigger or equal to 1400x1050
+ if [ "$(expr $XRES_X \>= 1400)" == "1" ] && [ "$(expr $XRES_Y \>= 1050)" == "1" ]; then
+ WINDOW_SIZE_X=1024
+ WINDOW_SIZE_Y=786
+ # must be bigger or equal to 800x600
+ elif [ "$(expr $XRES_X \>= 800)" == "1" ] && [ "$(expr $XRES_Y \>= 600)" == "1" ]; then
+ WINDOW_SIZE_X=800
+ WINDOW_SIZE_Y=600
+ fi
+
+ # X and Y offsets
+ OFFSET_X=$(expr ${XRES_X} - ${WINDOW_SIZE_X})
+ OFFSET_X=$(expr ${OFFSET_X} / 2)
+ OFFSET_Y=$(expr ${XRES_Y} - ${WINDOW_SIZE_Y})
+ OFFSET_Y=$(expr ${OFFSET_Y} / 2)
+ fi
+
+ log "\tWindow size X: ${WINDOW_SIZE_X}"
+ log "\tWindow size X: ${WINDOW_SIZE_Y}"
+ log "\tOffset X: ${OFFSET_X}"
+ log "\tOffset X: ${OFFSET_Y}"
+
+ # final window geometry, 'Window_XxWindow_Y+Offset_X+Offset_Y'
+ X_GEOMETRY="${WINDOW_SIZE_X}x${WINDOW_SIZE_Y}+${OFFSET_X}+${OFFSET_Y}"
+
+ log "\tUsed geometry: ${X_GEOMETRY}"
+}
+
+#----[ prepare_for_qt ]----#
+function prepare_for_qt () {
+#------------------------------------------------------
+# prepare Qt installation
+# ---
+ export LD_LIBRARY_PATH="/opt/gnome/lib:$LD_LIBRARY_PATH"
+
+ #=============================================
+ # Setup Qt environment
+ #---------------------------------------------
+ set_inst_qt_env
+ set_splash 100
+
+ #=============================================
+ # patch X11 conf. if not update/continue mode
+ #---------------------------------------------
+ if [ ! -f /var/lib/YaST2/runme_at_boot ];then
+ if [ ! -f /etc/X11/xorg.conf.instorig ];then
+ # create backup copy...
+ cp /etc/X11/xorg.conf /etc/X11/xorg.conf.instorig
+
+ # Activate correct device/screen section...
+ sed -e "s#Screen.*Screen\[.*\]#Screen "\""Screen[$X11_CONFIG_ID]#" \
+ /etc/X11/xorg.conf >/etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+
+ # update core pointer input device section...
+ if [ -f "/usr/sbin/xupdate" ];then
+ cat /etc/X11/xorg.conf | \
+ /usr/sbin/xupdate > /etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+ fi
+
+ # update driver and busID if accelerated driver should be used...
+ if [ "$X11_CONFIG_ID" = 0 ];then
+ # replace BusID placeholder with real busID
+ XBusID=$(get_bus_id)
+ if [ ! -z "$XBusID" ];then
+ sed -e 's/#BusID/BusID/' \
+ -e "s#1:0:0#$XBusID#" /etc/X11/xorg.conf \
+ > /etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+ fi
+
+ # replace driver placeholder with real name
+ sed -e "s#ChangeMe#$XServer#" /etc/X11/xorg.conf \
+ > /etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+ fi
+ fi
+ fi
+ #=============================================
+ # start X-Server and wait until ready
+ #---------------------------------------------
+ if [ ! -z "$NEED_XSERVER" ];then
+ export DISPLAY=:0
+ [ -z $Xstartpath ] || ln -snf $Xbindir/XFree86 /var/X11R6/bin/X
+ $Xexecutable -deferglyphs 16 2>/dev/tty8 1>&2 vt07 &
+ xserver_pid=$!
+ wait_for_x11
+ if [ "$server_running" = 1 ];then
+ log "\tX-Server is ready: $xserver_pid"
+ fi
+ fi
+ #=============================================
+ # set YaST2 Qt options for local displays
+ #---------------------------------------------
+ if [ ! -z "$NEED_XSERVER" ];then
+ Y2_UI_ARGS="--noborder --auto-fonts"
+ count_qt_geometry
+ if [ "${X_GEOMETRY}" != "" ]; then
+ Y2_UI_ARGS="${Y2_UI_ARGS} -geometry ${X_GEOMETRY}"
+ fi
+ fi
+}
+
+#----[ prepare_for_ncurses ]----#
+function prepare_for_ncurses () {
+#------------------------------------------------------
+# prepare NCURSES installation
+# ---
+ #=============================================
+ # Create Braille config if not update mode
+ #---------------------------------------------
+ if [ $INST_MODE = "normal" ];then
+ if [ ! -z "$Braille" ];then
+ log "Braille config needed, setting up braille display"
+ sed -e "s#brlname=.*#brlname=$Braille#" \
+ -e "s#brlport=.*#brlport=$Brailledevice#" /etc/suse-blinux.conf \
+ >/tmp/suse-blinux.conf
+ mv -f /tmp/suse-blinux.conf /etc
+ /etc/init.d/suse-blinux start
+ fi
+ fi
+ #=============================================
+ # Check for FbIterm
+ #---------------------------------------------
+ check_run_fbiterm
+ log "\tCheck for FB-I-terminal: RUN_FBITERM = $RUN_FBITERM"
+}
+
+#----[ prepare_for_ssh ]----#
+function prepare_for_ssh () {
+#------------------------------------------------------
+# prepare SSH installation
+# ---
+#
+ :
+}
+
+#----[ prepare_for_vnc ]----#
+function prepare_for_vnc () {
+#------------------------------------------------------
+# prepare VNC installation
+# ---
+#
+ #=============================================
+ # Setup splash screen
+ #---------------------------------------------
+ set_splash 100
+
+ #=============================================
+ # Setup y2base options
+ #---------------------------------------------
+ # xxx
+ #Y2_UI_ARGS="--fullscreen --noborder --auto-fonts"
+ Y2_UI_ARGS="--noborder --auto-fonts"
+
+ #=============================================
+ # Setup VNC server and start it
+ #---------------------------------------------
+ setupVNCAuthentication
+ if [ $VNCPASS_EXCEPTION = 0 ];then
+ disable_splash
+ startVNCServer
+ wait_for_x11
+ if [ "$server_running" = 1 ];then
+ log "\tXvnc-Server is ready: $xserver_pid"
+ fi
+ fi
+}
+
+function check_gtk()
+{
+ echo "silly stub check_gtk"
+ return 0
+}
+
+#----[ check_Qt ]----#
+function check_Qt () {
+#------------------------------------------------------
+# check if the prepared medium Qt is valid
+# ---
+ if [ ! -z "$NEED_XSERVER" ];then
+ if [ "$server_running" = 0 ];then
+ # /.../
+ # X-Server couldn't be started, selecting
+ # NCURSES mode as fallback ?
+ # ---
+ log "\tX-Server couldn't be started, falling back to ncurses"
+ Y2_MODE_FLAGS='("text_fallback")'
+ SELECTED_MEDIUM="NCURSES"
+ prepare_for_ncurses
+ Y2_MODE=ncurses
+ fi
+ else
+ /usr/sbin/testX --fast 2>/dev/null
+ if test $? = 1;then
+ log "\tCannot access Display: $DISPLAY, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ prepare_for_ncurses
+ Y2_MODE=ncurses
+ fi
+ fi
+}
+
+#----[ check_network ]----#
+function check_network () {
+#------------------------------------------------------
+# check if the prepared medium SSH is valid. It is valid
+# if there is a network interface accessable and we are
+# able to use ncurses or X11
+# ---
+ if ! found_iface ; then
+ # /.../
+ # No network interface found for SSH or VNC installation
+ # this is a fatal error here
+ # ---
+ log "\tNo network interface found, fatal error"
+ fatalError
+ fi
+ if [ ! -z "$DISPLAY" ];then
+ log "\tDisplay: $DISPLAY found for network install"
+ Y2_MODE=gtk
+ fi
+ if ! check_gtk ; then
+ log "\tQt plugin check failed falling back to ncurses"
+ Y2_MODE=ncurses
+ fi
+}
+
+#----[ check_vnc ]----#
+function check_vnc () {
+#------------------------------------------------------
+# check if the prepared medium VNC is valid
+# ---
+ check_network
+ if [ $VNCPASS_EXCEPTION = 1 ];then
+ log "\tVNC access has been disabled due to a password exception"
+ log "\tPlease make sure the password is at least 8 characters long"
+ fatalError
+ fi
+ if [ "$server_running" = 0 ];then
+ # /.../
+ # XVnc server couldn't be started, what to do now, I think
+ # this is a fatal error here
+ # ---
+ log "\tXVnc server couldn't be started, fatal error"
+ fatalError
+ fi
+}
+
+#----[ start_yast ]----#
+function start_yast () {
+#------------------------------------------------------
+# Start YaST2 refering to the contents of the Y2_*
+# startup variables
+# ---
+ local overcommit
+ read overcommit < /proc/sys/vm/overcommit_memory
+ echo "*** Starting YaST2 ***"
+ log "\tAllow big memory allocation: overcommit_memory=1"
+ echo 1 > /proc/sys/vm/overcommit_memory
+ if [ "$SPLASH" = yes -a -x /sbin/splash -a -n "$SPLASHCFG" ];then
+ /sbin/splash -t "YaST running"
+ fi
+ export QT_IM_MODULE=xim
+
+ if [ "$RUN_FBITERM" = "1" ]; then
+ OPT_FBITERM=/usr/bin/fbiterm
+ else
+ OPT_FBITERM=
+ fi
+
+ # set up a background if any needed
+ if [ "${BACKGROUND_IMAGE}" != "" ]; then
+ log "\tUsing background: ${BACKGROUND_IMAGE}"
+ fvwm-root --dither ${BACKGROUND_IMAGE}
+ fi
+
+ log "\tStarting YaST2:"
+ log "\tMODULE_NAME: $Y2_MODULE_NAME"
+ log "\tMODE_FLAGS: $Y2_MODE_FLAGS"
+ log "\tMODULE_ARGS: $Y2_MODULE_ARGS"
+ log "\tMODE: $Y2_MODE"
+ log "\tUI_ARGS: $Y2_UI_ARGS"
+ log "\tQT_IM_MODULE:$QT_IM_MODULE"
+ $OPT_FBITERM y2base \
+ "$Y2_MODULE_NAME" \
+ $Y2_MODE_FLAGS \
+ $Y2_MODULE_ARGS \
+ $Y2_MODE \
+ $Y2_UI_ARGS
+ Y2_EXIT_CODE=$?
+ Y2_ABORT_MESSAGE="YaST seems to be aborted abnormally !"
+ Y2_OK_MESSAGE="YaST procedure ended successfully"
+ if [ -s /etc/yast.inf ];then
+ #=============================================
+ # check yast.inf contents
+ #---------------------------------------------
+ cat /etc/yast.inf | grep -q -i "Aborted: 1"
+ if [ $? = 0 ];then
+ log "\t$Y2_ABORT_MESSAGE"
+ fi
+ else
+ #=============================================
+ # YaST ended successfully
+ #---------------------------------------------
+ log "\t$Y2_OK_MESSAGE"
+ fi
+ if [ $SELECTED_MEDIUM = "SSH" ] && [ ! "$VNC" = 1 ];then
+ echo "*** Preparing SSH installation for reboot ***"
+ echo "*** NOTE: after reboot, you have to reconnect and call ***"
+ echo "*** /usr/lib/YaST2/startup/YaST2.ssh ***"
+ log "\tPreparing SSH installation for reboot"
+ echo $Y2_EXIT_CODE > /tmp/YaST2_ssh_installation_finished
+ fi
+ if [ $Y2_EXIT_CODE -eq 0 ];then
+ start_yast_and_reboot
+ start_yast_again
+ fi
+ log "\tReset memory allocation: overcommit_memory=$overcommit"
+ echo $overcommit > /proc/sys/vm/overcommit_memory
+}
+
+#----[ start_yast_and_reboot ]----#
+function start_yast_and_reboot () {
+#------------------------------------------------------
+# This function will reboot the system and start yast
+# again by touching the file /var/lib/YaST2/runme_at_boot.
+# The function is triggered by the file /var/lib/YaST2/reboot
+# ---
+ if [ -f /var/lib/YaST2/reboot ];then
+ rm -f /var/lib/YaST2/reboot
+ touch /var/lib/YaST2/runme_at_boot
+ /sbin/shutdown -r now
+ fi
+}
+
+#----[ start_yast_again ]----#
+function start_yast_again () {
+#------------------------------------------------------
+# This function will restart yast again with the same
+# options as used before. The function is triggered by
+# the file /var/lib/YaST2/restart_yast
+# ---
+ if [ -f /var/lib/YaST2/restart_yast ];then
+ rm -f /var/lib/YaST2/restart_yast
+ start_yast
+ fi
+}
+
+#=============================================
+# Start the Magic :-)
+#=============================================
+# 1) Source common script functions
+#---------------------------------------------
+. /usr/lib/YaST2/startup/common/functions.sh
+. /usr/lib/YaST2/startup/requires
+. /usr/lib/YaST2/startup/arch/ia64/x11.sh
+
+#=============================================
+# 1.1) set splash progress bar to 90%
+#---------------------------------------------
+set_splash 90
+#=============================================
+# 1.2) set root HOME directory
+#---------------------------------------------
+export HOME=/root
+#=============================================
+# 1.3) set HTTP/FTP proxy and configure syslog
+#---------------------------------------------
+set_syslog ; set_proxy
+
+#=============================================
+# 2) Initialize...
+#---------------------------------------------
+# 2.1) setup PATH
+PATH=$ybindir:$PATH
+[ -z Xstartpath ] || PATH=/var/X11R6/bin:$PATH
+#=============================================
+# 2.2) get X11 driver directory
+#---------------------------------------------
+X11_DRIVER_DIR=$Xdriverpath
+if [ -d $Xdriver64path ];then
+ X11_DRIVER_DIR=$Xdriver64path
+fi
+#=============================================
+# 2.3) obtain RAM size in Kb
+#---------------------------------------------
+MEM_TOTAL=`awk '/^MemTotal:/{ print $2 }' /proc/meminfo`
+if [ ${#MEM_TOTAL} -gt 9 ];then
+ MEM_TOTAL=1000000000
+fi
+#=============================================
+# 2.4) check for valid framebuffer
+#---------------------------------------------
+FBDEV_OK=0
+if (: < /dev/fb0) 2>/dev/null ; then
+ FBDEV_OK=1
+fi
+#=============================================
+# 2.5) setup installation mode (update y/n)
+#---------------------------------------------
+INST_MODE="normal"
+if [ -f /var/lib/YaST2/update_mode ];then
+ INST_MODE="update"
+fi
+#=============================================
+# 2.6) import install.inf
+#---------------------------------------------
+import_install_inf
+
+#=============================================
+# 2.7) set LOG prefix
+#---------------------------------------------
+LOG_PREFIX="Stage [call]"
+
+#=============================================
+# 3) Medium prequalification
+#---------------------------------------------
+# Check which installation mediums can be used. There are
+# four mediums available: Qt(0) SSH(1), VNC(2) and NCURSES(3).
+# The following checks will create an array which contains
+# the possible mediums. An index of 1 indicates "can be used"
+# an index of 0 indicated "cannot be used"
+# ---
+MEDIUM=(1 1 1 1)
+
+#=============================================
+# 3.1) prequalification checks for Qt
+#---------------------------------------------
+log "Starting prequalification checks..."
+log "==================================="
+# 3.1.1) Qt plugin check...
+if ! check_gtk ; then
+ log "\tQt plugin check failed -> Medium Qt disabled"
+ MEDIUM[0]=0
+fi
+# 3.1.2) X-Server module check...
+# BEG IA64: use accelerated X11 driver
+ia64_check_x11
+# END IA64:
+XServerAccel=$XServer
+if [ "$XServer" = "vmware" ];then
+ if [ ! -f "$X11_DRIVER_DIR/${XServer}_drv.so" ];then
+ log "\t$XServer driver not installed -> Medium Qt disabled"
+ MEDIUM[0]=0
+ fi
+ X11_CONFIG_ID=vmware
+else
+ XServer=fbdev
+ if [ $FBDEV_OK -eq 0 ];then
+ log "\tNo Framebuffer available: Using vesa driver"
+ XServer=vesa
+ fi
+ if [ ! -f "$X11_DRIVER_DIR/${XServer}_drv.so" ];then
+ log "\t$XServer driver not installed -> Medium Qt disabled"
+ MEDIUM[0]=0
+ fi
+ X11_CONFIG_ID=$XServer
+fi
+if [ "$acceleratedx" = "1" ];then
+ if [ ! -f "$X11_DRIVER_DIR/${XServerAccel}_drv.so" ];then
+ log "\t$XServerAccel driver not installed -> X11 acceleration disabled"
+ else
+ log "\tUsing accelerated driver -> $XServerAccel"
+ MEDIUM[0]=1
+ XServer=$XServerAccel
+ X11_CONFIG_ID=0
+ fi
+fi
+# 3.1.3) Memory check >= 90MB for Qt/X11...
+if [ $MEM_TOTAL -lt "$MEM_NEEDED" ];then
+ log "\tMemory requirement > 90MB not fulfilled -> Medium Qt disabled"
+ MEDIUM[0]=0
+fi
+# 3.1.4) Check if we need to start our own X11 server...
+if [ -z "$DISPLAY" ];then
+ NEED_XSERVER=1
+fi
+# 3.1.5) Check for xorg.conf...
+if [ ! -f /etc/X11/xorg.conf ];then
+if [ ! -f $Xorgconftempl ];then
+ log "\tNo X11 configuration template found -> Medium Qt disabled"
+ MEDIUM[0]=0
+else
+ cp $Xorgconftempl /etc/X11/xorg.conf
+fi
+fi
+# 3.1.6) Check for WindowManager configuration
+if [ ! -f $Xsharedir/fvwm/fvwmrc.yast2 ];then
+ log "\tNo Windowmanager configuration found -> Medium Qt disabled"
+ MEDIUM[0]=0
+fi
+# 3.1.7) Check for remote display usage
+if [ ! -z $Display_IP ];then
+ log "\tRemote Display usage -> Medium Qt enabled"
+ log "\tExporting DISPLAY to host: $Display_IP:0.0"
+ export DISPLAY="$Display_IP:0.0"
+ NEED_XSERVER=""
+ MEDIUM[0]=1
+fi
+
+#=============================================
+# 3.2) prequalification checks for SSH
+#---------------------------------------------
+# 3.2.1) Check for SSH daemon
+if [ -f /var/run/sshd.*pid ];then
+ ps `cat /var/run/sshd.*pid` >/dev/null || MEDIUM[2]=0
+else
+ log "\tNo SSH daemon running -> Medium SSH disabled"
+ MEDIUM[1]=0
+fi
+
+#=============================================
+# 3.3) prequalification checks for VNC
+#---------------------------------------------
+# 3.3.1) Check for WindowManager configuration
+if [ ! -f $Xsharedir/fvwm/fvwmrc.yast2 ];then
+ log "\tNo Windowmanager configuration found -> Medium VNC disabled"
+ MEDIUM[2]=0
+fi
+# 3.3.2) Check for VNC X-Server binary
+if [ ! -x $Xbindir/Xvnc ] ; then
+ log "\tNo Xvnc server installed -> Medium VNC disabled"
+ MEDIUM[2]=0
+fi
+# 3.3.3) Check for testX binary
+if [ ! -x /usr/sbin/testX ] ; then
+ log "\tNo testX binary installed -> Medium VNC disabled"
+ MEDIUM[2]=0
+fi
+
+#=============================================
+# 4) Evaluate medium selection
+#---------------------------------------------
+# At this point we are evaluating the variables which have
+# been imported from the install.inf file into the current
+# environment. The standard method of installing the system
+# should be Qt based. Refering to the variables Textmode,
+# Braille, UseSSH and VNC another medium could be selected
+# VNC overrides UseSSH
+# ---
+log "Evaluate medium selection..."
+log "============================"
+SELECTED_MEDIUM="QT"
+if [ "$Textmode" = 1 ];then
+ log "\tMedium Textmode (ncurses) has been selected"
+ SELECTED_MEDIUM="NCURSES"
+fi
+if [ ! -z "$Braille" ];then
+ log "\tMedium Braille (ncurses) has been selected"
+ SELECTED_MEDIUM="NCURSES"
+fi
+if [ "$UseSSH" = 1 ];then
+ log "\tMedium SSH has been selected"
+ SELECTED_MEDIUM="SSH"
+fi
+if [ "$VNC" = 1 ];then
+ log "\tMedium VNC has been selected"
+ SELECTED_MEDIUM="VNC"
+fi
+
+#=============================================
+# 5) Check selected medium
+#---------------------------------------------
+# Refering to the prequalification check results we need to
+# check if the selected medium is valid according to the
+# MEDIUM flag entry. If the medium is not valid we will
+# fallback to NCURSES mode
+# ---
+log "Check selected medium..."
+log "========================"
+log "\tWished medium is: $SELECTED_MEDIUM"
+case $SELECTED_MEDIUM in
+ QT) {
+ if [ ${MEDIUM[0]} -eq 0 ];then
+ log "\tMedium Qt not available, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ fi
+ } ;;
+ SSH) {
+ if [ ${MEDIUM[1]} -eq 0 ];then
+ log "\tMedium SSH not available, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ fi
+ } ;;
+ VNC) {
+ if [ ${MEDIUM[2]} -eq 0 ];then
+ log "\tMedium VNC not available, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ fi
+ } ;;
+esac
+log "\tSelected medium is: $SELECTED_MEDIUM"
+
+#=============================================
+# 6) Prepare selected medium
+#---------------------------------------------
+case $SELECTED_MEDIUM in
+ QT) prepare_for_qt ; Y2_MODE=gtk ;;
+ SSH) prepare_for_ssh ; Y2_MODE=ncurses ;;
+ VNC) prepare_for_vnc ; Y2_MODE=gtk ;;
+ NCURSES) prepare_for_ncurses ; Y2_MODE=ncurses ;;
+esac
+
+#=============================================
+# 7) Check prepared medium
+#---------------------------------------------
+case $SELECTED_MEDIUM in
+ QT) check_Qt ;;
+ SSH) check_network ;;
+ VNC) check_vnc ;;
+esac
+
+# The prepare_for_ncurses in step 6 is kinda useless if step 7 can
+# change Y2MODE to ncurses in several ways
+# Anyway, #150799
+if [ "$Y2_MODE" = "ncurses" ]; then
+ Y2_UI_ARGS=--nothreads
+fi
+
+#=============================================
+# 8) Call YaST2
+#---------------------------------------------
+Y2_MODULE_NAME=${1:-installation}; shift
+Y2_MODULE_ARGS=\(\"$*\"\)
+start_yast
+
+#=============================================
+# 9) Clean sweep
+#---------------------------------------------
+# 9.1) clear Qt environment...
+clr_inst_qt_env
+
+# 9.2) kill X-Server...
+if [ "$server_running" = 1 ];then
+ sleep 1 && kill $xserver_pid
+ while kill -0 $xserver_pid 2>/dev/null ; do
+ sleep 1
+ done
+fi
+
+#=============================================
+# 10) exit with YaST2 exit code
+#---------------------------------------------
+exit $Y2_EXIT_CODE
+
+
Added: trunk/gtk/integrate/yast2
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/integrate/yast2?rev=42515&vi…
==============================================================================
--- trunk/gtk/integrate/yast2 (added)
+++ trunk/gtk/integrate/yast2 Thu Nov 29 18:25:41 2007
@@ -0,0 +1,280 @@
+#!/bin/bash
+
+# File: /sbin/yast2
+# Module: yast2
+# Summary: YaST2 launch script
+#
+# This script is responsable to start the YaST setup tools. If no arguments
+# are given, a control center should be launched that will call this same script
+# with the wanted setup tool as an argument. In which case, we shall detect the
+# best YaST frontend to provide (eg. gtk for gnome, qt for kde, ncurses for console).
+#
+
+export PATH=/sbin:/usr/sbin:$PATH
+
+# load common script functions
+# (like the detection of frontend plugins)
+. /usr/lib/YaST2/bin/yast2-funcs
+
+# allow user to over-rule the default frontend via a global file
+FRONTEND="auto"
+if test -f /etc/sysconfig/yast2; then
+ . /etc/sysconfig/yast2
+fi
+
+# Arguments to be passed for frontend and the control center (like the --fullscreen)
+YAST_ARGS=""
+
+printhelp()
+{
+ echo "Usage: $0 [OPTIONS] [MODULE] [module specific parameters]"
+ echo
+ echo "OPTIONS:"
+ echo " -l, --list list all available modules"
+ echo " -g, --geometry default window size (graphical frontend only)"
+ echo " --noborder no window manager border for main window (graphical frontend only)"
+ echo " --fullscreen use full screen (graphical frontend only)"
+ echo " -s, --style widget style (qt only)"
+ echo " -h, --help this message"
+ echo
+ echo "exceptional case for installing packages:"
+ echo "$0 OPTION <package> [<package> [...]]"
+ echo
+ echo "OPTION:"
+ echo " -i, --install install rpm package"
+ echo
+ echo "<package> can be a single short package name (e.g. gvim)"
+ echo "which will be installed with dependency checking, or the full"
+ echo "path to an rpm package (e.g /tmp/gvim.rpm) which will be"
+ echo "installed without dependency checking"
+ echo
+}
+
+listmodules()
+{
+ list=`/bin/ls -1 /usr/share/applications/YaST2/*.desktop 2>/dev/null`
+
+ if [ -z "$list" ] ; then
+ echo "No modules installed"
+ else
+ echo "Available modules:"
+ echo
+ grep -h "Exec=/sbin/yast2 " $list | \
+ sed 's|Exec=/sbin/yast2 \([^ ]\+\)\( .*\)\?|\1|' | \
+ sort -u
+ fi
+}
+
+YCP_MENU="$ybindir/y2base menu"
+QT_MENU="$ybindir/y2controlcenter"
+GTK_MENU="/opt/gnome/bin/control-center"
+run_yast_menu()
+{
+ if [ $FRONTEND == "ncurses" ]; then
+ while true ; do
+ $YCP_MENU ncurses $YAST_ARGS
+ if [ ! -e "/var/lib/YaST2/restart_menu" ] ; then
+ break
+ fi
+ done
+ else # gtk or qt
+ if echo $WINDOWMANAGER | grep -qi "gnome" &&
+ [ -e $GTK_MENU ]; then
+ $GTK_MENU $YAST_ARGS
+ elif [ -e $QT_CONTROL_CENTER ]; then
+ $QT_MENU $YAST_ARGS
+ else
+ # run the same YCP menu of ncurses
+ $YCP_MENU $FRONTEND $YAST_ARGS
+ fi
+ fi
+}
+
+## PARSE arguments
+TEMP=`/usr/bin/getopt -o hlg:s:Si --long help,list,kcontrol,geometry:,style:,strings,install,fullscreen,noborder \
+ -n 'yast2' -- "$@"`
+
+if [ $? != 0 ] ; then
+ echo "Exit." >&2
+ exit 1
+fi
+
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+while true ; do
+ case "$1" in
+ -h|--help) printhelp; exit 0 ;;
+ -l|--list) listmodules; exit 0 ;;
+ -g|--geometry) YAST_ARGS="$YAST_ARGS -geometry $2"; shift 2; ;;
+ -i|--install) Y2_INSTALL_PACKAGES=true; shift ;;
+ --fullscreen) YAST_ARGS="$YAST_ARGS --fullscreen"; shift ;;
+ --noborder) YAST_ARGS="$YAST_ARGS --noborder" ; shift ;;
+ --kcontrol) YAST_ARGS="$YAST_ARGS --kcontrol_id YaST" ; shift ;;
+ --) shift ; break ;;
+ *) echo "Unrecognized option $1" ; exit 1 ;;
+
+ # IMPORTANT: Remember to change that "getopt" call above, too
+ # if you change anything here!
+ esac
+done
+
+if [ "$Y2_INSTALL_PACKAGES" = "true" ]; then
+ export module=sw_single
+else
+ # allow module as argument, defaults to "menu"
+ export module="${1-menu}"
+ shift
+fi
+
+case "`/usr/bin/basename $0`" in
+ YaST|yast|yast1|zast)
+ unset DISPLAY
+ ;;
+esac
+
+if [ "$UID" = 0 ]; then
+ echo $$ > /var/run/yast.pid
+fi
+set_lang_from_sysconfig
+
+## CHECK what frontend we should use
+if [ $FRONTEND != "ncurses" ] && [ $FRONTEND != "qt" ] && [ $FRONTEND != "gtk" ] && \
+ [ $FRONTEND != "auto" ]; then
+ echo "Warning: specified frontend $FRONTEND is unknown."
+ FRONTEND="auto"
+fi
+
+if [ $FRONTEND == "auto" ]; then
+ if [ -z "$DISPLAY" ]; then
+ # using the terminal
+ FRONTEND="ncurses"
+ else
+ # running on X11
+ # TODO: maybe GTK could be the default one? ;-)
+ if echo $WINDOWMANAGER | grep -qi "gnome" || \
+ echo $WINDOWMANAGER | grep -qi "xfce" ; then
+ FRONTEND="gtk"
+ else
+ FRONTEND="qt"
+ fi
+ fi
+fi
+
+# fallbacks should go here so that an user preferred frontend also fallback
+if [ $FRONTEND == "gtk" ] && ! check_gtk && check_qt ; then
+ FRONTEND="qt"
+fi
+if [ $FRONTEND == "qt" ] && ! check_qt && check_gtk ; then
+ FRONTEND="gtk"
+fi
+if [ $FRONTEND != "ncurses" ] && ! check_qt && ! check_gtk ; then
+ FRONTEND="ncurses"
+fi
+if [ $FRONTEND == "ncurses" ] && ! check_ncurses; then
+ echo "Error: please install yast2-ncurses to use the YaST2 text mode interface"
+ exit 1
+fi
+
+## SET frontend specific environment settings and whatever they need
+if [ $FRONTEND == "ncurses" ]; then
+ TTY=`/usr/bin/tty`
+ # on console, start yast in UTF-8 locale (only on a 'local' console)
+ if [ "$TERM" = "linux" -a \( "$TTY" = /dev/console -o "$TTY" != "${TTY#/dev/tty[0-9]}" \) ] ; then
+ case "$LANG" in
+ # if it is known that a language doesn't yet work well with ncurses
+ # on console use English instead:
+ ja*|ko*|zh*)
+ export LANG=en_US.UTF-8
+ export LC_CTYPE=en_US.UTF-8
+ ;;
+ *)
+ # get rid of encoding and/or modifier
+ export LANG=${LANG%%[.(a)]*}.UTF-8
+ export LC_CTYPE=${LANG%%[.(a)]*}.UTF-8
+ ;;
+ esac
+ if /bin/testutf8 ; [ $? -ne 2 ] ; then
+ /usr/bin/test -x /bin/unicode_start && /bin/unicode_start
+ uc_started=1
+ fi
+ else
+ case "$TERM" in
+ vt*|xterm*|linux|screen*)
+ # probe terminal and fix lang settings
+ UTF8TESTED=0
+ # binary /bin/testutf8 is missing at least on s390x, #158001
+ /usr/bin/test -x /bin/testutf8 && UTF8TESTED=1 && /bin/testutf8
+ # return code of the /bin/testutf8
+ # 0=utf-unknown, 1=utf-ok, 2=utf-err
+ UTF8STATUS=$?
+
+ # not tested or not working UTF-8 support
+ if [ "$UTF8TESTED" == "1" ] && [ $UTF8STATUS -ne 2 ] ; then
+ /usr/bin/test -n "$LANG" && LANG=${LANG%.UTF-8}
+ /usr/bin/test -n "$LC_CTYPE" && LC_CTYPE=${LC_CTYPE%.UTF-8}
+ else
+ /usr/bin/test -n "$LANG" && LANG=${LANG%%[.(a)]*}.UTF-8
+ /usr/bin/test -n "$LC_CTYPE" && LC_CTYPE=${LC_CTYPE%%[.(a)]*}.UTF-8
+ fi
+ ;;
+ esac
+ fi
+
+ # this fixes launching of interactive subprocesses, #150799
+ YAST_ARGS="$YAST_ARGS --nothreads"
+fi
+
+if [ $FRONTEND == "qt" ]; then
+ set_qt_home_dir
+
+ # FIXME: why the hack was this done? full screening something that
+ # takes so much time to load is just annoying!
+ if echo $WINDOWMANAGER | grep -qi "kde" ; then
+ if [ $module == "sw_single" ] ; then
+ case "$YAST_ARGS" in
+ *fullscreen*) ;;
+ *) YAST_ARGS="$YAST_ARGS --fullscreen" ;;
+ esac
+ fi
+ fi
+fi
+
+## RUN the requested module
+if [ $module == "menu" ]; then
+ run_yast_menu
+else
+ # we do a cycle because we want to keep the online_update module alive as long
+ # as there are pending patches
+ while true ; do
+ # Transform every argument into a ycp string, that is surround all
+ # args by ("..."). args may contain spaces.
+ a=("$@")
+ b=("${a[@]/#/(\"}")
+ c=("${b[@]/%/\")}")
+ set -- "${c[@]}"
+
+ $ybindir/y2base $module "$@" $FRONTEND "$YAST_ARGS"
+
+ if [ ! $module == "online_update" ] || [ ! -e "/var/lib/YaST2/selected_patches.ycp" ] ; then
+ break
+ fi
+ done
+fi
+
+## LAST frontend specific changes
+if [ $FRONTEND == "ncurses" ]; then
+ if [ "$uc_started" ] ; then
+ /usr/bin/test -x /bin/unicode_stop && /bin/unicode_stop
+ fi
+fi
+
+## EXIT
+exit_code=$?
+
+if [ "$UID" = 0 ]; then
+ rm -f /var/run/yast.pid
+fi
+
+exit $exit_code
+
Added: trunk/gtk/integrate/yast2-funcs
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/integrate/yast2-funcs?rev=42…
==============================================================================
--- trunk/gtk/integrate/yast2-funcs (added)
+++ trunk/gtk/integrate/yast2-funcs Thu Nov 29 18:25:41 2007
@@ -0,0 +1,141 @@
+# File: /usr/share/YaST2/bin/yast2-funcs
+# Module: yast2
+# Summary: Common functions for YaST2 start scripts
+# Authors: Arvin Schnell <arvin(a)suse.de>
+#
+# $Id: yast2-funcs 24861 2005-08-12 11:10:25Z locilka $
+
+# some path definitions
+ybindir=/usr/lib/YaST2/bin
+logdir=/var/log/YaST2
+
+
+# font for qt
+# obsolete, we should not need it anymore, adrian
+# Y2_XFONT="-gnu-unifont-medium-r-normal--16-160-75-75-p-80-iso10646-1"
+
+
+#
+# check if plugins are in lib or lib64 subdir and sets the variable
+# plugindir accordingly
+#
+function get_plugindir()
+{
+ plugindir=/usr/lib/YaST2/plugin
+ if `ldd $ybindir/y2base | egrep --quiet "/lib64/(.*/)?libc.so"` ; then
+ plugindir=/usr/lib64/YaST2/plugin
+ fi
+}
+
+#
+# check if the gtk plugin and all necessary libaries are present
+#
+function check_gtk()
+{
+ get_plugindir
+ Y2_GTK=$plugindir/libpy2gtk.so.2
+
+ if [ -e "$Y2_GTK" ] ; then
+ if ! `/usr/bin/ldd "$Y2_GTK" | grep --quiet "=> not found"` ; then
+ return 0 # success
+ fi
+ echo "warning: the gtk frontend is installed but does not work"
+ sleep 1
+ fi
+
+ return 1 # failure
+}
+
+#
+# check if the qt plugin and all necessary libaries are present
+#
+function check_qt()
+{
+ get_plugindir
+ Y2_QT=$plugindir/libpy2qt.so.2
+
+ if [ -e "$Y2_QT" ] ; then
+ if ! `/usr/bin/ldd "$Y2_QT" | grep --quiet "=> not found"` ; then
+ return 0 # success
+ fi
+ echo "warning: the qt frontend is installed but does not work"
+ sleep 1
+ fi
+
+ return 1 # failure
+}
+
+
+#
+# check if the ncurses plugin and all necessary libaries are present
+#
+function check_ncurses()
+{
+ get_plugindir
+ Y2_NCURSES=$plugindir/libpy2ncurses.so.2
+
+ if [ -e "$Y2_NCURSES" ] ; then
+ if ! `/usr/bin/ldd "$Y2_NCURSES" | grep --quiet "=> not found"` ; then
+ return 0 # success
+ fi
+ echo "warning: the ncurses frontend is installed but does not work"
+ sleep 1
+ fi
+
+ return 1 # failure
+}
+
+
+#
+# if LANG is empty set LANG to RC_LANG in /etc/sysconfig/language
+#
+function set_lang_from_sysconfig()
+{
+ # if LANG is "POSIX", unset LANG
+ # SL 9.3 had default LANG set to ""
+ # SL 10.0 has default LANG set to "POSIX"
+ if [ "$LANG" == "POSIX" ] ; then
+ LANG=""
+ fi
+
+ # if LANG is not empty and /etc/sysconfig/language exists
+ if [ -z "$LANG" -a -r /etc/sysconfig/language ] ; then
+ . /etc/sysconfig/language
+ if [ -n "$RC_LANG" ] ; then
+ export LANG=$RC_LANG
+ fi
+ fi
+}
+
+
+function set_qt_home_dir()
+{
+ local user="$USER"
+ if [ "$KDESU_USER" ]; then
+ user="$KDESU_USER"
+ fi
+ temp_QT_HOME_DIR="`eval echo ~$user/.qt/`"
+ if test -r "$temp_QT_HOME_DIR/qtrc"; then
+ export QT_HOME_DIR="$temp_QT_HOME_DIR"
+ fi
+}
+
+
+function set_inst_qt_env()
+{
+ export XCURSOR_THEME="crystalwhite"
+ export QT_HOME_DIR="`eval echo /tmp/.qt/`"
+ mkdir -p /tmp/.qt
+ [ -e /usr/share/desktop-data/qtrc ] && cp /usr/share/desktop-data/qtrc /tmp/.qt/
+}
+
+
+function clr_inst_qt_env()
+{
+ rm -rf /tmp/.qt/
+}
+
+
+### Local Variables: ***
+### mode: shell-script ***
+### End: ***
Added: trunk/gtk/package/yast2-gtk-rpmlintrc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/package/yast2-gtk-rpmlintrc?…
==============================================================================
--- trunk/gtk/package/yast2-gtk-rpmlintrc (added)
+++ trunk/gtk/package/yast2-gtk-rpmlintrc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,2 @@
+# yast2 likes a .so file for it's plugin that looks like a -devel pkg thing
+addFilter("devel-file-in-non-devel-package")
Added: trunk/gtk/package/yast2-gtk.changes
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/package/yast2-gtk.changes?re…
==============================================================================
--- trunk/gtk/package/yast2-gtk.changes (added)
+++ trunk/gtk/package/yast2-gtk.changes Thu Nov 29 18:25:41 2007
@@ -0,0 +1,107 @@
+-------------------------------------------------------------------
+Wed Oct 6 15:32:01 BST 2007 - mmichael(a)suse.de
+
+- n#300750: big speedup wrt. search / sort
+
+-------------------------------------------------------------------
+Wed Aug 26 15:32:01 BST 2007 - mmichael(a)suse.de
+
+- n#300390: warn if cancelling a non-submitted transaction.
+
+-------------------------------------------------------------------
+Wed Aug 8 15:32:01 BST 2007 - mmichael(a)suse.de
+
+- #296945: pulse progress bar impl.
+
+-------------------------------------------------------------------
+Fri Aug 10 18:01:20 CEST 2007 - mvidner(a)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(a)suse.de
+
+- FaTE #302018: details on how to print the license
+- 2.15.8
+
+-------------------------------------------------------------------
+Wed Aug 8 09:22:32 CEST 2007 - mvidner(a)suse.cz
+
+- Don't build-require yast2-devel-doc.
+- 2.15.7.2
+
+-------------------------------------------------------------------
+Mon Aug 6 14:00:37 CEST 2007 - mvidner(a)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(a)suse.cz
+
+- removed yast2-devel from BuildRequires
+- 2.15.7
+
+-------------------------------------------------------------------
+Mon Jul 23 15:32:01 BST 2007 - mmichael(a)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(a)suse.cz
+
+- adapted to new libzypp
+- added support for translations
+- 2.15.5
+
+-------------------------------------------------------------------
+Thu Jun 21 10:24:55 CEST 2007 - mmichael(a)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(a)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(a)suse.de
+
+- upgrade to yast2-gtk-2.15.2, fixes upgrade.ycp
+
+-------------------------------------------------------------------
+Fri Mar 16 13:36:04 CET 2007 - mmichael(a)suse.de
+
+- upgrade to yast2-gtk-2.15.1, several fixes, including #247682, #247683
+
+-------------------------------------------------------------------
+Wed Feb 7 11:26:07 CET 2007 - mmichael(a)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(a)suse.de
+
+- added yast2-gtk-autogen.patch to fix build with latests yast2-devtools
+
+-------------------------------------------------------------------
+Mon Aug 28 11:34:13 CEST 2006 - cthiel(a)suse.de
+
+- fix build
+
+-------------------------------------------------------------------
+Wed Aug 23 18:20:30 CEST 2006 - mmichael(a)suse.de
+
+- import yast2-gtk into autobuild.
+
Added: trunk/gtk/src/.cvsignore
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/.cvsignore?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/.cvsignore (added)
+++ trunk/gtk/src/.cvsignore Thu Nov 29 18:25:41 2007
@@ -0,0 +1,7 @@
+Makefile.in
+Makefile
+*.lo
+*.la
+.libs
+.deps
+dummy
Added: trunk/gtk/src/Makefile.am
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/Makefile.am?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/Makefile.am (added)
+++ trunk/gtk/src/Makefile.am Thu Nov 29 18:25:41 2007
@@ -0,0 +1,68 @@
+AM_CFLAGS = $(GTK_CFLAGS) \
+ -DTHEMEDIR=\"${themedir}/current\"
+AM_CXXFLAGS = $(GTK_CFLAGS) \
+ -DY2LOG=\"ui-gtk\" \
+ -DTHEMEDIR=\"${themedir}/current\"
+
+noinst_HEADERS = $(wildcard *.h)
+
+# test linkage for missing symbols etc.
+noinst_PROGRAMS = dummy
+
+# plugin, libtool forces 'lib' prefix
+plugin_LTLIBRARIES = libpy2gtk.la
+
+libpy2gtk_la_LDFLAGS = -version-info 2:0
+libpy2gtk_la_LIBADD = -L$(plugindir) $(PYUI_LIBS) -L$(libdir) -lycp -ly2 \
+ $(GTK_LIBS) $(ZYPP_LIBS) $(GTKHTML_LIBS)
+libpy2gtk_la_SOURCES = \
+ Y2CCGtk.cc \
+ YGUtils.cc \
+ YGUI.cc \
+ YGDialog.cc \
+ YGLayout.cc \
+ YGWidget.cc \
+ YGLabel.cc \
+ YGPushButton.cc \
+ YGProgressBar.cc \
+ YGTextEntry.cc \
+ YGMultiLineEdit.cc \
+ YGIntField.cc \
+ YGRadioButton.cc \
+ YGImage.cc \
+ YGFrame.cc \
+ YGComboBox.cc \
+ YGTable.cc \
+ YGTree.cc \
+ YGMenuButton.cc \
+ YGBarGraph.cc \
+ YGDumbTab.cc \
+ YGWizard.cc \
+ YGTime.cc \
+ YGPackageSelector.cc \
+ ygtkratiobox.c \
+ ygtkbargraph.c \
+ ygtksteps.c \
+ ygtkfieldentry.c \
+ ygtkmenubutton.c \
+ ygtkwizard.c \
+ ygtkcellrendererarrow.c \
+ ygtkfindentry.c \
+ ygdkmngloader.c \
+ ygtkhtmlwrap.c \
+ ygtkrichtext.c
+# should only append ygtkrichtext.c if USE_GTKHTML is set
+
+dummy_SOURCES = dummy.cc
+dummy_LDADD = libpy2gtk.la
+
+check_PROGRAMS = test
+TESTS = $(check_PROGRAMS)
+
+test_SOURCES = test.cc
+test_LDADD = $(top_builddir)/src/$(plugin_LTLIBRARIES)
+
+INCLUDES = -I$(srcdir)/include -I$(includedir) -I$(includedir)/yui $(ZYPP_CFLAGS)
+
+EXTRA_DIST =
+
Added: trunk/gtk/src/Y2CCGtk.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/Y2CCGtk.cc?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/Y2CCGtk.cc (added)
+++ trunk/gtk/src/Y2CCGtk.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,68 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <YGUI.h>
+#include <YUIComponent.h>
+#include <ycp/y2log.h>
+
+#if YAST2_VERSION >= 2015006
+// New UI plugin work
+# include <Y2CCUI.h>
+# define NEW_UI_PLUGIN
+# define Y2CCUI_INIT
+#else
+# define Y2CCUI Y2ComponentCreator
+# define Y2CCUI_INIT Y2ComponentBroker::BUILTIN
+#endif
+
+class YGUIComponent : public YUIComponent
+{
+public:
+
+ YGUIComponent() : YUIComponent() {}
+
+ virtual string name() const { return "gtk"; }
+
+ virtual YUI *createUI (int argc, char **argv,
+ bool with_threads, const char * macro_file)
+ {
+#ifdef IMPL_DEBUG
+ fprintf (stderr, "Create a gtk+ UI: %d '%s' !\n", with_threads, macro_file);
+#endif
+ return new YGUI (argc, argv, with_threads, macro_file);
+ }
+};
+
+class Y2CCGtk : public Y2CCUI
+{
+public:
+ Y2CCGtk () : Y2CCUI (Y2CCUI_INIT) { };
+
+ bool isServerCreator () const { return true; };
+
+ Y2Component *create (const char * name) const
+ {
+ y2milestone( "Creating %s component", name );
+ if (!strcmp (name, "gtk") ) {
+#ifdef NEW_UI_PLUGIN
+ Y2Component* ret = YUIComponent::uiComponent ();
+ if (!ret || ret->name () != name) {
+ y2debug ("UI component is %s, creating %s", ret? ret->name().c_str() : "NULL", name);
+ ret = new YGUIComponent();
+ }
+ return ret;
+#else
+ return new YGUIComponent();
+#endif
+ }
+ else
+ return 0;
+ }
+};
+
+// Singleton plugin registration instance.
+Y2CCGtk g_y2ccgtk;
+
+
Added: trunk/gtk/src/YGBarGraph.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGBarGraph.cc?rev=42515&…
==============================================================================
--- trunk/gtk/src/YGBarGraph.cc (added)
+++ trunk/gtk/src/YGBarGraph.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,193 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+#include "ygtkbargraph.h"
+
+#include "YBarGraph.h"
+
+class YGBarGraph : public YBarGraph, public YGWidget
+{
+public:
+ YGBarGraph (const YWidgetOpt &opt, YGWidget *parent)
+ : YBarGraph (opt)
+ , YGWidget (this, parent, true, YGTK_TYPE_BAR_GRAPH, NULL)
+ { }
+
+ // YBarGraph
+ virtual void doUpdate()
+ {
+ ygtk_bar_graph_create_entries (YGTK_BAR_GRAPH (getWidget()), segments());
+ for (int i = 0; i < segments(); i++)
+ ygtk_bar_graph_setup_entry (YGTK_BAR_GRAPH (getWidget()), i,
+ label(i).c_str(), value(i));
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createBarGraph (YWidget *parent, YWidgetOpt &opt)
+{
+ return new YGBarGraph (opt, YGWidget::get (parent));
+}
+
+#include "YPartitionSplitter.h"
+
+class YGPartitionSplitter : public YPartitionSplitter, public YGWidget
+{
+public:
+ YGtkBarGraph *m_barGraph;
+ bool m_showDelta;
+ GtkWidget *m_scale, *m_free_spin, *m_new_spin;
+ string m_freeLabel, m_newPartLabel;
+
+ YGPartitionSplitter (const YWidgetOpt &opt, YGWidget *parent,
+ int _usedSize, int _totalFreeSize, int _newPartSize,
+ int _minNewPartSize, int _minFreeSize,
+ const YCPString &usedLabel, const YCPString &freeLabel,
+ const YCPString &newPartLabel, const YCPString &freeFieldLabel,
+ const YCPString &newPartFieldLabel)
+ : YPartitionSplitter (opt, _usedSize, _totalFreeSize, _newPartSize,
+ _minNewPartSize, _minFreeSize, usedLabel,
+ freeLabel, newPartLabel, freeFieldLabel,
+ newPartFieldLabel)
+ , YGWidget (this, parent, true, 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->value_cstr(),
+ usedSize());
+ m_freeLabel = freeLabel->value();
+ m_newPartLabel = newPartLabel->value();
+ // the others are setup-ed on SetValue()
+
+ /* Labels over the slider */
+ GtkWidget *labels_box, *free_label, *new_part_label;
+ labels_box = gtk_hbox_new (FALSE, 0);
+ free_label = gtk_label_new (freeFieldLabel->value_cstr());
+ new_part_label = gtk_label_new (newPartFieldLabel->value_cstr());
+ gtk_box_pack_start (GTK_BOX (labels_box), free_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (labels_box), new_part_label, FALSE, FALSE, 0);
+
+ /* Slider and the spinners */
+ m_showDelta = opt.countShowDelta.value();
+
+ GtkWidget *slider_box = gtk_hbox_new (FALSE, 0);
+ m_scale = gtk_hscale_new_with_range (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);
+
+ 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);
+
+ g_signal_connect (G_OBJECT (m_scale), "value-changed",
+ G_CALLBACK (scale_changed_cb), this);
+ g_signal_connect (G_OBJECT (m_free_spin), "value-changed",
+ G_CALLBACK (free_spin_changed_cb), this);
+ g_signal_connect (G_OBJECT (m_new_spin), "value-changed",
+ G_CALLBACK (new_spin_changed_cb), this);
+
+ /* Main layout */
+ gtk_box_pack_start (GTK_BOX (getWidget()), graph, TRUE, TRUE, 0);
+ 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 void setValue (int newValue)
+ {
+ IMPL
+ YPartitionSplitter::setValue (newValue);
+
+ ygtk_bar_graph_setup_entry (m_barGraph, 1, m_freeLabel.c_str(),
+ remainingFreeSize());
+ ygtk_bar_graph_setup_entry (m_barGraph, 2, m_newPartLabel.c_str(),
+ newPartSize());
+
+ // block connections
+ g_signal_handlers_block_by_func (m_scale,
+ (gpointer) scale_changed_cb, this);
+ g_signal_handlers_block_by_func (m_free_spin,
+ (gpointer) free_spin_changed_cb, this);
+ g_signal_handlers_block_by_func (m_new_spin,
+ (gpointer) new_spin_changed_cb, this);
+
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_free_spin),
+ remainingFreeSize());
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_new_spin),
+ newPartSize());
+ gtk_range_set_value (GTK_RANGE (m_scale), remainingFreeSize());
+
+ // unblock connections
+ g_signal_handlers_unblock_by_func (m_scale,
+ (gpointer) scale_changed_cb, this);
+ g_signal_handlers_unblock_by_func (m_free_spin,
+ (gpointer) free_spin_changed_cb, this);
+ g_signal_handlers_unblock_by_func (m_new_spin,
+ (gpointer) new_spin_changed_cb, this);
+ }
+
+ static void scale_changed_cb (GtkRange *range, YGPartitionSplitter *pThis)
+ {
+ IMPL
+ int newFreeSize = (int) gtk_range_get_value (range);
+ int newPartSize = pThis->totalFreeSize() - newFreeSize;
+ if (pThis->m_showDelta)
+ newPartSize += pThis->usedSize();
+
+ pThis->setValue (newPartSize);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void free_spin_changed_cb (GtkSpinButton *spin, YGPartitionSplitter *pThis)
+ {
+ IMPL
+ int newFreeSize = gtk_spin_button_get_value_as_int (spin);
+ int newPartSize = pThis->totalFreeSize() - newFreeSize;
+ if (pThis->m_showDelta)
+ newPartSize += pThis->usedSize();
+
+ pThis->setValue (newPartSize);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void new_spin_changed_cb (GtkSpinButton *spin, YGPartitionSplitter *pThis)
+ {
+ IMPL
+ if (pThis->m_showDelta)
+ pThis->setValue (pThis->remainingFreeSize() - pThis->totalFreeSize());
+ else
+ pThis->setValue (gtk_spin_button_get_value_as_int (spin));
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createPartitionSplitter (YWidget *parent, YWidgetOpt &opt,
+ int usedSize, int totalFreeSize, int newPartSize,
+ int minNewPartSize, int minFreeSize,
+ const YCPString &usedLabel,const YCPString &freeLabel,
+ const YCPString &newPartLabel,
+ const YCPString &freeFieldLabel,
+ const YCPString &newPartFieldLabel)
+{
+ return new YGPartitionSplitter (opt, YGWidget::get (parent), usedSize,
+ totalFreeSize, newPartSize, minNewPartSize, minFreeSize, usedLabel,
+ freeLabel, newPartLabel, freeFieldLabel, newPartFieldLabel);
+}
Added: trunk/gtk/src/YGComboBox.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGComboBox.cc?rev=42515&…
==============================================================================
--- trunk/gtk/src/YGComboBox.cc (added)
+++ trunk/gtk/src/YGComboBox.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,156 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YComboBox.h"
+#include "YGWidget.h"
+
+class YGComboBox : public YComboBox, public YGLabeledWidget
+{
+bool m_showingIcons;
+
+ public:
+ YGComboBox (const YWidgetOpt &opt, YGWidget *parent, YCPString label)
+ : YComboBox (opt, label)
+ , YGLabeledWidget (this, parent, label, YD_HORIZ, true,
+ opt.isEditable.value() ? GTK_TYPE_COMBO_BOX_ENTRY : GTK_TYPE_COMBO_BOX, NULL)
+ {
+ // pixbufs will be enabled if icons are provided
+ m_showingIcons = false;
+
+ GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, GDK_TYPE_PIXBUF);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (getWidget()), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ if(opt.isEditable.value())
+ gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (getWidget()), 0);
+ else {
+ GtkCellRenderer* cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (getWidget()), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
+ "text", 0, NULL);
+ }
+
+ g_signal_connect (G_OBJECT (getWidget()), "changed",
+ G_CALLBACK (selected_changed_cb), this);
+ }
+
+ GtkComboBox *getComboBox() const
+ {
+ return GTK_COMBO_BOX ((const_cast<YGComboBox *>(this)->getWidget()));
+ }
+
+ GtkEntry *getEntry()
+ {
+ if (!GTK_IS_COMBO_BOX_ENTRY (getWidget())) {
+ y2error ("YGComboBox: trying to edit read-only combo box");
+ return NULL;
+ }
+
+ GtkWidget *entry = gtk_bin_get_child (GTK_BIN (getWidget()));
+ if (!GTK_IS_ENTRY (entry)) {
+ g_error ("YGComboBox: GtkComboBoxEntry doesn't have a GtkEntry as child");
+ return NULL;
+ }
+
+ return GTK_ENTRY (entry);
+ }
+
+ virtual void itemAdded (const YCPString &string, int index, bool selected)
+ {
+ GtkListStore *store = GTK_LIST_STORE (gtk_combo_box_get_model (getComboBox()));
+ GtkTreeIter iter;
+ gtk_list_store_insert (store, &iter, index);
+ gtk_list_store_set (store, &iter, 0, string->value_cstr(), -1);
+
+ if(hasIcons() && !m_showingIcons) {
+ 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", 1, NULL);
+ m_showingIcons = true;
+ }
+
+ if (hasIcons() && !itemIcon (index)->value().empty()) {
+ std::string path = itemIcon (index)->value();
+ if (path[0] != '/')
+ path = ICON_DIR + path;
+
+ GdkPixbuf *pixbuf;
+ GError *error = 0;
+ pixbuf = gdk_pixbuf_new_from_file (path.c_str(), &error);
+ if (!pixbuf)
+ y2warning ("YGComboBox: Could not load icon: %s.\n"
+ "Because %s", path.c_str(), error->message);
+ gtk_list_store_set (store, &iter, 1, pixbuf, -1);
+ }
+
+ if (selected || index == 0)
+ setCurrentItem (index);
+ }
+
+ virtual void setValue (const YCPString &value)
+ {
+ IMPL
+ gtk_entry_set_text (getEntry(), value->value_cstr());
+ }
+
+ virtual YCPString getValue() const
+ {
+ return YCPString (gtk_combo_box_get_active_text (getComboBox()));
+ }
+
+ virtual int getCurrentItem() const
+ {
+ return gtk_combo_box_get_active (getComboBox());
+ }
+
+ virtual void setCurrentItem (int index)
+ {
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) selected_changed_cb, this);
+ gtk_combo_box_set_active (GTK_COMBO_BOX(getWidget()), index);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) selected_changed_cb, this);
+ }
+
+ virtual void setInputMaxLength (const YCPInteger &numberOfChars)
+ {
+ gtk_entry_set_width_chars (getEntry(), numberOfChars->asInteger()->value());
+ }
+
+ // Events notifications
+ static void selected_changed_cb (GtkComboBox *widget, YGComboBox *pThis)
+ {
+ /* selected_changed_cb() is called when a new item was selected or the user has
+ typed some text on a writable ComboBox. text_changed is true for the later and
+ false for the former. */
+ bool text_changed = GTK_IS_COMBO_BOX_ENTRY (widget)
+ && pThis->getCurrentItem() == -1;
+
+ if (text_changed) {
+ g_signal_handlers_block_by_func (pThis->getWidget(), (gpointer)
+ selected_changed_cb, pThis);
+ YGUtils::filterText (GTK_EDITABLE (pThis->getEntry()), 0, -1,
+ pThis->getValidChars()->value_cstr());
+ g_signal_handlers_unblock_by_func (pThis->getWidget(), (gpointer)
+ selected_changed_cb, pThis);
+
+ pThis->emitEvent (YEvent::ValueChanged, true, true);
+ }
+ else
+ pThis->emitEvent (YEvent::SelectionChanged, true, true);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YComboBox)
+};
+
+YWidget *
+YGUI::createComboBox (YWidget *parent, YWidgetOpt & opt,
+ const YCPString & label)
+{
+ return new YGComboBox (opt, YGWidget::get (parent), label);
+}
Added: trunk/gtk/src/YGDialog.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGDialog.cc?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/YGDialog.cc (added)
+++ trunk/gtk/src/YGDialog.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,379 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGDialog.h"
+#include <gdk/gdkkeysyms.h>
+#include <math.h> // easter
+
+/* In the main dialog case (when opt.hasDefaultSize is set), 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.
+*/
+
+class YGWindow;
+static YGWindow *main_window = NULL;
+
+YGWindow::~YGWindow()
+{
+ IMPL
+ setChild (NULL);
+ gtk_widget_destroy (m_widget);
+ g_object_unref (G_OBJECT (m_widget));
+}
+
+void YGWindow::setChild (YWidget *new_child)
+{
+ IMPL
+ 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;
+}
+
+void YGWindow::ref (YGWindow *window)
+{
+ window->m_refcount++;
+}
+void YGWindow::unref (YGWindow *window)
+{
+ if (--window->m_refcount == 0) {
+ bool is_main_window = (window == main_window);
+ delete window;
+ if (is_main_window)
+ main_window = NULL;
+ }
+}
+
+static gboolean draw_border_cb (GtkWidget *widget, GdkEventExpose *event,
+ YGWindow *pThis)
+{
+ IMPL
+ // to avoid background from overlapping, we emit the expose to the containee
+ // ourselves
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ gtk_bin_get_child (GTK_BIN (widget)),
+ event);
+
+ GtkAllocation *alloc = &widget->allocation;
+ gtk_draw_shadow (gtk_widget_get_style (widget), widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ alloc->x, alloc->y, alloc->width, alloc->height);
+ return TRUE;
+}
+
+static gboolean expode_window_timeout_cb (gpointer data)
+{
+ GtkWindow *window = YGUI::ui()->currentWindow();
+ if (!window)
+ return FALSE;
+ 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;
+}
+
+gboolean YGWindow::close_window_cb (GtkWidget *widget, GdkEvent *event,
+ YGWindow *pThis)
+{
+ IMPL
+ // never let GTK+ destroy the window! just inform YCP, and let it
+ // do its thing.
+ pThis->closeWindow();
+ return TRUE;
+}
+
+void YGWindow::closeWindow()
+{
+ if (!m_canClose || m_canClose (m_canCloseData))
+ YGUI::ui()->sendEvent (new YCancelEvent());
+}
+
+static gboolean key_pressed_cb (GtkWidget *widget, GdkEventKey *event,
+ YGWindow *pThis)
+{
+ IMPL
+ // if not main dialog, close it on escape
+ if (event->keyval == GDK_Escape &&
+ /* not main window */ main_window != pThis)
+ {
+ pThis->closeWindow();
+ 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)) {
+ y2milestone ("Caught YaST2 magic key combination");
+ 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:
+ y2milestone ("Starting xterm");
+ system ("/usr/bin/xterm &");
+ return TRUE;
+ case GDK_T:
+ dumpYastTree (pThis->getChild());
+ 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, NULL);
+ else {
+ g_source_remove (explode_timeout);
+ explode_timeout = 0;
+ }
+ return TRUE;
+ default:
+ break;
+ }
+ }
+ return FALSE;
+}
+
+YGWindow::YGWindow (bool main_window)
+{
+ m_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_object_ref (G_OBJECT (m_widget));
+ gtk_object_sink (GTK_OBJECT (m_widget));
+
+ m_refcount = 0;
+ if (main_window)
+ ::main_window = this;
+ m_child = NULL;
+ m_canClose = NULL;
+
+ {
+ GtkWindow *parent = YGUI::ui()->currentWindow();
+ 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);
+ //gtk_window_set_focus_on_map (window, FALSE);
+ }
+ else {
+ gtk_window_set_title (window, "YaST");
+ if (YGUI::ui()->unsetBorder())
+ gtk_window_set_decorated (window, FALSE);
+ }
+
+ if (main_window) {
+ int w = YGUI::ui()->getDefaultSize (YD_HORIZ),
+ h = YGUI::ui()->getDefaultSize (YD_VERT);
+ gtk_window_set_default_size (window, w, h);
+ }
+
+ gtk_window_set_role (window, "yast-gtk");
+ if (!YGUI::ui()->hasWM())
+ g_signal_connect (G_OBJECT (m_widget), "expose-event",
+ G_CALLBACK (draw_border_cb), 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);
+}
+
+void YGWindow::setCloseCallback (YGWindowCloseFn canClose, void *canCloseData)
+{
+ m_canClose = canClose;
+ m_canCloseData = canCloseData;
+}
+
+void YGWindow::unsetCloseCallback()
+{
+ m_canClose = NULL;
+}
+
+YGDialog::YGDialog (YWidgetOpt &opt)
+ : YDialog (opt),
+ YGWidget (this, NULL, FALSE, GTK_TYPE_HBOX, NULL)
+{
+ setBorder (0);
+ m_padding = 0;
+ m_containee = gtk_event_box_new();
+ if (hasDefaultSize() && main_window)
+ m_window = main_window;
+ else
+ m_window = new YGWindow (hasDefaultSize());
+ YGWindow::ref (m_window);
+
+ if (hasWarnColor() || hasInfoColor()) {
+ // emulate a warning / info dialog
+ GtkWidget *icon = gtk_image_new_from_stock
+ (hasWarnColor() ? 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);
+
+ GtkRequisition req;
+ gtk_widget_size_request (icon, &req);
+ m_padding = req.width + 24;
+ }
+ 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::showWindow()
+{
+ IMPL
+ m_window->setChild (this);
+ gtk_widget_show (m_window->getWidget());
+ YGUI::ui()->busyCursor();
+}
+
+void YGDialog::hideWindow()
+{
+ IMPL
+ m_window->setChild (NULL);
+ gtk_widget_hide (m_window->getWidget());
+}
+
+YDialog *
+YGUI::createDialog (YWidgetOpt &opt)
+{
+ IMPL
+ return new YGDialog (opt);
+}
+
+static list <YGDialog *> dialogs_stack;
+
+void
+YGUI::showDialog (YDialog *_dialog)
+{
+ IMPL
+ YGDialog *dialog = static_cast <YGDialog *> (_dialog);
+ if (dialog->hasDefaultSize())
+ dialogs_stack.push_back (dialog);
+ dialog->showWindow();
+}
+
+void
+YGUI::closeDialog (YDialog *_dialog)
+{
+ IMPL
+ YGDialog *dialog = static_cast <YGDialog *> (_dialog);
+ if (dialog->hasDefaultSize()) {
+ dialogs_stack.pop_back();
+ if (!dialogs_stack.empty()) {
+ YGDialog *old_dialog = dialogs_stack.back();
+ old_dialog->showWindow();
+ }
+ else
+ dialog->hideWindow();
+ }
+ else
+ dialog->hideWindow();
+}
+
+GtkWindow *
+YGUI::currentWindow()
+{
+ YDialog *ydialog = YGUI::ui()->currentDialog();
+ if (ydialog)
+ return static_cast<YGDialog *>(ydialog)->getWindow();
+ else
+ return NULL;
+}
+
+YGDialog *
+YGUI::currentYGDialog()
+{
+ YDialog *ydialog = YGUI::ui()->currentDialog();
+ if (ydialog)
+ return static_cast<YGDialog *>(ydialog);
+ else
+ return NULL;
+}
+
+void YGDialog::busyCursor()
+{
+ // NOTE: GdkDisplay won't change for new dialogs, so we don't
+ // have to synchronize between them or something.
+ static GdkCursor *cursor = NULL;
+ if (!cursor) {
+ GdkDisplay *display = gtk_widget_get_display (m_window->getWidget());
+ cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+ }
+ gdk_window_set_cursor (m_window->getWidget()->window, cursor);
+}
+
+void YGDialog::normalCursor()
+{
+ gdk_window_set_cursor (m_window->getWidget()->window, NULL);
+}
+
Added: trunk/gtk/src/YGDialog.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGDialog.h?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGDialog.h (added)
+++ trunk/gtk/src/YGDialog.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,70 @@
+#ifndef YGDIALOG_H
+#define YGDIALOG_H
+
+#include "YGWidget.h"
+#include "YDialog.h"
+
+typedef bool (*YGWindowCloseFn) (void *closure);
+
+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;
+ YGWindowCloseFn m_canClose;
+ void *m_canCloseData;
+
+private:
+ static gboolean close_window_cb (GtkWidget *widget, GdkEvent *event,
+ YGWindow *pThis);
+public:
+ YGWindow (bool main_window);
+ ~YGWindow();
+ void setChild (YWidget *new_child);
+ static void ref (YGWindow *window);
+ static void unref (YGWindow *window);
+
+ void normalCursor();
+ void busyCursor();
+
+ void setCloseCallback (YGWindowCloseFn canClose, void *canCloseData);
+ void unsetCloseCallback();
+ void closeWindow();
+
+ // Y(G)Widget-like methods
+ GtkWidget *getWidget() { return m_widget; }
+ YWidget *getChild() { return m_child; }
+};
+
+class YGDialog : public YDialog, public YGWidget
+{
+ int m_padding;
+ GtkWidget *m_containee;
+
+ YGWindow *m_window;
+
+public:
+ YGDialog (YWidgetOpt &opt);
+ virtual ~YGDialog();
+ void showWindow();
+ void hideWindow();
+ GtkWindow *getWindow() { return GTK_WINDOW (m_window->getWidget()); }
+
+ void setCloseCallback (YGWindowCloseFn closeCallback, void *closeData)
+ { m_window->setCloseCallback (closeCallback, closeData); }
+ void unsetCloseCallback()
+ { m_window->unsetCloseCallback(); }
+
+ void normalCursor();
+ void busyCursor();
+
+ YGWIDGET_IMPL_COMMON
+
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (m_containee)
+};
+
+#endif // YGDIALOG_H
+
Added: trunk/gtk/src/YGDumbTab.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGDumbTab.cc?rev=42515&v…
==============================================================================
--- trunk/gtk/src/YGDumbTab.cc (added)
+++ trunk/gtk/src/YGDumbTab.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,118 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.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;
+ vector <GtkWidget *> m_tab_widgets;
+
+public:
+ YGDumbTab (const YWidgetOpt &opt, YGWidget *parent)
+ : YDumbTab (opt),
+ YGWidget (this, parent, true, GTK_TYPE_NOTEBOOK, NULL)
+ {
+ IMPL
+ m_containee = gtk_event_box_new();
+ gtk_widget_show (m_containee);
+ g_object_ref (G_OBJECT (m_containee));
+ gtk_object_sink (GTK_OBJECT (m_containee));
+
+ m_last_tab = 0;
+ // GTK+ keeps the notebook size set to the biggset page. We can't
+ // do this since this is dynamic, but at least don't let the notebook
+ // reduce its size.
+ ygtk_adj_size_set_only_expand (YGTK_ADJ_SIZE (m_adj_size), TRUE);
+
+ g_signal_connect (G_OBJECT (getWidget()), "switch-page",
+ G_CALLBACK (changed_tab_cb), this);
+ }
+
+ ~YGDumbTab()
+ {
+ IMPL
+ gtk_widget_destroy (m_containee);
+ g_object_unref (G_OBJECT (m_containee));
+ }
+
+ virtual void addTab (const YCPString &label_text)
+ {
+ IMPL
+ // the tab label
+ string str = YGUtils::mapKBAccel (label_text->value_cstr());
+ GtkWidget *label = gtk_label_new (str.c_str());
+ gtk_widget_show (label);
+
+ GtkNotebook *notebook = GTK_NOTEBOOK (getWidget());
+ g_signal_handlers_block_by_func (notebook, (gpointer) changed_tab_cb, this);
+
+ GtkWidget *empty = gtk_event_box_new();
+ gtk_widget_show (empty);
+
+ gtk_notebook_append_page (notebook, empty, label);
+ m_tab_widgets.push_back (empty);
+
+ if (!m_last_tab)
+ change_tab (0);
+
+ g_signal_handlers_unblock_by_func (notebook, (gpointer) changed_tab_cb, this);
+ }
+
+ // 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 change_tab (int tab_nb)
+ {
+ if (m_last_tab)
+ gtk_container_remove (GTK_CONTAINER (m_last_tab), m_containee);
+
+ GtkWidget *tab = m_tab_widgets [tab_nb];
+ gtk_container_add (GTK_CONTAINER (tab), m_containee);
+ m_last_tab = tab;
+ }
+
+ virtual int getSelectedTabIndex()
+ {
+ IMPL
+ return gtk_notebook_get_current_page (GTK_NOTEBOOK (getWidget()));
+ }
+
+ virtual void setSelectedTab (int index)
+ {
+ IMPL
+ change_tab (index);
+
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) changed_tab_cb, this);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (getWidget()), index);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) changed_tab_cb, this);
+ }
+
+ static void changed_tab_cb (GtkNotebook *notebook, GtkNotebookPage *page,
+ gint tab_nb, YGDumbTab *pThis)
+ {
+ YCPValue id = pThis->_tabs[tab_nb].id();
+ YGUI::ui()->sendEvent (new YMenuEvent (id));
+
+ pThis->change_tab (tab_nb);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (m_containee)
+};
+
+YWidget *
+YGUI::createDumbTab (YWidget *parent, YWidgetOpt &opt)
+{
+ IMPL
+ return new YGDumbTab (opt, YGWidget::get (parent));
+}
Added: trunk/gtk/src/YGFrame.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGFrame.cc?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGFrame.cc (added)
+++ trunk/gtk/src/YGFrame.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,171 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-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 15
+
+class YGBaseFrame : public YGWidget
+{
+protected:
+// a GtkAlignment to set some indentation on the child
+GtkWidget *m_containee;
+
+public:
+ YGBaseFrame (YWidget *y_widget, YGWidget *parent)
+ : YGWidget (y_widget, parent, true, GTK_TYPE_FRAME,
+ "shadow-type", GTK_SHADOW_NONE, NULL)
+ {
+ IMPL
+ m_containee = gtk_alignment_new (0, 0, 1, 1);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (m_containee), 0, 0, 15, 0);
+ gtk_widget_show (m_containee);
+ gtk_container_add (GTK_CONTAINER (getWidget()), m_containee);
+ }
+ virtual ~YGBaseFrame() {}
+};
+
+#include "YFrame.h"
+
+class YGFrame : public YFrame, public YGBaseFrame
+{
+public:
+ YGFrame (const YWidgetOpt &opt, YGWidget *parent, const YCPString &label)
+ : YFrame (opt, label),
+ YGBaseFrame (this, parent)
+ {
+ GtkWidget *label_widget = gtk_label_new ("");
+ YGUtils::setWidgetFont (GTK_WIDGET (label_widget), PANGO_WEIGHT_BOLD,
+ PANGO_SCALE_MEDIUM);
+ gtk_widget_show (label_widget);
+ gtk_frame_set_label_widget (GTK_FRAME (getWidget()), label_widget);
+ setLabel (label);
+ }
+
+ virtual ~YGFrame() {}
+
+ // YFrame
+ virtual void setLabel (const YCPString &_str)
+ {
+ IMPL
+ /* Get rid of mnemonics; make no sense here. */
+ const char *_cstr = _str->value_cstr();
+ size_t _clen = strlen (_cstr);
+
+ string str;
+ str.reserve (_clen);
+ for (size_t i = 0; i < _clen; i++)
+ if (_cstr[i] != '&')
+ str += _cstr[i];
+
+ GtkWidget *label = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ gtk_label_set_text (GTK_LABEL (label), str.c_str());
+
+ YFrame::setLabel (_str);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YContainerWidget *
+YGUI::createFrame (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ IMPL
+ return new YGFrame (opt, YGWidget::get (parent), label);
+}
+
+#if YAST2_YGUI_CHECKBOX_FRAME
+#include "YCheckBoxFrame.h"
+
+class YGCheckBoxFrame : public YCheckBoxFrame, public YGBaseFrame
+{
+public:
+ YGCheckBoxFrame (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, bool checked)
+ : YCheckBoxFrame (opt, label),
+ YGBaseFrame (this, parent)
+ {
+ IMPL
+ GtkWidget *button = gtk_check_button_new_with_mnemonic("");
+ YGUtils::setWidgetFont (GTK_WIDGET (button), PANGO_WEIGHT_BOLD,
+ PANGO_SCALE_MEDIUM);
+ gtk_widget_show_all (button);
+ gtk_frame_set_label_widget (GTK_FRAME (getWidget()), button);
+
+ setLabel (label);
+ setValue (checked);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (toggled_cb), this);
+ }
+ virtual ~YGCheckBoxFrame() {}
+
+ // YCheckBoxFrame
+ virtual void setLabel (const YCPString &_str)
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ GtkLabel *label = GTK_LABEL (GTK_BIN (button)->child);
+
+ string str (YGUtils::mapKBAccel (_str->value_cstr()));
+ gtk_label_set_text_with_mnemonic (label, str.c_str());
+ YCheckBoxFrame::setLabel (_str);
+ }
+
+ bool getValue()
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ }
+
+ void setValue (bool newValue)
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), newValue);
+ }
+
+ virtual void setEnabling (bool enabled)
+ {
+ GtkWidget *frame = getWidget();
+ if (enabled)
+ {
+ gtk_widget_set_sensitive (frame, TRUE);
+ handleChildrenEnablement (getValue());
+ }
+ else
+ {
+ setChildrenEnabling( false );
+ gtk_widget_set_sensitive (frame, FALSE);
+ }
+ }
+
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+
+private:
+ static void toggled_cb (GtkWidget *widget, YGCheckBoxFrame *pThis)
+ {
+ pThis->setEnabling (true);
+ if (pThis->getNotify())
+ YGUI::ui()->sendEvent (new YWidgetEvent (pThis, YEvent::ValueChanged));
+ }
+};
+
+YContainerWidget *
+YGUI::createCheckBoxFrame (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, bool checked)
+{
+ IMPL
+ return new YGCheckBoxFrame (opt, YGWidget::get (parent), label, checked);
+}
+
+#else
+# warning "Not compiling CheckBoxFrame..."
+#endif /*YAST2_YGUI_CHECKBOX_FRAME*/
Added: trunk/gtk/src/YGImage.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGImage.cc?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGImage.cc (added)
+++ trunk/gtk/src/YGImage.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,287 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include "ygdkmngloader.h"
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YEvent.h"
+#include "YGWidget.h"
+#include "YImage.h"
+
+class YGImage : public YImage, public YGWidget
+{
+ bool m_hasZeroWidth, m_hasZeroHeight, m_isScaled, m_isTiled, m_isAnimation;
+ bool m_imageLoaded;
+
+ struct Animation {
+ GdkPixbufAnimation *pixbuf;
+ GdkPixbufAnimationIter *frame;
+ guint timeout_id;
+ };
+ union {
+ GdkPixbuf *m_pixbuf;
+ Animation *m_animation;
+ };
+ gchar *alt_text;
+
+ void initOptions (const YWidgetOpt &opt)
+ {
+ IMPL
+ m_imageLoaded = false;
+ m_hasZeroWidth = opt.zeroWidth.value();
+ m_hasZeroHeight = opt.zeroHeight.value();
+ m_isAnimation = opt.animated.value();
+ m_isScaled = opt.scaleToFit.value();
+ m_isTiled = opt.tiled.value();
+
+ if (m_hasZeroWidth || m_isScaled || m_isTiled)
+ setStretchable (YD_HORIZ, true);
+ if (m_hasZeroHeight || m_isScaled || m_isTiled)
+ setStretchable (YD_VERT, true);
+
+ if (m_isScaled && m_isTiled) {
+ y2warning ("YImage can't be scaled and tiled at the same time");
+ m_isTiled = false;
+ }
+
+ if (m_isAnimation)
+ m_animation = NULL;
+ else
+ m_pixbuf = NULL;
+
+ g_signal_connect (G_OBJECT (getWidget()), "expose-event",
+ G_CALLBACK (expose_event_cb), this);
+ gtk_widget_queue_draw (getWidget());
+ }
+
+ void loadImage (GdkPixbuf *pixbuf, const char *error_msg)
+ {
+ IMPL
+ if (pixbuf == NULL) {
+ g_warning ("Couldn't load image - %s", error_msg);
+ return;
+ }
+
+ m_imageLoaded = true;
+ m_pixbuf = pixbuf;
+ gtk_widget_set_size_request (getWidget(), m_hasZeroWidth ? -1 : gdk_pixbuf_get_width (pixbuf),
+ m_hasZeroHeight ? -1 : gdk_pixbuf_get_height (pixbuf));
+ }
+
+ void loadAnimation (GdkPixbufAnimation *pixbuf, const char *error_msg)
+ {
+ IMPL
+ if (pixbuf == NULL) {
+ g_warning ("Couldn't load animation - %s", error_msg);
+ return;
+ }
+
+ m_imageLoaded = true;
+ m_animation = new Animation;
+ m_animation->pixbuf = pixbuf;
+
+ m_animation->frame = NULL;
+ advance_frame_cb (this);
+
+ g_signal_connect (G_OBJECT (getWidget()), "expose-event",
+ G_CALLBACK (expose_event_cb), this);
+ gtk_widget_queue_draw (getWidget());
+ }
+
+public:
+ YGImage (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &filename_str, const YCPString &text)
+ : YImage (opt),
+ YGWidget (this, parent, true, GTK_TYPE_DRAWING_AREA, NULL)
+ {
+ IMPL
+ alt_text = g_strdup (text->value_cstr());
+ initOptions (opt);
+
+ const char *filename = filename_str->value_cstr();
+ GError *error = 0;
+ if (m_isAnimation) {
+ GdkPixbufAnimation *pixbuf;
+ if (ygdk_mng_pixbuf_is_file_mng (filename))
+ pixbuf = ygdk_mng_pixbuf_new_from_file (filename, &error);
+ else
+ pixbuf = gdk_pixbuf_animation_new_from_file (filename, &error);
+ loadAnimation (pixbuf, error ? error->message : "(undefined)");
+ }
+ else {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+ loadImage (pixbuf, error ? error->message : "(undefined)");
+ }
+ }
+
+ YGImage (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPByteblock &byteblock, const YCPString &text)
+ : YImage (opt),
+ YGWidget (this, parent, true, GTK_TYPE_DRAWING_AREA, NULL)
+ {
+ IMPL
+ alt_text = g_strdup (text->value_cstr());
+ initOptions (opt);
+
+ GError *error = 0;
+ if (m_isAnimation && ygdk_mng_pixbuf_is_data_mng (byteblock->value(), byteblock->size()))
+ {
+ GdkPixbufAnimation *pixbuf;
+ pixbuf = ygdk_mng_pixbuf_new_from_data (byteblock->value(), byteblock->size(), &error);
+ loadAnimation (pixbuf, error ? error->message : "(undefined)");
+ }
+ else
+ {
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+ g_signal_connect (G_OBJECT (loader), "area-prepared",
+ G_CALLBACK (image_loaded_cb), this);
+
+ if (!gdk_pixbuf_loader_write (loader,
+ byteblock->value(), byteblock->size(), &error))
+ g_warning ("Could not load image from data blocks: %s", error->message);
+ gdk_pixbuf_loader_close (loader, &error);
+ }
+ }
+
+ virtual ~YGImage()
+ {
+ IMPL
+ if (m_imageLoaded) {
+ if (m_isAnimation) {
+ g_object_unref (G_OBJECT (m_animation->pixbuf));
+ if (m_animation->timeout_id)
+ g_source_remove (m_animation->timeout_id);
+ delete m_animation;
+ }
+ else
+ g_object_unref (G_OBJECT (m_pixbuf));
+ }
+ g_free (alt_text);
+ }
+
+ // callback for image loading
+ static void image_loaded_cb (GdkPixbufLoader *loader, YGImage *pThis)
+ {
+ IMPL
+ if (pThis->m_isAnimation) {
+ if (pThis->m_animation) {
+ // a new frame loaded -- just redraw the widget
+ if (gdk_pixbuf_animation_iter_on_currently_loading_frame
+ (pThis->m_animation->frame))
+ gtk_widget_queue_draw (pThis->getWidget());
+ }
+ else {
+ GdkPixbufAnimation *pixbuf = gdk_pixbuf_loader_get_animation (loader);
+ g_object_ref (G_OBJECT (pixbuf));
+ pThis->loadAnimation (pixbuf, " on block data reading callback");
+ }
+ }
+ else {
+ GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ g_object_ref (G_OBJECT (pixbuf));
+ pThis->loadImage (pixbuf, " on block data reading callback");
+ }
+ }
+
+ // callback for image displaying
+ static gboolean advance_frame_cb (void *pData)
+ {
+ IMPL
+ YGImage *pThis = (YGImage *) pData;
+ Animation *animation = pThis->m_animation;
+
+ if (!animation->frame) // no frame yet loaded
+ animation->frame = gdk_pixbuf_animation_get_iter (animation->pixbuf, NULL);
+ else
+ if (gdk_pixbuf_animation_iter_advance (animation->frame, NULL))
+ gtk_widget_queue_draw (pThis->getWidget());
+
+ // shedule next frame
+ int delay = gdk_pixbuf_animation_iter_get_delay_time (animation->frame);
+ if (delay != -1)
+ animation->timeout_id = g_timeout_add (delay, advance_frame_cb, pThis);
+
+ GdkPixbuf *pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (pThis->m_animation->frame);
+ gtk_widget_set_size_request (pThis->getWidget(), gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+ return FALSE;
+ }
+
+ static gboolean expose_event_cb (GtkWidget *widget, GdkEventExpose *event,
+ YGImage *pThis)
+ {
+ IMPL
+ int x, y, width, height;
+ x = widget->allocation.x + 6;
+ y = widget->allocation.y + 6;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ cairo_t *cr = gdk_cairo_create (widget->window);
+
+ if (!pThis->m_imageLoaded) {
+ // show default text if no image was loaded
+ PangoLayout *layout;
+ layout = gtk_widget_create_pango_layout (widget, pThis->alt_text);
+
+ int text_width, text_height;
+ pango_layout_get_size (layout, &text_width, &text_height);
+ text_width /= PANGO_SCALE;
+ text_height /= PANGO_SCALE;
+
+ x += (width - text_width) / 2;
+ y += (height - text_height) / 2;
+
+ cairo_move_to (cr, x, y);
+ pango_cairo_show_layout (cr, layout);
+
+ g_object_unref (layout);
+ cairo_destroy (cr);
+ return TRUE;
+ }
+
+ GdkPixbuf *pixbuf;
+ if (pThis->m_isAnimation)
+ pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (pThis->m_animation->frame);
+ else
+ pixbuf = pThis->m_pixbuf;
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+
+ if (pThis->m_isTiled)
+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+
+ if (pThis->m_isScaled) {
+ double scale_x = (double) gdk_pixbuf_get_width (pixbuf) / width;
+ double scale_y = (double) gdk_pixbuf_get_height (pixbuf) / height;
+ cairo_matrix_t matrix;
+ cairo_matrix_init_scale (&matrix, scale_x, scale_y);
+ cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
+ }
+
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+ return TRUE;
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createImage (YWidget *parent, YWidgetOpt &opt,
+ YCPByteblock image_data, YCPString default_text)
+{
+ IMPL
+ return new YGImage (opt, YGWidget::get (parent), image_data, default_text);
+}
+
+YWidget *
+YGUI::createImage (YWidget *parent, YWidgetOpt &opt,
+ YCPString file_name, YCPString default_text)
+{
+ IMPL
+ return new YGImage (opt, YGWidget::get (parent), file_name, default_text);
+}
Added: trunk/gtk/src/YGIntField.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGIntField.cc?rev=42515&…
==============================================================================
--- trunk/gtk/src/YGIntField.cc (added)
+++ trunk/gtk/src/YGIntField.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,152 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+#define SLIDER_NICESIZE_IN_CHARS 15
+
+class YGSpinBox : public YGLabeledWidget
+{
+ GtkWidget *m_spiner, *m_slider;
+
+public:
+ YGSpinBox (YWidget *y_widget, YGWidget *parent,
+ const YWidgetOpt &opt, const YCPString &label,
+ int minValue, int maxValue, int initialValue,
+ bool show_slider)
+ : YGLabeledWidget (y_widget, parent, label, YD_HORIZ, true,
+ GTK_TYPE_HBOX, 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), TRUE);
+ YGLabeledWidget::setBuddy (m_slider);
+ gtk_widget_set_size_request (m_slider,
+ YGUtils::getCharsWidth (m_slider, SLIDER_NICESIZE_IN_CHARS), -1);
+
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_slider, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_spiner, FALSE, FALSE, 5);
+ 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);
+ g_signal_connect (G_OBJECT (m_spiner), "value-changed",
+ G_CALLBACK (spiner_changed_cb), this);
+ if (m_slider)
+ g_signal_connect (G_OBJECT (m_slider), "value-changed",
+ G_CALLBACK (slider_changed_cb), this);
+ }
+
+ GtkSpinButton *getSpiner()
+ { return GTK_SPIN_BUTTON (m_spiner); }
+
+ bool useSlider()
+ { return m_slider != NULL; }
+ GtkHScale *getSlider()
+ { return GTK_HSCALE (m_slider); }
+
+ virtual void reportValue (int newValue) {}
+
+ void doSetValue (int newValue)
+ {
+ gtk_spin_button_set_value (getSpiner(), newValue);
+ if (useSlider())
+ gtk_range_set_value (GTK_RANGE (getSlider()), newValue);
+ }
+
+ // Events callbacks
+ static void spiner_changed_cb (GtkSpinButton *widget, YGSpinBox *pThis)
+ {
+ int newValue = gtk_spin_button_get_value_as_int (pThis->getSpiner());
+ pThis->reportValue (newValue);
+ if (pThis->useSlider())
+ gtk_range_set_value (GTK_RANGE (pThis->getSlider()), newValue);
+ 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_SET_VALUE_CHAIN(ParentClass) \
+ virtual void reportValue (int newValue) { \
+ ParentClass::setValue (newValue); \
+ } \
+ virtual void setValue (int newValue) { \
+ doSetValue (newValue); \
+ reportValue (newValue); \
+ }
+
+#include "YIntField.h"
+
+class YGIntField : public YIntField, public YGSpinBox
+{
+public:
+ YGIntField (const YWidgetOpt &opt, YGWidget *parent, const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+ : YIntField (opt, label, minValue, maxValue, initialValue)
+ , YGSpinBox (this, parent, opt, label, minValue, maxValue, initialValue, false)
+ { }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YIntField)
+ YGSPIN_BOX_IMPL_SET_VALUE_CHAIN (YIntField)
+};
+
+YWidget *
+YGUI::createIntField (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+{
+ IMPL
+ return new YGIntField (opt, YGWidget::get (parent), label,
+ minValue, maxValue, initialValue);
+}
+
+#include "YSlider.h"
+
+class YGSlider : public YSlider, public YGSpinBox
+{
+public:
+ YGSlider (const YWidgetOpt &opt, YGWidget *parent, const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+ : YSlider (opt, label, minValue, maxValue, initialValue)
+ , YGSpinBox (this, parent, opt, label, minValue, maxValue, initialValue, true)
+ { }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YSlider)
+ YGSPIN_BOX_IMPL_SET_VALUE_CHAIN (YSlider)
+};
+
+YWidget *
+YGUI::createSlider (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+{
+ IMPL
+ return new YGSlider (opt, YGWidget::get (parent), label,
+ minValue, maxValue, initialValue);
+}
Added: trunk/gtk/src/YGLabel.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGLabel.cc?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGLabel.cc (added)
+++ trunk/gtk/src/YGLabel.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,97 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+#include "YLabel.h"
+
+class YGLabel : public YLabel, public YGWidget
+{
+public:
+ YGLabel (const YWidgetOpt &opt, YGWidget *parent, YCPString text)
+ : YLabel (opt, text),
+ YGWidget (this, parent, true, GTK_TYPE_LABEL, NULL)
+ {
+ IMPL
+ gtk_misc_set_alignment (GTK_MISC (getWidget()), 0.0, 0.5);
+ if (opt.isOutputField.value())
+ gtk_label_set_selectable (GTK_LABEL (getWidget()), TRUE);
+
+ if (opt.boldFont.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM);
+ if (opt.isHeading.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_ULTRABOLD, PANGO_SCALE_XX_LARGE);
+ setLabel (text);
+ }
+
+ virtual void setLabel (const YCPString &label)
+ {
+ gtk_label_set_label (GTK_LABEL (getWidget()), label->value_cstr());
+ YLabel::setLabel (label);
+
+ // Some YCP progs have no labeled labels cluttering the layout
+ label->value().empty() ? gtk_widget_hide (getWidget())
+ : gtk_widget_show (getWidget());
+ }
+
+ // YWidget
+ virtual bool doSetKeyboardFocus()
+ { return false; }
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createLabel (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &text)
+{
+ return new YGLabel (opt, YGWidget::get (parent), text);
+}
+
+#include "YColoredLabel.h"
+#include "ygtkbargraph.h"
+
+class YGColoredLabel : public YColoredLabel, public YGWidget
+{
+public:
+ YGColoredLabel (const YWidgetOpt &opt, YGWidget *parent, YCPString text,
+ const YColor &fgColor, const YColor &bgColor, int margin)
+ : YColoredLabel (opt, text),
+ YGWidget (this, parent, true, YGTK_TYPE_COLORED_LABEL, NULL)
+ {
+ IMPL
+ gtk_misc_set_alignment (GTK_MISC (getWidget()), 0.0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (getWidget()), margin, margin);
+
+ if (opt.boldFont.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM);
+ if (opt.isHeading.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_ULTRABOLD, PANGO_SCALE_XX_LARGE);
+ setLabel (text);
+
+ YGtkColoredLabel *color_label = YGTK_COLORED_LABEL (getWidget());
+ ygtk_colored_label_set_shadow_type (color_label, GTK_SHADOW_OUT);
+ ygtk_colored_label_set_foreground (color_label, fgColor.red, fgColor.green, fgColor.blue);
+ ygtk_colored_label_set_background (color_label, bgColor.red, bgColor.green, bgColor.blue);
+ }
+
+ virtual void setLabel (const YCPString &label)
+ {
+ gtk_label_set_label (GTK_LABEL (getWidget()), label->value_cstr());
+ YColoredLabel::setLabel (label);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createColoredLabel (YWidget *parent, YWidgetOpt &opt, YCPString label,
+ YColor fgColor, YColor bgColor, int margin)
+{
+ return new YGColoredLabel (opt, YGWidget::get (parent), label,
+ fgColor, bgColor, margin);
+}
Added: trunk/gtk/src/YGLayout.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGLayout.cc?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/YGLayout.cc (added)
+++ trunk/gtk/src/YGLayout.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,371 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+#include "YGUtils.h"
+
+#include "YSplit.h"
+#include "ygtkratiobox.h"
+#include "YSpacing.h"
+
+// GtkBox-like container (actually, more like our YGtkRatioBox)
+class YGSplit : public YSplit, public YGWidget
+{
+ // This group is meant to set all YGLabeledWidget with horizontal label
+ // to share the same width (if they belong to the same YSplit), so they
+ // look right
+ GtkSizeGroup *m_labels_group;
+
+public:
+ YGSplit (const YWidgetOpt &opt, YGWidget *parent, YUIDimension dim)
+ : YSplit (opt, dim),
+ YGWidget (this, parent, true,
+ dim == YD_HORIZ ? YGTK_TYPE_RATIO_HBOX
+ : YGTK_TYPE_RATIO_VBOX, NULL)
+ {
+ setBorder (0);
+ m_labels_group = NULL;
+ }
+
+ ~YGSplit()
+ {
+ if (m_labels_group)
+ g_object_unref (G_OBJECT (m_labels_group));
+ }
+
+ virtual void childAdded (YWidget *ychild)
+ {
+ IMPL
+ YGWidget *ygchild = YGWidget::get (ychild);
+
+ gtk_container_add (GTK_CONTAINER (getWidget()), ygchild->getLayout());
+ sync_stretchable (ychild);
+
+ // set labels of YGLabeledWidgets to the same width
+ // we have to do quite some work due to over-clutter on YCP progs
+ while (ychild) {
+ if (ychild->isContainer()) {
+ // try to see if there is a YGLabeledWidget at start
+ // (and ignore YSpacings)
+ YContainerWidget *container = (YContainerWidget *) ychild;
+ if (container->numChildren())
+ for (int i = 0; i < container->numChildren(); i++) {
+ ychild = container->child (i);
+ if (!dynamic_cast <YSpacing *> (ychild))
+ break;
+ }
+ else // no kids
+ break;
+ }
+ else {
+ ygchild = YGWidget::get (ychild);
+ YGLabeledWidget *labeled_child = dynamic_cast <YGLabeledWidget *> (ygchild);
+ if (labeled_child && labeled_child->orientation() == YD_HORIZ) {
+ if (!m_labels_group)
+ m_labels_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (m_labels_group,
+ labeled_child->getLabelWidget());
+ }
+ break;
+ }
+ }
+ }
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+
+ virtual void sync_stretchable (YWidget *ychild)
+ {
+ IMPL
+ YGtkRatioBox *box = YGTK_RATIO_BOX (getWidget());
+ YGWidget *child = YGWidget::get (ychild);
+
+ YUIDimension dim = dimension();
+ bool horiz_fill = child->isStretchable (YD_HORIZ)
+ || ychild->hasWeight (YD_HORIZ);
+ bool vert_fill = child->isStretchable (YD_VERT)
+ || ychild->hasWeight (YD_VERT);
+
+ ygtk_ratio_box_set_child_packing (box, child->getLayout(), ychild->weight (dim),
+ horiz_fill, vert_fill, 0);
+ ygtk_ratio_box_set_child_expand (box, child->getLayout(),
+ child->isStretchable (dim),
+ ychild->isLayoutStretch (dim));
+ YGWidget::sync_stretchable();
+ }
+
+ virtual void moveChild (YWidget *, long, long) {}; // ignore
+};
+
+YContainerWidget *
+YGUI::createSplit (YWidget *parent, YWidgetOpt &opt, YUIDimension dimension)
+{
+ IMPL
+ return new YGSplit (opt, YGWidget::get (parent), dimension);
+}
+
+#include "YAlignment.h"
+
+class YGAlignment : public YAlignment, public YGWidget
+{
+ GdkPixbuf *m_background_pixbuf;
+
+public:
+ YGAlignment (const YWidgetOpt &opt, YGWidget *parent,
+ YAlignmentType halign, YAlignmentType valign)
+ : YAlignment (opt, halign, valign),
+ YGWidget (this, parent, true, GTK_TYPE_ALIGNMENT, NULL)
+ {
+ setBorder (0);
+ m_background_pixbuf = 0;
+ }
+
+ virtual ~YGAlignment()
+ {
+ if (m_background_pixbuf)
+ g_object_unref (G_OBJECT (m_background_pixbuf));
+ }
+
+ virtual void childAdded (YWidget *ychild)
+ {
+ YGWidget *child = YGWidget::get (ychild);
+ gtk_container_add (GTK_CONTAINER (getWidget()), child->getLayout());
+
+ /* The padding is used for stuff like making YCP progs nicer for
+ yast-qt wizard, so it hurts us -- it's disabled. */
+ //child->setPadding (topMargin(), bottomMargin(),
+ // leftMargin(), rightMargin());
+ setMinSize (minWidth(), minHeight());
+
+ sync_stretchable (ychild); // alignment will be set here
+ }
+ YGWIDGET_IMPL_CHILD_REMOVED (m_widget)
+
+ virtual void sync_stretchable (YWidget *child)
+ {
+ IMPL
+ setAlignment (align [YD_HORIZ], align [YD_VERT]);
+ YGWidget::sync_stretchable (m_y_widget);
+ }
+
+ void setAlignment (YAlignmentType halign, YAlignmentType valign)
+ {
+ // special case (which YAlignment.cc also uses); let stretchable
+ // children stretch if opt.stretch is set (exploitable by the wizard)
+ GValue hstretch, vstretch;
+ hstretch = YGUtils::floatToGValue (0);
+ if (_stretch [YD_HORIZ] && YGWidget::get (child (0))->isStretchable (YD_HORIZ))
+ hstretch = YGUtils::floatToGValue (1);
+ vstretch = YGUtils::floatToGValue (0);
+ if (_stretch [YD_VERT] && YGWidget::get (child (0))->isStretchable (YD_VERT))
+ vstretch = YGUtils::floatToGValue (1);
+
+ if (halign != YAlignUnchanged) {
+ GValue xalign = YGUtils::floatToGValue (yToGtkAlign (halign));
+ g_object_set_property (G_OBJECT (getWidget()), "xalign", &xalign);
+ g_object_set_property (G_OBJECT (getWidget()), "xscale", &hstretch);
+ }
+ if (valign != YAlignUnchanged) {
+ GValue yalign = YGUtils::floatToGValue (yToGtkAlign (valign));
+ g_object_set_property (G_OBJECT (getWidget()), "yalign", &yalign);
+ g_object_set_property (G_OBJECT (getWidget()), "yscale", &vstretch);
+ }
+ }
+
+ void setPadding (int top, int bottom, int left, int right)
+ {
+ gtk_alignment_set_padding (GTK_ALIGNMENT (getWidget()),
+ top, bottom, left, right);
+ }
+
+ virtual void setBackgroundPixmap (string filename)
+ {
+ // YAlignment will prepend a path to the image
+ YAlignment::setBackgroundPixmap (filename);
+ 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;
+ }
+
+ virtual void moveChild (YWidget *, long, long) {}; // ignore
+
+ virtual string getDebugLabel() const
+ {
+ struct inner {
+ static const char *alignLabel (YAlignmentType align)
+ {
+ switch (align) {
+ case YAlignUnchanged:
+ return "unchanged";
+ case YAlignBegin:
+ return "begin";
+ case YAlignEnd:
+ return "end";
+ case YAlignCenter:
+ return "center";
+ }
+ return ""; /*not run*/
+ }
+ };
+
+ string str;
+ str += inner::alignLabel (align [YD_HORIZ]);
+ str += " x ";
+ str += inner::alignLabel (align [YD_VERT]);
+ return str;
+ }
+
+private:
+ // helper -- converts YWidget YAlignmentType to Gtk's align float
+ static float yToGtkAlign (YAlignmentType align)
+ {
+ switch (align) {
+ case YAlignBegin: return 0.0;
+ default:
+ case YAlignCenter: return 0.5;
+ case YAlignEnd: return 1.0;
+ }
+ }
+};
+
+YContainerWidget *
+YGUI::createAlignment (YWidget *parent, YWidgetOpt &opt,
+ YAlignmentType halign, YAlignmentType valign)
+{
+ IMPL
+ return new YGAlignment (opt, YGWidget::get (parent), halign, valign);
+}
+
+#include "YEmpty.h"
+
+// Just an empty space.
+class YGEmpty : public YEmpty, public YGWidget
+{
+public:
+ YGEmpty (const YWidgetOpt &opt, YGWidget *parent)
+ : YEmpty (opt),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+};
+
+YWidget *
+YGUI::createEmpty (YWidget *parent, YWidgetOpt &opt)
+{
+ IMPL
+ return new YGEmpty (opt, YGWidget::get (parent));
+}
+
+#include "YSpacing.h"
+
+// Empty space, with a fixed size.
+class YGSpacing : public YSpacing, public YGWidget
+{
+public:
+ YGSpacing (const YWidgetOpt &opt, YGWidget *parent,
+ float size, bool horizontal, bool vertical)
+ : YSpacing (opt, size, horizontal, vertical),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ gtk_widget_set_size_request (getWidget(), width(), height());
+ }
+};
+
+YWidget *
+YGUI::createSpacing (YWidget *parent, YWidgetOpt & opt, float size,
+ bool horiz, bool vert)
+{
+ IMPL
+ return new YGSpacing (opt, YGWidget::get (parent), size, horiz, vert);
+}
+
+#include "YReplacePoint.h"
+
+// an empty space that will get replaced
+class YGReplacePoint : public YReplacePoint, public YGWidget
+{
+public:
+ YGReplacePoint (const YWidgetOpt &opt, YGWidget *parent)
+ : YReplacePoint (opt),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CHILD_ADDED (getWidget())
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YContainerWidget *
+YGUI::createReplacePoint( YWidget *parent, YWidgetOpt & opt )
+{
+ IMPL
+ return new YGReplacePoint (opt, YGWidget::get (parent));
+}
+
+#include "YSquash.h"
+
+// 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 (const YWidgetOpt &opt, YGWidget *parent,
+ bool hsquash, bool vsquash)
+ : YSquash (opt, hsquash, vsquash),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CHILD_ADDED (getWidget())
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YContainerWidget *
+YGUI::createSquash (YWidget *parent, YWidgetOpt &opt,
+ bool hsquash, bool vsquash)
+{
+ IMPL
+ return new YGSquash (opt, YGWidget::get (parent), hsquash, vsquash);
+}
Added: trunk/gtk/src/YGMenuButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGMenuButton.cc?rev=4251…
==============================================================================
--- trunk/gtk/src/YGMenuButton.cc (added)
+++ trunk/gtk/src/YGMenuButton.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,79 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YMenuButton.h"
+#include "ygtkmenubutton.h"
+
+class YGMenuButton : public YMenuButton, public YGWidget
+{
+public:
+ YGMenuButton (const YWidgetOpt &opt,
+ YGWidget *parent,
+ YCPString label)
+ : YMenuButton (opt, label),
+ YGWidget (this, parent, true, YGTK_TYPE_MENU_BUTTON, NULL)
+ {
+ IMPL
+ setLabel (label);
+ }
+
+ virtual ~YGMenuButton() {}
+
+ // YMenuButton
+ virtual void setLabel (const YCPString &label)
+ {
+ IMPL
+ string str = YGUtils::mapKBAccel (label->value_cstr());
+ ygtk_menu_button_set_label (YGTK_MENU_BUTTON (getWidget()), str.c_str());
+ YMenuButton::setLabel (label);
+ }
+
+ // YMenuButton
+ virtual void createMenu()
+ {
+ GtkWidget *menu = doCreateMenu (getToplevelMenu()->itemList());
+ gtk_widget_show_all (menu);
+ ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (getWidget()), menu);
+ }
+
+ static GtkWidget* doCreateMenu (YMenuItemList &items)
+ {
+ GtkWidget *menu = gtk_menu_new();
+ for (YMenuItemListIterator it = items.begin(); it != items.end(); it++) {
+ GtkWidget *entry;
+ string str = YGUtils::mapKBAccel ((*it)->getLabel()->value_cstr());
+ entry = gtk_menu_item_new_with_mnemonic (str.c_str());
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), entry);
+
+ if ((*it)->hasChildren())
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (entry),
+ doCreateMenu ((*it)->itemList()));
+ else
+ g_signal_connect (G_OBJECT (entry), "activate",
+ G_CALLBACK (selected_item_cb), *it);
+ }
+
+ return menu;
+ }
+
+ static void selected_item_cb (GtkMenuItem *menuitem, YMenuItem *yitem)
+ {
+ YGUI::ui()->sendEvent (new YMenuEvent (yitem->getId()));
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createMenuButton (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ return new YGMenuButton (opt, YGWidget::get (parent), label);
+}
Added: trunk/gtk/src/YGMultiLineEdit.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGMultiLineEdit.cc?rev=4…
==============================================================================
--- trunk/gtk/src/YGMultiLineEdit.cc (added)
+++ trunk/gtk/src/YGMultiLineEdit.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,247 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include <string>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+class YGTextView : public YGScrolledWidget
+{
+int maxChars;
+
+public:
+ YGTextView (YWidget *y_widget, YGWidget *parent, const YWidgetOpt &opt,
+ const YCPString &label, const YCPString &text, bool editable)
+ : YGScrolledWidget (y_widget, parent, label, YD_VERT, true,
+ GTK_TYPE_TEXT_VIEW, "wrap-mode", GTK_WRAP_WORD, NULL)
+ {
+ IMPL
+ if (!opt.isShrinkable.value())
+ setMinSizeInChars (20, 10);
+ setPolicy (GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ maxChars = -1;
+ setText (text);
+
+ if (!editable)
+ {
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (getWidget()), FALSE);
+ gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (getWidget()), FALSE);
+ }
+
+ g_signal_connect (G_OBJECT (getBuffer()), "changed",
+ G_CALLBACK (text_changed_cb), this);
+ }
+
+ GtkTextBuffer* getBuffer()
+ { return gtk_text_view_get_buffer (GTK_TEXT_VIEW (getWidget())); }
+
+ int getCharsNb()
+ {
+ IMPL
+ return gtk_text_buffer_get_char_count (getBuffer());
+ }
+
+ void setCharsNb (int max_chars)
+ {
+ IMPL
+ maxChars = max_chars;
+ if (maxChars != -1 && getCharsNb() > maxChars)
+ truncateText (maxChars);
+ }
+
+ void truncateText(int pos)
+ {
+ IMPL
+ 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);
+
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) text_changed_cb, this);
+ gtk_text_buffer_delete (getBuffer(), &start_it, &end_it);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) text_changed_cb, this);
+ }
+
+ void setText (const YCPString &text)
+ {
+ IMPL
+ gtk_text_buffer_set_text (getBuffer(), text->value_cstr(), -1);
+ }
+
+ YCPString getText()
+ {
+ IMPL
+ 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);
+ YCPString str (text);
+ g_free (text);
+ return str;
+ }
+
+ void scrollToBottom()
+ {
+ YGUtils::scrollTextViewDown (GTK_TEXT_VIEW (getWidget()));
+ }
+
+ // Event callbacks
+ static void text_changed_cb (GtkTextBuffer *buffer, YGTextView *pThis)
+ {
+ if (pThis->maxChars != -1 && pThis->getCharsNb() > pThis->maxChars) {
+ pThis->truncateText (pThis->maxChars);
+ gdk_beep();
+ }
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+};
+
+#include "YMultiLineEdit.h"
+
+class YGMultiLineEdit : public YMultiLineEdit, public YGTextView
+{
+public:
+ YGMultiLineEdit (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, const YCPString &text)
+ : YMultiLineEdit (opt, label)
+ , YGTextView (this, parent, opt, label, text, true)
+ { }
+
+ // YMultiLineEdit
+ virtual void setText (const YCPString &text)
+ { YGTextView::setText (text); }
+
+ virtual YCPString text()
+ { return YGTextView::getText(); }
+
+ virtual void setInputMaxLength (const YCPInteger &numberOfChars)
+ { YGTextView::setCharsNb (numberOfChars->asInteger()->value()); }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YMultiLineEdit)
+};
+
+YWidget *
+YGUI::createMultiLineEdit (YWidget *parent, YWidgetOpt & opt,
+ const YCPString & label, const YCPString & text)
+{
+ return new YGMultiLineEdit (opt, YGWidget::get (parent), label, text);
+}
+
+#include "YLogView.h"
+
+class YGLogView : public YLogView, public YGTextView
+{
+public:
+ YGLogView (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, int visibleLines, int maxLines)
+ : YLogView (opt, label, visibleLines, maxLines)
+ , YGTextView (this, parent, opt, label, YCPString(""), false)
+ {
+ setMinSizeInChars (0, visibleLines);
+ }
+
+ // YLogView
+ virtual void setLogText (const YCPString &text)
+ {
+ setText (text);
+ scrollToBottom();
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YLogView)
+};
+
+YWidget *
+YGUI::createLogView (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, int visibleLines,
+ int maxLines)
+{
+ return new YGLogView (opt, YGWidget::get (parent),
+ label, visibleLines, maxLines);
+}
+
+#include "YRichText.h"
+
+class YGPlainText : public YRichText, public YGTextView
+{
+bool m_autoScrollDown;
+
+public:
+ YGPlainText(const YWidgetOpt &opt, YGWidget *parent, const YCPString &text)
+ : YRichText (opt, text)
+ , YGTextView (this, parent, opt, YCPString(""), text, false)
+ {
+ IMPL
+ m_autoScrollDown = opt.autoScrollDown.value();
+ }
+
+ // YRichText
+ virtual void setText (const YCPString &text)
+ {
+ IMPL
+ YGTextView::setText (text);
+ if (m_autoScrollDown)
+ scrollToBottom();
+ YRichText::setText (text);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+#include "ygtkhtmlwrap.h"
+
+class YGRichText : public YRichText, public YGScrolledWidget
+{
+bool m_autoScrollDown;
+
+public:
+ YGRichText(const YWidgetOpt &opt, YGWidget *parent, const YCPString &text)
+ : YRichText (opt, text)
+ , YGScrolledWidget (this, parent, true, ygtk_html_wrap_get_type(), NULL)
+ {
+ IMPL
+ if (!opt.isShrinkable.value())
+ setMinSizeInChars (20, 8);
+ m_autoScrollDown = opt.autoScrollDown.value();
+
+ ygtk_html_wrap_init (getWidget());
+ ygtk_html_wrap_connect_link_clicked (getWidget(), G_CALLBACK (link_clicked_cb), this);
+
+ setText (text);
+ }
+
+ // YRichText
+ virtual void setText (const YCPString &_text)
+ {
+ IMPL
+ string text (_text->value());
+ YGUtils::replace (text, "&product;", 9, YUI::ui()->productName().c_str());
+
+ ygtk_html_wrap_set_text (getWidget(), text.c_str());
+ if (m_autoScrollDown)
+ ygtk_html_wrap_scroll (getWidget(), FALSE);
+ YRichText::setText (_text);
+ }
+
+ static void link_clicked_cb (GtkWidget *widget, const char *url, YGRichText *pThis)
+ {
+ YGUI::ui()->sendEvent (new YMenuEvent (YCPString (url)));
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createRichText (YWidget *parent, YWidgetOpt &opt, const YCPString &text)
+{
+ if (opt.plainTextMode.value())
+ return new YGPlainText (opt, YGWidget::get (parent), text);
+ else
+ return new YGRichText (opt, YGWidget::get (parent), text);
+}
+
Added: trunk/gtk/src/YGPackageSelector.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGPackageSelector.cc?rev…
==============================================================================
--- trunk/gtk/src/YGPackageSelector.cc (added)
+++ trunk/gtk/src/YGPackageSelector.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,2680 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/*
+ Textdomain "yast2-gtk"
+*/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGi18n.h"
+#include "YGDialog.h"
+#include "YPackageSelector.h"
+#include "ygtkhtmlwrap.h"
+#include "ygtkwizard.h"
+#include "ygtkcellrendererarrow.h"
+#include "ygtkratiobox.h"
+#include "ygtkfindentry.h"
+
+#include <map>
+
+//#define DISABLE_PACKAGE_SELECTOR
+
+#ifndef DISABLE_PACKAGE_SELECTOR
+#include <zypp/ZYppFactory.h>
+#include <zypp/ResObject.h>
+#include <zypp/ResPoolProxy.h>
+#include <zypp/ui/Selectable.h>
+#include <zypp/Patch.h>
+#include <zypp/Selection.h>
+#include <zypp/Package.h>
+#include <zypp/Pattern.h>
+#include <zypp/Language.h>
+#include <zypp/Product.h>
+#ifdef PRE_ZYPP_3
+#include <zypp/Source.h>
+#include <zypp/SourceManager.h>
+#else
+#include <zypp/Repository.h>
+#include <zypp/RepoManager.h>
+#endif
+
+/* We should consider linking to libgnome and use gnome_url_show(url) here,
+ or at least do some path finding. */
+#define FILEMANAGER_EXEC "/usr/bin/nautilus"
+inline bool FILEMANAGER_PRESENT()
+{ return g_file_test (FILEMANAGER_EXEC, G_FILE_TEST_IS_EXECUTABLE); }
+inline void FILEMANAGER_LAUNCH (const char *path)
+{ system ((string (FILEMANAGER_EXEC) + " " + path + " &").c_str()); }
+
+// some typedefs and functions to short Zypp names
+typedef zypp::ResPoolProxy ZyppPool;
+inline ZyppPool zyppPool() { return zypp::getZYpp()->poolProxy(); }
+typedef zypp::ui::Selectable::Ptr ZyppSelectable;
+typedef zypp::ui::Selectable* ZyppSelectablePtr;
+typedef zypp::ResObject::constPtr ZyppObject;
+typedef zypp::Package::constPtr ZyppPackage;
+typedef zypp::Patch::constPtr ZyppPatch;
+typedef zypp::Pattern::constPtr ZyppPattern;
+typedef zypp::Language::constPtr ZyppLanguage;
+inline ZyppPackage tryCastToZyppPkg (ZyppObject obj)
+ { return zypp::dynamic_pointer_cast <const zypp::Package> (obj); }
+inline ZyppPatch tryCastToZyppPatch (ZyppObject obj)
+ { return zypp::dynamic_pointer_cast <const zypp::Patch> (obj); }
+inline ZyppPattern tryCastToZyppPattern (ZyppObject obj)
+ { return zypp::dynamic_pointer_cast <const zypp::Pattern> (obj); }
+inline ZyppLanguage tryCastToZyppLanguage (ZyppObject obj)
+ { return zypp::dynamic_pointer_cast <const zypp::Language> (obj); }
+
+static zypp::Text
+fastGetSummary (ZyppObject obj)
+{
+ static std::map<std::string, zypp::Text> name_to_summary;
+ std::string &summary = name_to_summary[ obj->name() ];
+ if (summary.length() <= 0)
+ summary = obj->summary();
+ return summary;
+}
+
+// Computer icon comes from Tango, but may not be installed, or not initialized.
+#include "computer.xpm"
+
+static bool acceptLicense (ZyppSelectablePtr sel)
+{
+ if (sel->hasLicenceConfirmed())
+ return true;
+
+ ZyppObject object = sel->candidateObj();
+ ZyppPackage package = tryCastToZyppPkg (object);
+ if (!package)
+ return true;
+
+ const string &license = package->licenseToConfirm();
+ if (license.empty()) {
+ sel->setLicenceConfirmed (true);
+ return true;
+ }
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons (_("License Agreement"),
+ YGUI::ui()->currentWindow(), GTK_DIALOG_MODAL,
+ _("_Reject"), GTK_RESPONSE_REJECT, _("_Accept"), GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkWidget *license_view, *license_window;
+
+ license_view = ygtk_html_wrap_new();
+ ygtk_html_wrap_set_text (license_view, license.c_str());
+
+ license_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (license_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (license_window), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (license_window), license_view);
+
+ GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox);
+ gtk_box_pack_start (vbox, license_window, TRUE, TRUE, 6);
+
+ const char *print_text = _("If you would like to print this license, check the EULA.txt file on the first media");
+ GtkLabel *print_label = GTK_LABEL (gtk_label_new (print_text));
+ gtk_box_pack_start (vbox, GTK_WIDGET (print_label), FALSE, TRUE, 2);
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400);
+ gtk_widget_show_all (dialog);
+
+ bool confirmed = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT;
+ gtk_widget_destroy (dialog);
+
+ sel->setLicenceConfirmed (confirmed);
+ return confirmed;
+}
+
+// install / remove convinience wrapper. You only need to specify an object
+// if you want that particular version to be installed.
+// returns true on sucess
+static bool mark_selectable (ZyppSelectablePtr selectable, bool install /*or remove*/)
+{
+ zypp::ui::Status status = selectable->status();
+
+ if (install) {
+ if (!selectable->hasCandidateObj()) {
+ y2warning ("YGPackageSelector: no package on repository to install");
+ return false;
+ }
+ if (!acceptLicense (selectable))
+ return false;
+ if (status == zypp::ui::S_Del)
+ status = zypp::ui::S_KeepInstalled;
+ else {
+ if (status == zypp::ui::S_KeepInstalled)
+ status = zypp::ui::S_Update;
+ else
+ status = zypp::ui::S_Install;
+ }
+ }
+ else /*remove*/ {
+ if (status == zypp::ui::S_NoInst)
+ ; // do nothing
+ else if (status == zypp::ui::S_Install)
+ status = zypp::ui::S_NoInst;
+ else if (status == zypp::ui::S_Update)
+ status = zypp::ui::S_KeepInstalled;
+ else
+ status = zypp::ui::S_Del;
+ }
+
+#if 0 // debug
+ const char *name = selectable->name().c_str();
+ switch (status) {
+ case zypp::ui::S_KeepInstalled:
+ y2milestone ("keep %s installed\n", name);
+ break;
+ case zypp::ui::S_Update:
+ y2milestone ("update %s\n", name);
+ break;
+ case zypp::ui::S_Install:
+ y2milestone ("install %s\n", name);
+ break;
+ case zypp::ui::S_Del:
+ y2milestone ("remove %s\n", name);
+ break;
+ case zypp::ui::S_NoInst:
+ y2milestone ("don't install %s\n", name);
+ break;
+ default:
+ y2milestone ("error: unknown action: should not happen\n");
+ break;
+ }
+#endif
+
+ return selectable->set_status (status);
+}
+
+// tries to solve possible dependencies problems and asks the user for
+// manual resolution if needed (there is not much space for interface
+// design here)
+static bool solveProblems()
+{
+ IMPL
+ zypp::Resolver_Ptr resolver = zypp::getZYpp()->resolver();
+ if (resolver->resolvePool())
+ return true;
+ zypp::ResolverProblemList problems = resolver->problems();
+ if (problems.empty())
+ return true;
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Resolve Problems"),
+ YGUI::ui()->currentWindow(), GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("C_onfirm"), GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkWidget *problems_view;
+ problems_view = gtk_tree_view_new();
+
+ GtkWidget *problems_window;
+ problems_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (problems_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (problems_window), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (problems_window), problems_view);
+
+ GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox);
+ gtk_box_pack_start (vbox, problems_window, TRUE, TRUE, 0);
+
+ // create model
+ // the vairous columns are: radio button active (boolean), problem
+ // or solution description (string), is radio button (boolean: always
+ // true), show radio button (boolean; false for problems)
+ GtkTreeStore *problems_store = gtk_tree_store_new (4,
+ G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
+ // install view
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *radio_renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes ("",
+ radio_renderer, "active", 0, "radio", 2, "visible", 3, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (problems_view), column);
+ g_signal_connect (G_OBJECT (radio_renderer), "toggled",
+ G_CALLBACK (YGUtils::tree_view_radio_toggle_cb),
+ GTK_TREE_MODEL (problems_store));
+
+ column = gtk_tree_view_column_new_with_attributes (_("Problems"),
+ gtk_cell_renderer_text_new(), "text", 1, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (problems_view), column);
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (problems_view), FALSE);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (problems_view),
+ GTK_TREE_MODEL (problems_store));
+ g_object_unref (G_OBJECT (problems_store));
+
+ // construct model
+ GtkTreeIter piter, siter;
+ map <GtkTreePath *, zypp::ProblemSolution *> users_actions;
+ for (zypp::ResolverProblemList::iterator it = problems.begin();
+ it != problems.end(); it++) {
+ zypp::ProblemSolutionList solutions = (*it)->solutions();
+
+ gtk_tree_store_append (problems_store, &piter, NULL);
+ gtk_tree_store_set (problems_store, &piter, 0, FALSE,
+ 1, (*it)->description().c_str(), 2, TRUE, 3, FALSE, -1);
+
+ for (zypp::ProblemSolutionList::iterator jt = solutions.begin();
+ jt != solutions.end(); jt++) {
+ gtk_tree_store_append (problems_store, &siter, &piter);
+ gtk_tree_store_set (problems_store, &siter, 0, FALSE,
+ 1, (*jt)->description().c_str(), 2, TRUE, 3, TRUE, -1);
+ users_actions [gtk_tree_model_get_path (GTK_TREE_MODEL (
+ problems_store), &siter)] = get_pointer (*jt);
+ }
+ }
+
+ // set tree properties
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (problems_view)), GTK_SELECTION_NONE);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (problems_view));
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400);
+ gtk_widget_show_all (dialog);
+
+ bool confirmed = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT;
+
+ if (confirmed) {
+ // apply user solutions
+ zypp::ProblemSolutionList userChoices;
+
+ GtkTreeIter iter;
+ for (map <GtkTreePath *, zypp::ProblemSolution *>::iterator it
+ = users_actions.begin(); it != users_actions.end(); it++) {
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (problems_store),
+ &iter, it->first);
+ gboolean state = FALSE;
+ gtk_tree_model_get (GTK_TREE_MODEL (problems_store), &iter,
+ 0, &state, -1);
+ if (state)
+ userChoices.push_back (it->second);
+
+ gtk_tree_path_free (it->first);
+ }
+ resolver->applySolutions (userChoices);
+ }
+
+ gtk_widget_destroy (dialog);
+ if (confirmed)
+ // repeate the all process as things may not yet be solved
+ return solveProblems();
+ return false;
+}
+
+#ifdef PRE_ZYPP_3
+static string getSourceName (zypp::Source_Ref source)
+{ // based on yast-qt's singleProduct()
+ if (!source.enabled())
+ // can't get name if disabled; strangely, source.resolvables().begin()
+ // hangs
+ return "";
+ string ret;
+ bool found = false;
+ for (zypp::ResStore::iterator it = source.resolvables().begin();
+ it != source.resolvables().end(); it++) {
+ zypp::Product::Ptr product;
+ product = zypp::dynamic_pointer_cast <zypp::Product> (*it);
+ if (product) {
+ if (found) {
+ y2milestone ("Multiple products on installation source %s",
+ source.alias().c_str());
+ return "";
+ }
+ found = true;
+ ret = fastGetSummary (product);
+ }
+ }
+
+ if (!found)
+ y2milestone ("No product on installation source %s",
+ source.alias().c_str());
+ return ret;
+}
+#endif
+
+#define PACKAGE_INFO_HEIGHT 140
+#define ADVANCED_INFO_HEIGHT 80
+
+// Expander widget with the package information
+class PackageInformation
+{
+ GtkWidget *m_widget, *m_notebook;
+ // Information text
+ GtkWidget *m_about_text, *m_authors_text, *m_filelist_text, *m_changelog_text;
+ bool m_use_filemanager;
+
+public:
+ PackageInformation (const char *expander_text, bool only_description)
+ {
+ m_widget = gtk_expander_new (expander_text);
+ gtk_widget_set_sensitive (m_widget, FALSE);
+
+ if (only_description) {
+ GtkWidget *about_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (about_win),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ m_about_text = ygtk_html_wrap_new();
+ gtk_container_add (GTK_CONTAINER (about_win), m_about_text);
+ gtk_container_add (GTK_CONTAINER (m_widget), about_win);
+ m_authors_text = m_filelist_text = m_changelog_text = NULL;
+ m_notebook = NULL;
+ }
+ else {
+ m_notebook = gtk_notebook_new();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (m_notebook), GTK_POS_BOTTOM);
+ gtk_container_add (GTK_CONTAINER (m_widget), m_notebook);
+
+ m_about_text = add_text_tab (m_notebook, _("Description"));
+ m_filelist_text = add_text_tab (m_notebook, _("File List"));
+ if ((m_use_filemanager = FILEMANAGER_PRESENT()))
+ ygtk_html_wrap_connect_link_clicked (m_filelist_text,
+ G_CALLBACK (dir_pressed_cb), NULL);
+ m_changelog_text = add_text_tab (m_notebook, _("Change Log"));
+ m_authors_text = add_text_tab (m_notebook, _("Authors"));
+ }
+ gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (m_widget)),
+ -1, PACKAGE_INFO_HEIGHT);
+ }
+
+ GtkWidget *getWidget()
+ { return m_widget; }
+
+ void setPackage (ZyppSelectablePtr selectable, ZyppObject object)
+ {
+ if (!selectable || !object) {
+ if (m_about_text)
+ set_text (m_about_text, "");
+ if (m_filelist_text)
+ set_text (m_filelist_text, "");
+ if (m_changelog_text)
+ set_text (m_changelog_text, "");
+ if (m_authors_text)
+ set_text (m_authors_text, "");
+ gtk_expander_set_expanded (GTK_EXPANDER (m_widget), FALSE);
+ gtk_widget_set_sensitive (m_widget, FALSE);
+ return;
+ }
+
+ /* Keep notebook on first page; but only when not visible to not
+ annoy the user. */
+ if (m_notebook && !gtk_expander_get_expanded (GTK_EXPANDER (m_widget)))
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (m_notebook), 0);
+ gtk_widget_set_sensitive (m_widget, TRUE);
+
+ ZyppPackage package = tryCastToZyppPkg (object);
+ if (m_about_text) {
+ string description = YGUtils::escape_markup (object->description(), true);
+
+ // cut authors, since they have their own section
+ string::size_type pos = description.find ("Authors:");
+ if (pos != string::npos)
+ description.erase (pos, string::npos);
+
+ string str;
+ if (package) {
+ description += "<br>";
+ str = package->url();
+ if (!str.empty())
+ description += _("Website: ") + str + "<br>";
+ str = package->license();
+ if (!str.empty())
+ description += _("License: ") + str + "<br>";
+ description += _("Size: ") + object->size().asString() + "b<br>";
+ }
+
+#ifdef PRE_ZYPP_3
+ zypp::Source_Ref source = object->source();
+ str = getSourceName (source);
+ if (str.empty())
+ str = source.url().asString();
+ else
+ str = str + " (" + source.url().asString() + ")";
+#else
+ zypp::Repository repo = object->repository();
+ str = repo.info().name();
+#endif
+ if (!str.empty())
+ description += _("Repository: ") + str;
+
+ set_text (m_about_text, description);
+ }
+ if (package) {
+ if (m_filelist_text) {
+ string filelist;
+ const std::list <string> &filenames = package->filenames();
+ for (std::list <string>::const_iterator it = filenames.begin();
+ it != filenames.end(); it++) {
+ string file (*it);
+ // don't show created dirs
+ if (g_file_test (file.c_str(), G_FILE_TEST_IS_DIR))
+ continue;
+ // set the path as a link
+ if (m_use_filemanager) {
+ string::size_type pos = file.find_last_of ('/');
+ if (pos != string::npos) { // should be always true
+ string dirname (file, 0, pos+1);
+ string basename (file, pos+1, string::npos);
+ file = "<a href=" + dirname + ">" + dirname + "</a>" + basename;
+ }
+ }
+ filelist += file + "<br>";
+ }
+ set_text (m_filelist_text, filelist);
+ }
+ if (m_changelog_text) {
+ string text;
+ const std::list <zypp::ChangelogEntry> &changelog = package->changelog();
+ for (std::list <zypp::ChangelogEntry>::const_iterator it = changelog.begin();
+ it != changelog.end(); it++) {
+ string t = "<blockquote>" + YGUtils::escape_markup (it->text(), true) +
+ "</blockquote>";
+ text += "<p>" + it->date().asString() + ""
+ + YGUtils::escape_markup (it->author()) + ":<br>"
+ + t + "</p>";
+ }
+ set_text (m_changelog_text, text);
+ }
+ if (m_authors_text) {
+ string packager (YGUtils::escape_markup (package->packager())), authors;
+
+ const std::list <string> &authors_list = package->authors();
+ if (!authors_list.empty()) {
+ for (std::list <string>::const_iterator it = authors_list.begin();
+ it != authors_list.end(); it++)
+ authors += *it;
+ }
+ else {
+// TODO: stuff changed on YGUtils, descript. and this needs to be reviewd
+ /* authors() should be the proper way to get authors, but it seems to
+ be rarely used, instead packagers list them on the description. */
+ string description (object->description());
+//std::cerr << "description: " << description << std::endl;
+ string::size_type pos = description.find ("Authors:");
+ if (pos != string::npos) {
+ pos = description.find_first_not_of (
+ '-', pos + sizeof ("Authors:") + 1);
+//std::cerr << "copy string from " << pos << std::endl;
+ authors = string (description, pos, string::npos);
+ authors = YGUtils::escape_markup (authors, true);
+//std::cerr << "authors: " << authors << std::endl;
+ }
+ }
+
+ string text;
+ if (!packager.empty())
+ text = _("Packaged by:") + ("<blockquote>" + packager) +
+ "</blockquote>";
+ if (!authors.empty()) {
+ if (!packager.empty())
+ text += "<br><br>";
+ text += _("Developed by:") + ("<blockquote>" + authors) +
+ "</blockquote>";
+ }
+ set_text (m_authors_text, text);
+ }
+ }
+ else {
+ if (m_filelist_text)
+ set_text (m_filelist_text, "");
+ if (m_changelog_text)
+ set_text (m_changelog_text, "");
+ if (m_authors_text)
+ set_text (m_authors_text, "");
+ }
+ }
+
+private:
+ // auxiliaries to cut down on code
+ static GtkWidget *add_text_tab (GtkWidget *notebook, const char *label)
+ {
+ GtkWidget *widget, *scroll_win;
+ scroll_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_win),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ widget = ygtk_html_wrap_new();
+ gtk_container_add (GTK_CONTAINER (scroll_win), widget);
+
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scroll_win,
+ gtk_label_new (label));
+ return widget;
+ }
+
+ static void set_text (GtkWidget *widget, const string &text)
+ {
+ const char *str = _("<i>(not available)</i>");
+ if (!text.empty())
+ str = text.c_str();
+ ygtk_html_wrap_set_text (widget, str);
+ ygtk_html_wrap_scroll (widget, TRUE); // scroll to the start
+ }
+
+ /* When a directory is pressed on the file list. */
+ static void dir_pressed_cb (GtkWidget *text, const gchar *link)
+ { FILEMANAGER_LAUNCH (link); }
+};
+
+// Table widget with package sources
+ /* I don't like this, since it differs from the rest of the code, but to
+ avoid declarations... */
+ struct SourcesTableListener
+ {
+ virtual ~SourcesTableListener() {}
+ virtual void sources_changed_cb() = 0;
+ };
+class SourcesTable
+{
+ GtkWidget *m_widget;
+ GtkTreeModel *m_model;
+ SourcesTableListener *m_listener;
+
+public:
+ SourcesTable (SourcesTableListener *listener)
+ : m_listener (listener)
+ {
+ /* 0 - source enabled?, 1 - source name (estimation), 2 - source URL,
+ 3 - source id; what they call of alias. */
+ GtkListStore *store = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING);
+ m_model = GTK_TREE_MODEL (store);
+
+#ifdef PRE_ZYPP_3
+ zypp::SourceManager_Ptr manager = zypp::SourceManager::sourceManager();
+ for (zypp::SourceManager::Source_const_iterator it = manager->Source_begin();
+ it != manager->Source_end(); it++) {
+ zypp::Source_Ref src = *it;
+ if (src && src.enabled()) {
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, src.enabled(),
+ 1, getSourceName (src).c_str(), 2, src.url().asString().c_str(),
+ 3, src.alias().c_str(), -1);
+ }
+ }
+#else
+ zypp::RepoManager manager;
+ std::list <zypp::RepoInfo> repos = manager.knownRepositories();
+ for (std::list <zypp::RepoInfo>::iterator it = repos.begin();
+ it != repos.end(); it++) {
+ if (it->enabled()) {
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, bool(it->enabled()),
+ 1, it->name().c_str(), 2, it->alias().c_str(), -1);
+ }
+ }
+#endif
+
+ GtkWidget *view = gtk_tree_view_new_with_model (m_model);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)),
+ GTK_SELECTION_NONE);
+ g_object_unref (G_OBJECT (m_model)); // tree view will take care of it
+
+ // prepare the view
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes ("",
+ renderer, "active", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (source_toggled_cb), this);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes ("",
+ renderer, "text", 1, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+#ifdef PRE_ZYPP_3
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes ("",
+ renderer, "text", 2, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+#endif
+
+ m_widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_size_request (m_widget, -1, ADVANCED_INFO_HEIGHT);
+ gtk_container_add (GTK_CONTAINER (m_widget), view);
+ }
+
+ GtkWidget *getWidget()
+ { return m_widget; }
+
+private:
+ static void source_toggled_cb (GtkCellRendererToggle *renderer,
+ gchar *path_str, SourcesTable *pThis)
+ {
+ IMPL
+ GtkTreeModel *model = pThis->m_model;
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+#ifdef PRE_ZYPP_3
+ gchar *alias;
+ gtk_tree_model_get (model, &iter, 3, &alias, -1);
+
+ zypp::SourceManager_Ptr manager = zypp::SourceManager::sourceManager();
+ zypp::Source_Ref source = manager->findSource (alias);
+ g_free (alias);
+
+ if (gtk_cell_renderer_toggle_get_active (renderer))
+ source.disable();
+ else
+ source.enable();
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ 0, source.enabled(), -1);
+#else
+ gchar *alias;
+ gtk_tree_model_get (model, &iter, 2, &alias, -1);
+
+ zypp::RepoManager manager;
+ zypp::RepoInfo repo = manager.getRepositoryInfo (alias);
+ g_free (alias);
+
+ bool enable = !gtk_cell_renderer_toggle_get_active (renderer);
+ repo.setEnabled (enable);
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ 0, bool (repo.enabled()), -1);
+#endif
+
+ pThis->m_listener->sources_changed_cb();
+ }
+};
+
+// Table widget to monitor disk partitions space-usage
+#define MIN_FREE_MB_WARN (80*1024)
+
+class DiskTable
+{
+ GtkWidget *m_widget;
+ GtkTreeModel *m_model;
+ bool m_has_warned; // only warn once
+
+ // evil long names
+ typedef zypp::DiskUsageCounter::MountPoint ZyppDu;
+ typedef zypp::DiskUsageCounter::MountPointSet ZyppDuSet;
+ typedef zypp::DiskUsageCounter::MountPointSet::iterator ZyppDuSetIterator;
+
+public:
+ DiskTable()
+ {
+ m_has_warned = false;
+ if (zypp::getZYpp()->diskUsage().empty())
+ zypp::getZYpp()->setPartitions (
+ zypp::DiskUsageCounter::detectMountPoints());
+
+ /* 0 - mount point (also used as id), 1 - percentage of disk usage
+ ([0, 100]), 2 - disk usage detail (i.e. "200Mb of 1Gb") */
+ GtkListStore *store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_INT,
+ G_TYPE_STRING);
+ m_model = GTK_TREE_MODEL (store);
+ update();
+
+ GtkWidget *view = gtk_tree_view_new_with_model (m_model);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)),
+ GTK_SELECTION_NONE);
+ g_object_unref (G_OBJECT (m_model)); // tree view will take care of it
+
+ // prepare the view
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes (_("Mount Point"),
+ renderer, "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+ renderer = gtk_cell_renderer_progress_new();
+ column = gtk_tree_view_column_new_with_attributes (_("Usage"),
+ renderer, "value", 1, "text", 2, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+ m_widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_size_request (m_widget, -1, ADVANCED_INFO_HEIGHT);
+ gtk_container_add (GTK_CONTAINER (m_widget), view);
+ }
+
+ GtkWidget *getWidget()
+ { return m_widget; }
+
+ static string sizeToString (long long size)
+ {
+ zypp::ByteCount count (size, zypp::ByteCount::K);
+ return count.asString();
+ }
+
+ void update()
+ {
+ GtkListStore *store = GTK_LIST_STORE (m_model);
+ gtk_list_store_clear (store);
+
+ bool warning = false;
+ ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
+ for (ZyppDuSetIterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
+ const ZyppDu &partition = *it;
+ if (!partition.readonly) {
+ // partition fields: dir, used_size, total_size (size on Kb)
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+
+ long usage = (partition.pkg_size * 100) / (partition.total_size + 1);
+ string usage_str = sizeToString (partition.pkg_size) + " (of " +
+ sizeToString (partition.total_size) + ")";
+ gtk_list_store_set (store, &iter, 0, partition.dir.c_str(),
+ 1, usage, 2, usage_str.c_str(), -1);
+
+ warning = warning ||
+ (partition.total_size > 1024 &&
+ partition.total_size - partition.pkg_size < MIN_FREE_MB_WARN);
+ }
+ }
+ if (warning)
+ warn();
+ }
+
+ void warn()
+ {
+ if (m_has_warned)
+ return;
+ m_has_warned = true;
+
+ GtkWidget *dialog, *view, *scroll_view;
+ dialog = gtk_message_dialog_new_with_markup (YGUI::ui()->currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK, _("<b>Disk Almost Full !</b>\n\n"
+ "One of the partitions is reaching its limit of capacity. You may "
+ "have to remove packages if you wish to install some."));
+
+ view = gtk_tree_view_new_with_model (m_model);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)),
+ GTK_SELECTION_NONE);
+
+ GtkTreeViewColumn *column;
+ column = gtk_tree_view_column_new_with_attributes (_("Mount Point"),
+ gtk_cell_renderer_text_new(), "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+ column = gtk_tree_view_column_new_with_attributes (_("Usage"),
+ gtk_cell_renderer_progress_new(),
+ "value", 1, "text", 2, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+ scroll_view = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_view),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_size_request (scroll_view, -1, 80);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll_view),
+ GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (scroll_view), view);
+ gtk_widget_show_all (scroll_view);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scroll_view);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+};
+
+// YOU patch selector
+class YGPatchSelector : public YPackageSelector, public YGWidget
+{
+ GtkWidget *m_patches_view;
+ GtkTreeModel *m_patches_model; // GtkListStore type
+
+ // Package information widget
+ PackageInformation *m_information_widget;
+
+public:
+ YGPatchSelector (const YWidgetOpt &opt, YGWidget *parent)
+ : YPackageSelector (opt),
+ YGWidget (this, parent, true, YGTK_TYPE_WIZARD, NULL)
+ {
+ setBorder (0);
+ GtkWidget *main_vbox = gtk_vbox_new (FALSE, 0);
+
+ YGtkWizard *wizard = YGTK_WIZARD (getWidget());
+ ygtk_wizard_set_child (YGTK_WIZARD (getWidget()), main_vbox);
+ GtkWindow *window = YGUI::ui()->currentWindow();
+ ygtk_wizard_set_header_text (wizard, window, _("Patch Selector"));
+ ygtk_wizard_set_header_icon (wizard, window,
+ THEMEDIR "/icons/32x32/apps/yast-software.png");
+ ygtk_wizard_set_help_text (wizard,
+ _("For information on a given patch, just press it and as well as the "
+ "Package Information expander to make those informations visible.<br>"
+ "To install a patch you just need to press the check button next to it "
+ "and then the button Install when you are done.")
+ );
+ ygtk_wizard_set_next_button_label (wizard, _("_Install"));
+ ygtk_wizard_set_next_button_id (wizard, g_strdup ("install"), g_free);
+ ygtk_wizard_set_abort_button_label (wizard, _("_Cancel"));
+ ygtk_wizard_set_abort_button_id (wizard, g_strdup ("cancel"), g_free);
+ g_signal_connect (G_OBJECT (getWidget()), "action-triggered",
+ G_CALLBACK (wizard_action_cb), this);
+
+ m_patches_view = gtk_tree_view_new();
+ GtkWidget *patches_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (patches_window), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (patches_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add (GTK_CONTAINER (patches_window), m_patches_view);
+
+ m_information_widget = new PackageInformation (_("Patch Information"), true);
+ GtkWidget *pkg_info_widget = m_information_widget->getWidget();
+
+ gtk_box_pack_start (GTK_BOX (main_vbox), patches_window, TRUE, TRUE, 6);
+ gtk_box_pack_start (GTK_BOX (main_vbox), pkg_info_widget, FALSE, FALSE, 6);
+ gtk_widget_show_all (main_vbox);
+
+ // Create a model for the patches lists
+ // models' columns: selected radio button state (boolean),
+ // package name (string), patch priority (string), selectable object (pointer)
+ m_patches_model = GTK_TREE_MODEL (gtk_list_store_new
+ (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
+
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes ("", renderer,
+ "active", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (m_patches_view), column);
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (patch_toggled_cb), this);
+
+ column = gtk_tree_view_column_new_with_attributes (_("Priority"),
+ gtk_cell_renderer_text_new(), "text", 1, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (m_patches_view), column);
+
+ column = gtk_tree_view_column_new_with_attributes (_("Name"),
+ gtk_cell_renderer_text_new(), "text", 2, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (m_patches_view), column);
+
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Patch>();
+ it != zyppPool().byKindEnd <zypp::Patch>(); it++) {
+ ZyppSelectable selectable = *it;
+ ZyppPatch patch = tryCastToZyppPatch (selectable->theObj());
+ if (!patch)
+ continue;
+ bool displayPatch = false;
+
+ // These rules are taken from YQPkgPatchList::fillList() in the RelevantPatches case
+ if (selectable->hasInstalledObj()) { // installed?
+ if (selectable->installedPoolItem().status().isIncomplete()) { // patch broken?
+ // The patch is broken: It had been installed, but the user somehow
+ // downgraded individual packages belonging to the patch to older versions.
+ displayPatch = true;
+
+ y2warning( "Installed patch is broken: %s - %s",
+ patch->name().c_str(),
+ patch->summary().c_str() );
+ }
+ } else { // not installed
+ if (selectable->hasCandidateObj() && selectable->candidatePoolItem().status().isSatisfied()) {
+ // This is a pretty exotic case, but still it might happen:
+ //
+ // The patch itelf is not installed, but it is satisfied because the
+ // user updated all the packages belonging to the patch to the versions
+ // the patch requires. All that is missing now is to get the patch meta
+ // data onto the system. So let's display the patch to give the user
+ // a chance to install it (if he so chooses).
+
+ displayPatch = true;
+
+ y2milestone( "Patch satisfied, but not installed yet: %s - %s",
+ patch->name().c_str(),
+ patch->summary().c_str() );
+ }
+ }
+
+ if (selectable->hasCandidateObj()) { // candidate available?
+ // The most common case: There is a candidate patch, i.e. one that could be
+ // installed, but either no version of that patch is installed or there is a
+ // newer one to which the patch could be updated.
+
+ if (selectable->candidatePoolItem().status().isNeeded()) { // patch really needed?
+ // Patches are needed if any of the packages that belong to the patch
+ // are installed on the system.
+
+ displayPatch = true;
+ } else {
+ // None of the packages that belong to the patch is installed on the system.
+
+ y2debug( "Patch not needed: %s - %s",
+ patch->name().c_str(),
+ patch->summary().c_str() );
+ }
+ }
+
+ if (displayPatch) {
+ // select them all
+ selectable->set_status (zypp::ui::S_Install);
+
+ GtkTreeIter iter;
+ GtkListStore *store = GTK_LIST_STORE (m_patches_model);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, selectable->toInstall(),
+ 1, patch->category().c_str(), 2, selectable->name().c_str(),
+ 3, get_pointer (selectable), -1);
+ }
+ }
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (m_patches_view), m_patches_model);
+
+ // TODO: severity should be sort by severity, not alphabetically
+ YGUtils::tree_view_set_sortable (GTK_TREE_VIEW (m_patches_view), 1);
+
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_patches_view), 2);
+
+ g_signal_connect (G_OBJECT (m_patches_view), "cursor-changed",
+ G_CALLBACK (patch_clicked_cb), this);
+ }
+
+ virtual ~YGPatchSelector()
+ {
+ IMPL
+ g_object_unref (m_patches_model);
+ delete m_information_widget;
+ }
+
+ static ZyppSelectablePtr selectedPatch (GtkTreeView *tree_view)
+ {
+ IMPL
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ gtk_tree_view_get_cursor (tree_view, &path, &column);
+ if (path) {
+ GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
+
+ ZyppSelectablePtr selectable = 0;
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_model_get (model, &iter, 3, &selectable, -1);
+
+ gtk_tree_path_free (path);
+ return selectable;
+ }
+ return NULL;
+ }
+
+ // callbacks
+ static void patch_clicked_cb (GtkTreeView *tree_view, YGPatchSelector *pThis)
+ {
+ IMPL
+ ZyppSelectablePtr sel = selectedPatch (tree_view);
+ pThis->m_information_widget->setPackage (sel, sel->theObj());
+ }
+
+ static void wizard_action_cb (YGtkWizard *wizard, gpointer id,
+ gint id_type, YGPatchSelector *pThis)
+ {
+ const gchar *action = (gchar *) id;
+ if (!strcmp (action, "install")) {
+ y2milestone ("Closing PackageSelector with 'accept'");
+ if (solveProblems())
+ YGUI::ui()->sendEvent (new YMenuEvent (YCPSymbol ("accept")));
+ }
+ else if (!strcmp (action, "cancel")) {
+ y2milestone ("Closing PackageSelector with 'cancel'");
+ YGUI::ui()->sendEvent (new YCancelEvent());
+ }
+ }
+
+ static void patch_toggled_cb (GtkCellRendererToggle *renderer,
+ gchar *path_str, YGPatchSelector *pThis)
+ {
+ IMPL
+ GtkTreeModel *model = pThis->m_patches_model;
+
+ // Toggle the box
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ gint *column = (gint*) g_object_get_data (G_OBJECT (renderer), "column");
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ gboolean state;
+ ZyppSelectablePtr selectable = 0;
+ gtk_tree_model_get (model, &iter, 0, &state, 3, &selectable, -1);
+
+ state = !state;
+ if (mark_selectable (selectable, state))
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter, column, state, -1);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+// Package selector's widget
+class PackageSelector : public SourcesTableListener
+{
+
+enum package_columns
+{
+ COL_SELECTABLE = 0, // selectable object (pointer)
+ COL_INSTALLED_NAME, // installed name (string)
+ COL_AVAILABLE_NAME, // available_name (string)
+ COL_IS_INSTALLED, // is installed (boolean)
+ COL_IS_AVAILABLE, // is available (boolean)
+ COL_CAN_BE_UPGRADED, // can be upgraded (boolean)
+ COL_CAN_BE_DOWNGRADED, // can be downgraded (boolean)
+ COL_SHOW_UPGRADABLE_CONTROL, // show up/downgrade control (boolean)
+ COL_HAS_CHILDREN, // has children
+ COL_FONT_STYLE // font style; italic for modified (integer) = 10
+};
+
+friend class YGPackageSelector;
+
+ GtkWidget *m_widget;
+
+ // The GtkTreeView widgets
+ GtkWidget *m_installed_view, *m_available_view;
+ // Packages backend model
+ GtkTreeModel *m_packages_model;
+
+ // Package information widget
+ PackageInformation *m_information_widget;
+ SourcesTable *m_sources_table;
+ DiskTable *m_disk_table;
+
+ // Search gizmos
+ GtkWidget *m_search_entry, *m_plain_view;
+ guint search_timeout_id;
+ bool name_opt, summary_opt, descr_opt, provides_opt, requires_opt;
+ list <string> m_search_queries;
+
+ // Interface tweak
+ GtkWidget *m_install_label, *m_remove_label;
+
+public:
+ PackageSelector (bool patterns_mode)
+ {
+ IMPL
+ m_widget = gtk_vbox_new (FALSE, 0);
+
+ GtkWidget *packages_hbox = gtk_hbox_new (FALSE, 0);
+
+ GtkWidget *available_box, *installed_box;
+ /* All views share a similar model structure. There is a common model for
+ all packages, where filters are installed upon to split it on two, each
+ installed on the tree view. The common model follows the following spec:
+ 0 - selectable object (pointer), 1 - installed name (string), 2 - available
+ name (string), 3 - is installed (boolean), 4 - is available (boolean),
+ 5 - can be upgraded (boolean), 6 - can be downgraded (boolean),
+ 7 - show up/downgrade control (boolean), 8 - has children,
+ 9 - font style; italic for modified (integer) = 10
+
+ Models are created at each view mode change (and the other freed). This
+ allows for more than one model type be used and is also better for speed,
+ since the filter and tree view then installed upon don't have to keep
+ syncing at every item change. */
+ installed_box = createListWidget (_("<b>Installed Software:</b>"),
+ "computer", computer_xpm, m_installed_view,
+ 1, false);
+ available_box = createListWidget (_("<b>Available Software:</b>"),
+ "gtk-cdrom", NULL, m_available_view,
+ 2, true);
+
+ /* FIXME: it seems (due to markup or something) search, this won't work.
+ Not really a issue as we provide searching, but...
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_installed_view), 0);
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (m_available_view), 0); */
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (m_installed_view), FALSE);
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (m_available_view), FALSE);
+
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (m_installed_view)), GTK_SELECTION_MULTIPLE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (m_available_view)), GTK_SELECTION_MULTIPLE);
+
+ GtkWidget *buttons_minsize, *selection_buttons_vbox, *install_button,
+ *remove_button;
+ selection_buttons_vbox = gtk_vbox_new (TRUE, 80);
+ // to avoid re-labeling glitches, let it only grow
+ buttons_minsize = ygtk_adj_size_new();
+ gtk_container_add (GTK_CONTAINER (buttons_minsize), selection_buttons_vbox);
+ ygtk_adj_size_set_only_expand (YGTK_ADJ_SIZE (buttons_minsize), TRUE);
+
+ install_button = createArrowButton (_("_install"), GTK_ARROW_RIGHT, &m_install_label);
+ remove_button = createArrowButton (_("_remove"), GTK_ARROW_LEFT, &m_remove_label);
+
+ GtkWidget *install_align = gtk_alignment_new (0, 1, 1, 0);
+ gtk_container_add (GTK_CONTAINER (install_align), install_button);
+ GtkWidget *remove_align = gtk_alignment_new (0, 0, 1, 0);
+ gtk_container_add (GTK_CONTAINER (remove_align), remove_button);
+
+ gtk_box_pack_start (GTK_BOX (selection_buttons_vbox), install_align,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (selection_buttons_vbox), remove_align,
+ TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (selection_buttons_vbox), 6);
+
+ gtk_box_pack_start (GTK_BOX (packages_hbox), available_box, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (packages_hbox), buttons_minsize,
+ FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (packages_hbox), installed_box, TRUE, TRUE, 0);
+
+ GtkWidget *view_box, *view_label, *view_categories, *view_patterns,
+ *view_languages;
+ view_label = gtk_label_new (_("View Packages:"));
+ gtk_label_set_use_markup (GTK_LABEL (view_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (view_label), 0, 0.5);
+ m_plain_view = gtk_radio_button_new_with_mnemonic (NULL, _("as _plain list"));
+ view_categories = gtk_radio_button_new_with_mnemonic_from_widget
+ (GTK_RADIO_BUTTON (m_plain_view), _("in _categories"));
+ view_patterns = gtk_radio_button_new_with_mnemonic_from_widget
+ (GTK_RADIO_BUTTON (m_plain_view), _("in _patterns"));
+ view_languages = gtk_radio_button_new_with_mnemonic_from_widget
+ (GTK_RADIO_BUTTON (m_plain_view), _("in _languages"));
+ view_box = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (view_box), view_label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (view_box), m_plain_view, FALSE, TRUE, 4);
+ gtk_box_pack_start (GTK_BOX (view_box), view_categories, FALSE, TRUE, 4);
+ gtk_box_pack_start (GTK_BOX (view_box), view_patterns, FALSE, TRUE, 4);
+ gtk_box_pack_start (GTK_BOX (view_box), view_languages, FALSE, TRUE, 4);
+ g_signal_connect (G_OBJECT (m_plain_view), "toggled",
+ G_CALLBACK (view_plain_mode_cb), this);
+ g_signal_connect (G_OBJECT (view_categories), "toggled",
+ G_CALLBACK (view_categories_mode_cb), this);
+ g_signal_connect (G_OBJECT (view_patterns), "toggled",
+ G_CALLBACK (view_patterns_mode_cb), this);
+ g_signal_connect (G_OBJECT (view_languages), "toggled",
+ G_CALLBACK (view_languages_mode_cb), this);
+
+ // default search fields
+ name_opt = summary_opt = provides_opt = true;
+ requires_opt = descr_opt = false;
+
+ GtkWidget *search_hbox, *search_label;
+ search_hbox = gtk_hbox_new (FALSE, 0);
+ search_label = gtk_label_new_with_mnemonic (_("_Search:"));
+ gtk_label_set_use_markup (GTK_LABEL (search_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (search_label), 0, 0.5);
+ m_search_entry = ygtk_find_entry_new();
+ gtk_label_set_mnemonic_widget (GTK_LABEL (search_label), m_search_entry);
+ gtk_box_pack_start (GTK_BOX (search_hbox), search_label, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (search_hbox), m_search_entry, TRUE, TRUE, 4);
+ search_timeout_id = 0;
+ g_signal_connect (G_OBJECT (m_search_entry), "activate", // when Enter
+ G_CALLBACK (search_activate_cb), this); // is pressed
+ g_signal_connect_after (G_OBJECT (m_search_entry), "changed",
+ G_CALLBACK (search_request_cb), this);
+ ygtk_find_entry_attach_menu (YGTK_FIND_ENTRY (m_search_entry),
+ create_search_menu());
+
+ /* we want "View Packages" to be aligned to "Search"; we could use a
+ GtkTable for that, but a GtkSizeGroup does the job with less hassle. */
+ GtkSizeGroup *align_labels = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (align_labels, view_label);
+ gtk_size_group_add_widget (align_labels, search_label);
+ g_object_unref (G_OBJECT (align_labels));
+
+ m_information_widget = new PackageInformation (_("Package Information"), false);
+ GtkWidget *pkg_info_widget = m_information_widget->getWidget();
+
+ m_sources_table = new SourcesTable (this);
+ m_disk_table = new DiskTable();
+
+ GtkWidget *advanced_expander = gtk_expander_new (_("Advanced"));
+ GtkWidget *advanced_notebook = gtk_notebook_new();
+ GtkWidget *sources_vbox = gtk_vbox_new (FALSE, 4);
+ GtkWidget *sources_label = gtk_label_new (
+ _("<i>Use the Software Repositories tool to manage the sources.</i>"));
+ gtk_misc_set_alignment (GTK_MISC (sources_label), 1, 0);
+ gtk_label_set_use_markup (GTK_LABEL (sources_label), TRUE);
+ gtk_box_pack_start (GTK_BOX (sources_vbox), m_sources_table->getWidget(),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (sources_vbox), sources_label, TRUE, TRUE, 0);
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (advanced_notebook), GTK_POS_BOTTOM);
+ gtk_notebook_append_page (GTK_NOTEBOOK (advanced_notebook),
+ sources_vbox, gtk_label_new (_("Repositories")));
+ gtk_notebook_append_page (GTK_NOTEBOOK (advanced_notebook),
+ m_disk_table->getWidget(), gtk_label_new (_("Disk Usage")));
+ gtk_container_add (GTK_CONTAINER (advanced_expander), advanced_notebook);
+
+ gtk_box_pack_start (GTK_BOX (m_widget), packages_hbox, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (m_widget), view_box, FALSE, FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (m_widget), search_hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (m_widget), pkg_info_widget, FALSE, FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (m_widget), advanced_expander, FALSE, FALSE, 0);
+ gtk_widget_show_all (m_widget);
+
+ g_object_ref (G_OBJECT (m_widget));
+ gtk_object_sink (GTK_OBJECT (m_widget));
+
+ // interface sugar
+ g_signal_connect (G_OBJECT (install_button), "clicked",
+ G_CALLBACK (install_button_clicked_cb), this);
+ g_signal_connect (G_OBJECT (remove_button), "clicked",
+ G_CALLBACK (remove_button_clicked_cb), this);
+
+ g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (
+ m_installed_view))), "changed",
+ G_CALLBACK (package_clicked_cb), this);
+ g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (
+ m_available_view))), "changed",
+ G_CALLBACK (package_clicked_cb), this);
+
+ // signal for default view
+ if (patterns_mode)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view_patterns), TRUE);
+ else
+ g_signal_emit_by_name (G_OBJECT (m_plain_view), "toggled", this);
+ }
+
+ // create widgets functions to cut down on code
+ GtkWidget *createListWidget (const char *header, const char *stock_icon,
+ const char **xpm_icon, GtkWidget *&list, int package_name_col,
+ bool has_version_col)
+ {
+ GtkWidget *vbox, *header_hbox, *image, *label, *scrolled_window;
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ list = gtk_tree_view_new();
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (list), TRUE);
+ gtk_tree_selection_set_select_function (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (list)), dont_select_groups_cb, this, NULL);
+ gtk_container_add (GTK_CONTAINER (scrolled_window), list);
+
+ header_hbox = gtk_hbox_new (FALSE, 0);
+ image = NULL;
+ if (stock_icon)
+ image = gtk_image_new_from_icon_name (stock_icon, GTK_ICON_SIZE_BUTTON);
+ if ((!stock_icon || gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY)
+ && xpm_icon) {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (xpm_icon);
+ image = gtk_image_new_from_pixbuf (pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ label = gtk_label_new_with_mnemonic (header);
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), list);
+ if (image)
+ gtk_box_pack_start (GTK_BOX (header_hbox), image, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (header_hbox), label, FALSE, FALSE, 4);
+
+ gtk_box_pack_start (GTK_BOX (vbox), header_hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 4);
+
+ // The treeview model will be built according to the view... Columns
+ // and renderers are common anyway...
+ GtkCellRenderer *text_renderer = gtk_cell_renderer_text_new();
+ g_object_set (G_OBJECT (text_renderer),
+ "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ GtkTreeViewColumn *column;
+ column = gtk_tree_view_column_new_with_attributes (_("Packages"),
+ text_renderer, "markup", package_name_col, "style", 9, NULL);
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+ // versions combo column
+ if (has_version_col) {
+ GtkCellRenderer *arrow_renderer = ygtk_cell_renderer_arrow_new();
+ column = gtk_tree_view_column_new_with_attributes (NULL,
+ arrow_renderer, "can-go-up", 5, "can-go-down", 6, "visible", 7, NULL);
+ gtk_tree_view_column_set_expand (column, FALSE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+ g_signal_connect (G_OBJECT (arrow_renderer), "pressed",
+ G_CALLBACK (change_available_version_cb), this);
+ }
+ return vbox;
+ }
+
+ GtkWidget *createArrowButton (const char *label, GtkArrowType arrow_type,
+ GtkWidget **label_widget)
+ {
+ GtkWidget *button, *box = gtk_hbox_new (FALSE, 0);
+ GtkWidget *arrow = gtk_arrow_new (arrow_type, GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (box), arrow);
+ *label_widget = gtk_label_new_with_mnemonic (label);
+ gtk_container_add (GTK_CONTAINER (box), *label_widget);
+ gtk_box_set_child_packing (GTK_BOX (box), arrow, FALSE, TRUE, 0,
+ arrow_type == GTK_ARROW_LEFT ? GTK_PACK_START : GTK_PACK_END);
+
+ button = gtk_button_new();
+ gtk_container_add (GTK_CONTAINER (button), box);
+ return button;
+ }
+
+ // Dynamic views support
+ void load_packages_view (GtkTreeModel *(* build_model) (GtkProgressBar *))
+ {
+ GtkWidget *dialog, *label, *vbox, *progress = 0;
+ dialog = gtk_dialog_new();
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ YGUI::ui()->currentWindow());
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 100, -1);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ vbox = GTK_DIALOG (dialog)->vbox;
+// gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
+ label = gtk_label_new (_("Loading packages list..."));
+ gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 4);
+ progress = gtk_progress_bar_new();
+ gtk_box_pack_start (GTK_BOX (vbox), progress, TRUE, FALSE, 4);
+ gtk_widget_show_all (dialog);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (m_installed_view), NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (m_available_view), NULL);
+ m_information_widget->setPackage (NULL, NULL);
+
+ GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (progress);
+ // build it
+ GtkTreeModel *model = (m_packages_model = build_model (progress_bar));
+
+ GtkTreeModel *installed_model, *available_model;
+ installed_model = gtk_tree_model_filter_new (model, NULL);
+ available_model = gtk_tree_model_filter_new (model, NULL);
+ g_object_unref (G_OBJECT (model));
+
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (
+ installed_model), is_package_installed, this, NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (
+ available_model), is_package_available, this, NULL);
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (m_installed_view), installed_model);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (m_available_view), available_model);
+ g_object_unref (G_OBJECT (installed_model));
+ g_object_unref (G_OBJECT (available_model));
+
+ // use the "available" name to do the sorting
+ GtkTreeSortable *sortable = GTK_TREE_SORTABLE (model);
+ gtk_tree_sortable_set_sort_func (sortable, COL_AVAILABLE_NAME,
+ YGUtils::sort_compare_cb,
+ GINT_TO_POINTER (COL_AVAILABLE_NAME),
+ NULL);
+ gtk_tree_sortable_set_sort_column_id (sortable, COL_AVAILABLE_NAME,
+ GTK_SORT_ASCENDING);
+
+ gtk_widget_destroy (dialog);
+ }
+
+ // macros to handle progress bar
+ #define SET_PROGRESS(_steps, _jump) int steps = _steps, step = 0, jump = _jump;
+ #define PROGRESS() \
+ if (progress && ((step++) % jump == 0)) { \
+ gdouble fraction = steps > 0 ? ((gdouble) step) / steps : 0; \
+ gtk_progress_bar_set_fraction (progress, fraction); \
+ while (gtk_events_pending()) gtk_main_iteration(); }
+
+ static GtkTreeModel *loadPackagesListAsPlain (GtkProgressBar *progress)
+ {
+ GtkListStore *store = gtk_list_store_new (10, G_TYPE_POINTER, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT);
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (1));
+
+ SET_PROGRESS (zyppPool().size <zypp::Package>(), 200)
+ GtkTreeIter iter;
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>();
+ it != zyppPool().byKindEnd <zypp::Package>(); it++)
+ {
+ ZyppSelectable selectable = *it;
+ gtk_list_store_append (store, &iter);
+ loadPackageRow (model, &iter, selectable);
+ PROGRESS()
+ }
+ return model;
+ }
+
+ static GtkTreeModel *loadPackagesListByCategory (GtkProgressBar *progress)
+ {
+ GtkTreeStore *store = gtk_tree_store_new (10, G_TYPE_POINTER, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT);
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (1));
+
+ // we need to create the categories tree as we iterate packages
+ map <string, GtkTreePath *> tree;
+
+ SET_PROGRESS (zyppPool().size <zypp::Package>(), 80)
+ GtkTreeIter iter, parent_iter;
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>();
+ it != zyppPool().byKindEnd <zypp::Package>(); it++)
+ {
+ ZyppSelectable selectable = *it;
+ ZyppObject object = selectable->theObj();
+
+ GtkTreePath *path = NULL;
+ ZyppPackage package = tryCastToZyppPkg (object);
+ if (package) {
+ // group is a string like "Productivity/Networking/Email/Utilities"
+ string group = package->group();
+
+ // We will now retrieve the hierarchy of the package's group and
+ // make sure a path has already been created on all nodes, as well
+ // as get last node's GtkTreePath
+ list <string> hierarchy = YGUtils::splitString (group, '/');
+ while (!hierarchy.empty()) {
+ string node = hierarchy.front();
+ hierarchy.pop_front();
+
+ map <string, GtkTreePath*>::iterator it = tree.find (node);
+ if (it == tree.end()) {
+ if (path) {
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
+ &parent_iter, path);
+ gtk_tree_store_append (store, &iter, &parent_iter);
+ }
+ else // create at root
+ gtk_tree_store_append (store, &iter, NULL);
+
+ string name = "<big><b>" + node + "</b></big>";
+ gtk_tree_store_set (store, &iter,
+ 0, NULL, 1, name.c_str(), 2, name.c_str(), 3, TRUE,
+ 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1);
+
+ path = gtk_tree_model_get_path (model, &iter);
+ tree [node] = path;
+ }
+ else // exists
+ path = it->second;
+ }
+ }
+
+ if (!path) // package has no group
+ continue;
+
+ gtk_tree_model_get_iter (model, &parent_iter, path);
+ gtk_tree_store_append (store, &iter, &parent_iter);
+ loadPackageRow (model, &iter, selectable);
+ PROGRESS()
+ }
+
+ // free GtkTreePaths
+ for (map <string, GtkTreePath*>::iterator it = tree.begin();
+ it != tree.end(); it++)
+ gtk_tree_path_free (it->second);
+ return model;
+ }
+
+ /* NOTE: Getting the packages under a pattern, language, etc is done
+ differently, so code re-use would be limited. Probably doesn't worth
+ the trouble and complexity of doing so. */
+
+ static GtkTreeModel *loadPackagesListByPattern (GtkProgressBar *progress)
+ {
+ GtkTreeStore *store = gtk_tree_store_new (10, G_TYPE_POINTER, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT);
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (0));
+
+ // we need to create a categories tree for the patterns
+ map <string, GtkTreeIter> tree;
+
+ SET_PROGRESS (zyppPool().size <zypp::Pattern>(), 5)
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Pattern>();
+ it != zyppPool().byKindEnd <zypp::Pattern>(); it++) {
+ ZyppSelectable selectable = *it;
+ ZyppObject object = selectable->theObj();
+ ZyppPattern pattern = tryCastToZyppPattern (object);
+ if (pattern && pattern->userVisible()) {
+ GtkTreeIter category_iter, pattern_iter, package_iter;
+ string category = pattern->category();
+ map <string, GtkTreeIter>::iterator cat_it = tree.find (category);
+ if (cat_it == tree.end()) {
+ string name = "<big><b>" + category + "</b></big>";
+ gtk_tree_store_append (store, &category_iter, NULL);
+ gtk_tree_store_set (store, &category_iter,
+ 0, NULL, 1, name.c_str(), 2, name.c_str(), 3, TRUE,
+ 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1);
+ tree [category] = category_iter;
+ }
+ else
+ category_iter = cat_it->second;
+
+ string name = "<b>" + fastGetSummary (object) + "</b>";
+ gtk_tree_store_append (store, &pattern_iter, &category_iter);
+ loadPackageRow (model, &pattern_iter, selectable);
+
+/* gtk_tree_store_set (store, &pattern_iter,
+ 0, get_pointer (selectable), 1, name.c_str(), 2, name.c_str(),
+ 3, TRUE, 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1);*/
+
+ // adding children packages
+ const set <string> &packages = pattern->install_packages();
+ for (ZyppPool::const_iterator pt2 =
+ zyppPool().byKindBegin <zypp::Package>();
+ pt2 != zyppPool().byKindEnd <zypp::Package>(); pt2++) {
+ ZyppSelectable sel = *pt2;
+ for (set <string>::iterator pt1 = packages.begin();
+ pt1 != packages.end(); pt1++) {
+ if (sel->name() == *pt1) {
+ gtk_tree_store_append (store, &package_iter, &pattern_iter);
+ loadPackageRow (model, &package_iter, sel);
+ }
+ }
+ }
+ }
+ PROGRESS()
+ }
+ return model;
+ }
+
+ static GtkTreeModel *loadPackagesListByLanguage (GtkProgressBar *progress)
+ {
+ GtkTreeStore *store = gtk_tree_store_new (10, G_TYPE_POINTER, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_INT);
+ GtkTreeModel *model = GTK_TREE_MODEL (store);
+ g_object_set_data (G_OBJECT (model), "detail-package", GINT_TO_POINTER (0));
+
+ SET_PROGRESS (zyppPool().size <zypp::Language>(), 20)
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Language>();
+ it != zyppPool().byKindEnd <zypp::Language>(); it++) {
+ ZyppSelectable langsel = *it;
+ ZyppObject langobj = langsel->theObj();
+ ZyppLanguage lang = tryCastToZyppLanguage (langobj);
+ if (lang) {
+ string langname = langsel->name();
+ if (langname.empty() || langname == "C")
+ continue;
+
+ string descrpt = "<b>" + langobj->description() + "</b>";
+ GtkTreeIter parent_iter, iter;
+ gtk_tree_store_append (store, &parent_iter, NULL);
+ loadPackageRow (model, &parent_iter, langsel);
+/* gtk_tree_store_set (store, &parent_iter,
+ 0, get_pointer (langsel), 1, descrpt.c_str(), 2, descrpt.c_str(),
+ 3, TRUE, 4, TRUE, 5, FALSE, 6, FALSE, 7, FALSE, 8, TRUE, -1);*/
+
+ for (ZyppPool::const_iterator it =
+ zyppPool().byKindBegin <zypp::Package>();
+ it != zyppPool().byKindEnd <zypp::Package>(); it++) {
+ ZyppSelectable pkgsel = *it;
+ ZyppObject pkgobj = pkgsel->theObj();
+
+ const zypp::CapSet &capSet = pkgobj->dep (zypp::Dep::FRESHENS);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++) {
+ if (it->index() == lang->name()) {
+ gtk_tree_store_append (store, &iter, &parent_iter);
+ loadPackageRow (model, &iter, pkgsel);
+ }
+ }
+ }
+ }
+ PROGRESS()
+ }
+ return model;
+ }
+ #undef SET_PROGRESS
+ #undef PROGRESS
+
+ static void induceObjects (ZyppSelectable selectable, ZyppObject &install_obj,
+ ZyppObject &available_obj, bool *has_upgrade,
+ bool *has_downgrade)
+ {
+ available_obj = (install_obj = NULL);
+ if (!selectable)
+ return;
+ switch (selectable->status()) {
+ case zypp::ui::S_Install:
+ case zypp::ui::S_Update:
+ install_obj = selectable->candidateObj();
+ break;
+ case zypp::ui::S_Del:
+ available_obj = selectable->installedObj();
+ break;
+ default:
+ available_obj = selectable->candidateObj();
+ install_obj = selectable->installedObj();
+ break;
+ }
+
+ // zypp keeps on the pool objects whose sources we disabled, so we may
+ // need to calculate the candidate object here.
+#ifdef PRE_ZYPP_3
+ if (available_obj != NULL && !available_obj->source().enabled()) {
+#else
+ // beware lurking tribool requires bool cast here.
+ if (available_obj != NULL && !(bool)(available_obj->repository().info().enabled())) {
+#endif
+ available_obj = NULL;
+ for (zypp::ui::Selectable::available_iterator it = selectable->availableBegin();
+ it != selectable->availableEnd(); it++) {
+#ifdef PRE_ZYPP_3
+ if (!(*it)->source().enabled())
+#else
+ if (!(*it)->repository().info().enabled())
+#endif
+ ;
+ else if (!available_obj)
+ available_obj = *it;
+ else if (zypp::Edition::compare ((*it)->edition(),
+ available_obj->edition()) > 0)
+ available_obj = *it;
+ }
+ }
+
+ bool has_up = false, has_down = false;
+ if (available_obj != NULL && install_obj != NULL) {
+ int res = zypp::Edition::compare (install_obj->edition(),
+ available_obj->edition());
+ if (res < 0)
+ has_up = true;
+ else if (res > 0)
+ has_down = true;
+ }
+
+ if (has_upgrade)
+ *has_upgrade = has_up;
+ if (has_downgrade)
+ *has_downgrade = has_down;
+ }
+
+ /* Must be called for the main model. */
+ static void loadPackageRow (GtkTreeModel *model, GtkTreeIter *iter,
+ ZyppSelectable selectable)
+ {
+ ZyppObject install_obj, available_obj;
+ bool has_upgrade, has_downgrade, has_children = FALSE;
+ induceObjects (selectable, install_obj, available_obj,
+ &has_upgrade, &has_downgrade);
+
+ bool detailed = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
+ "detail-package"));
+ string availableName, installedName, name (YGUtils::escape_markup (selectable->name()));
+ if (available_obj) {
+ if (detailed)
+ availableName = "<b>" + name + "</b> (" + available_obj->edition().version() +
+ ")\n<small>" + YGUtils::escape_markup (fastGetSummary (available_obj)) +
+ "</small>";
+ else {
+ ZyppPattern pattern = tryCastToZyppPattern (available_obj);
+ ZyppLanguage lang = tryCastToZyppLanguage (available_obj);
+ if (pattern) {
+ availableName = "<b>" + fastGetSummary (available_obj) + "</b>";
+ has_children = TRUE;
+ } else if (lang) {
+ availableName = "<b>" + available_obj->description() + "</b>";
+ has_children = TRUE;
+ } else
+ availableName = name + " (" + available_obj->edition().version() + ")";
+ }
+ }
+ if (install_obj) {
+ if (detailed)
+ installedName = "<b>" + name + "</b> (" + install_obj->edition().version() +
+ ")\n<small>" + YGUtils::escape_markup (fastGetSummary (install_obj)) +
+ "</small>";
+ else {
+ ZyppPattern pattern = tryCastToZyppPattern (install_obj);
+ ZyppLanguage lang = tryCastToZyppLanguage (install_obj);
+ if (pattern) {
+ installedName = "<b>" + fastGetSummary (install_obj) + "</b>";
+ has_children = TRUE;
+ } else if (lang) {
+ installedName = "<b>" + install_obj->description() + "</b>";
+ has_children = TRUE;
+ } else
+ installedName = name + " (" + install_obj->edition().version() + ")";
+ }
+ }
+
+ // Make sure that both the availableName and installedName
+ // are filled. Occasionally, the names are empty, so the
+ // following checks make sure these variable are filled.
+ if (availableName.empty())
+ availableName = installedName;
+ else if (installedName.empty())
+ installedName = availableName;
+
+ PangoStyle style = PANGO_STYLE_NORMAL;
+ if (selectable->toModify())
+ style = PANGO_STYLE_ITALIC;
+
+ // oh, would be nice to have a common set for tree models...
+ if (GTK_IS_LIST_STORE (model))
+ gtk_list_store_set (GTK_LIST_STORE (model), iter,
+ COL_SELECTABLE, get_pointer (selectable),
+ COL_INSTALLED_NAME, installedName.c_str(),
+ COL_AVAILABLE_NAME, availableName.c_str(),
+ COL_IS_INSTALLED, install_obj != 0,
+ COL_IS_AVAILABLE, available_obj != 0,
+ COL_CAN_BE_UPGRADED, has_upgrade,
+ COL_CAN_BE_DOWNGRADED, has_downgrade,
+ COL_SHOW_UPGRADABLE_CONTROL, detailed,
+ COL_HAS_CHILDREN, has_children,
+ COL_FONT_STYLE, style, -1);
+ else /*if (GTK_IS_TREE_STORE (model))*/
+ gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+ COL_SELECTABLE, get_pointer (selectable),
+ COL_INSTALLED_NAME, installedName.c_str(),
+ COL_AVAILABLE_NAME, availableName.c_str(),
+ COL_IS_INSTALLED, install_obj != 0,
+ COL_IS_AVAILABLE, available_obj != 0,
+ COL_CAN_BE_UPGRADED, has_upgrade,
+ COL_CAN_BE_DOWNGRADED, has_downgrade,
+ COL_SHOW_UPGRADABLE_CONTROL, detailed,
+ COL_HAS_CHILDREN, has_children,
+ COL_FONT_STYLE, style, -1);
+/* y2milestone ("set %s: %d - %d\n", selectable->name().c_str(),
+ available_obj != 0, install_obj != 0);*/
+ }
+
+ virtual ~PackageSelector()
+ {
+ IMPL
+ if (search_timeout_id)
+ g_source_remove (search_timeout_id);
+
+ delete m_information_widget;
+ delete m_sources_table;
+ delete m_disk_table;
+ gtk_widget_destroy (m_widget);
+ g_object_unref (G_OBJECT (m_widget));
+ }
+
+ GtkWidget *getWidget()
+ { return m_widget; }
+
+ static void view_plain_mode_cb (GtkToggleButton *button,
+ PackageSelector *pThis)
+ {
+ if (!gtk_toggle_button_get_active (button)) return;
+ pThis->load_packages_view (&loadPackagesListAsPlain);
+ }
+
+ static void view_categories_mode_cb (GtkToggleButton *button,
+ PackageSelector *pThis)
+ {
+ if (!gtk_toggle_button_get_active (button)) return;
+ pThis->clear_search_entry (true);
+ pThis->load_packages_view (&loadPackagesListByCategory);
+ }
+
+ static void view_patterns_mode_cb (GtkToggleButton *button,
+ PackageSelector *pThis)
+ {
+ if (!gtk_toggle_button_get_active (button)) return;
+ pThis->clear_search_entry (true);
+ pThis->load_packages_view (&loadPackagesListByPattern);
+ }
+
+ static void view_languages_mode_cb (GtkToggleButton *button,
+ PackageSelector *pThis)
+ {
+ if (!gtk_toggle_button_get_active (button)) return;
+ pThis->clear_search_entry (true);
+ pThis->load_packages_view (&loadPackagesListByLanguage);
+ }
+
+ void sources_changed_cb()
+ {
+ // reload view; FIXME: re-load the current view, not necessarly
+ // the plain list; hacky anyway
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m_plain_view)))
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (m_plain_view), TRUE);
+ else
+ g_signal_emit_by_name (G_OBJECT (m_plain_view), "toggled", this);
+ }
+
+ void clear_search_entry (bool dont_load)
+ {
+ if (dont_load)
+ g_signal_handlers_block_by_func (m_search_entry,
+ (gpointer) search_request_cb, this);
+ gtk_entry_set_text (GTK_ENTRY (m_search_entry), "");
+ if (dont_load)
+ g_signal_handlers_unblock_by_func (m_search_entry,
+ (gpointer) search_request_cb, this);
+ }
+
+ static void search_activate_cb (GtkEntry *entry, PackageSelector *pThis)
+ {
+ IMPL
+ if (pThis->search_timeout_id)
+ g_source_remove (pThis->search_timeout_id);
+ search_cb (pThis);
+ }
+
+ static void search_request_cb (GtkEditable *editable, PackageSelector *pThis)
+ {
+ IMPL
+ // we'll make a delay for the actual search to wait for the user
+ // to finish writting
+ if (pThis->search_timeout_id)
+ g_source_remove (pThis->search_timeout_id);
+ pThis->search_timeout_id = g_timeout_add (500, search_cb, pThis);
+ }
+
+ struct FindClosure {
+ bool found;
+ GtkTreeView *view;
+ PackageSelector *pThis;
+ };
+ static gboolean find_exact_match (GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gpointer data)
+ {
+ FindClosure *cl = (FindClosure *) data;
+
+ ZyppSelectablePtr sel = NULL;
+
+ gtk_tree_model_get (model, iter, COL_SELECTABLE, &sel, -1);
+
+ if (!sel)
+ return FALSE;
+
+ if (sel->name() == *cl->pThis->m_search_queries.begin()) {
+ cl->found = true;
+ gtk_tree_selection_select_iter
+ (gtk_tree_view_get_selection (cl->view), iter);
+ package_clicked_cb (gtk_tree_view_get_selection (cl->view), cl->pThis);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ void highlight_exact_matches ()
+ {
+ if (m_search_queries.empty() || !name_opt)
+ return;
+
+ FindClosure cl;
+ cl.found = false;
+ cl.pThis = this;
+ cl.view = GTK_TREE_VIEW (m_installed_view);
+
+ gtk_tree_model_foreach (gtk_tree_view_get_model (cl.view),
+ find_exact_match, &cl);
+
+ if (!cl.found) {
+ cl.view = GTK_TREE_VIEW (m_available_view);
+ gtk_tree_model_foreach (gtk_tree_view_get_model (cl.view),
+ find_exact_match, &cl);
+ }
+ }
+
+ static gboolean search_cb (gpointer data)
+ {
+ IMPL
+
+ // This is potentially very slow ...
+#ifdef IMPL_DEBUG
+ fprintf (stderr, "search start...\n");
+#endif
+ PackageSelector *pThis = (PackageSelector *) data;
+ pThis->search_timeout_id = 0;
+
+ const gchar *query = gtk_entry_get_text (GTK_ENTRY (pThis->m_search_entry));
+ bool plain_view = gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (pThis->m_plain_view));
+ if (!plain_view)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pThis->m_plain_view), TRUE);
+ pThis->m_search_queries = YGUtils::splitString (query, ' ');
+
+ // just re-filter
+ GtkTreeModel *available_model =
+ gtk_tree_view_get_model (GTK_TREE_VIEW (pThis->m_available_view));
+ GtkTreeModel *installed_model =
+ gtk_tree_view_get_model (GTK_TREE_VIEW (pThis->m_installed_view));
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (available_model));
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (installed_model));
+
+ pThis->highlight_exact_matches ();
+
+#ifdef IMPL_DEBUG
+ fprintf (stderr, "search done...\n");
+#endif
+ return FALSE;
+ }
+
+ GtkMenu *create_search_menu()
+ {
+ GtkWidget *menu = gtk_menu_new();
+ append_option_item (menu, _("Name"), &name_opt);
+ append_option_item (menu, _("Summary"), &summary_opt);
+ append_option_item (menu, _("Description"), &descr_opt);
+ append_option_item (menu, _("RPM Provides"), &provides_opt);
+ append_option_item (menu, _("RPM Requires"), &requires_opt);
+ gtk_widget_show_all (menu);
+ return GTK_MENU (menu);
+ }
+
+ static void append_option_item (GtkWidget *menu, const char *label, bool *option)
+ {
+ GtkWidget *item = gtk_check_menu_item_new_with_label (label);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), *option);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ g_signal_connect (G_OBJECT (item), "toggled",
+ G_CALLBACK (search_option_change_cb), option);
+ }
+
+ static void search_option_change_cb (GtkCheckMenuItem *item, bool *option)
+ { *option = item->active; }
+
+ inline static gboolean is_package_visible (GtkTreeModel *model, GtkTreeIter *iter,
+ PackageSelector *pThis, int visible_col)
+ {
+ gboolean visible, has_children;
+ ZyppSelectablePtr selectable;
+
+ gtk_tree_model_get (model, iter, visible_col, &visible,
+ COL_HAS_CHILDREN, &has_children,
+ COL_SELECTABLE, &selectable, -1);
+
+// fprintf (stderr, "is visible '%s'\n", selectable ? selectable->name().c_str() : "<noname>");
+ if (has_children)
+ visible = TRUE;
+ else if (visible && !pThis->m_search_queries.empty())
+ visible = pThis->does_package_match (selectable);
+
+ return visible;
+ }
+
+ static gboolean is_package_installed (GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
+ { return is_package_visible (model, iter, (PackageSelector *) data, 3); }
+
+ static gboolean is_package_available (GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data)
+ {
+ gboolean is_installed, is_available, has_upgrade, has_children;
+ gboolean visible = TRUE;
+ ZyppSelectablePtr selectable;
+ PackageSelector *pThis = (PackageSelector *) data;
+
+ // only show the packages that aren't installed
+ // unless there's an upgrade available
+ gtk_tree_model_get (model, iter, COL_SELECTABLE, &selectable,
+ COL_IS_INSTALLED, &is_installed,
+ COL_IS_AVAILABLE, &is_available,
+ COL_CAN_BE_UPGRADED, &has_upgrade,
+ COL_HAS_CHILDREN, &has_children, -1);
+ if (!has_children) {
+ if (is_available && (!is_installed || has_upgrade)) {
+ if (!pThis->m_search_queries.empty())
+ visible = pThis->does_package_match (selectable);
+ } else
+ visible = FALSE;
+ }
+
+ return visible;
+ }
+
+ bool does_package_match_one (ZyppSelectablePtr sel, string key)
+ {
+ ZyppObject obj = NULL;
+
+ if (name_opt && YGUtils::contains (sel->name(), key))
+ return TRUE;
+
+ if (summary_opt || descr_opt || provides_opt || requires_opt)
+ obj = sel->theObj();
+
+ if (summary_opt && YGUtils::contains (fastGetSummary (obj), key))
+ return TRUE;
+ if (descr_opt && YGUtils::contains (obj->description(), key))
+ return TRUE;
+ if (provides_opt) {
+ const zypp::CapSet &capSet = obj->dep (zypp::Dep::PROVIDES);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++)
+ if (YGUtils::contains (it->asString(), key))
+ return TRUE;
+ }
+ if (requires_opt) {
+ const zypp::CapSet &capSet = obj->dep (zypp::Dep::REQUIRES);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++)
+ if (YGUtils::contains (it->asString(), key))
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ gboolean does_package_match (ZyppSelectablePtr sel)
+ {
+ if (m_search_queries.empty())
+ return true;
+
+ bool and_results = true; // vs. or them ...
+
+ bool result = and_results;
+ for (list <string>::iterator it = m_search_queries.begin();
+ it != m_search_queries.end(); it++) {
+
+ // TODO: googlify more ...
+ if (*it == "OR") {
+ and_results = false;
+ continue;
+ }
+ if (*it == "AND") {
+ and_results = true;
+ continue;
+ }
+ bool match = does_package_match_one (sel, *it);
+ result = and_results ? result && match : result || match;
+ }
+ return result;
+ }
+
+ // callbacks
+ static bool getSelectedPackage (GtkTreeView *tree_view,
+ ZyppSelectablePtr *package_sel, GtkTreePath **_path = 0)
+ {
+ IMPL
+ GtkTreePath *path = 0;
+ gtk_tree_view_get_cursor (tree_view, &path, NULL);
+ if (path) {
+ GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_model_get (model, &iter, COL_SELECTABLE, package_sel, -1);
+ if (_path)
+ *_path = gtk_tree_model_filter_convert_path_to_child_path
+ (GTK_TREE_MODEL_FILTER (model), path);
+ gtk_tree_path_free (path);
+ return true;
+ }
+ return false;
+ }
+
+ // For SLED10 / older gtk+'s ...
+ static bool compat_gtk_tree_model_filter_convert_child_iter_to_iter (GtkTreeModelFilter *filter,
+ GtkTreeIter *filter_iter,
+ GtkTreeIter *child_iter)
+ {
+#if GTK_CHECK_VERSION(2,10,0)
+ return gtk_tree_model_filter_convert_child_iter_to_iter (filter, filter_iter, child_iter);
+#else // cut/paste from gtk+ HEAD...
+ gboolean ret;
+ GtkTreePath *child_path, *path;
+
+ memset (filter_iter, 0, sizeof (GtkTreeIter));
+
+ GtkTreeModel *child_model;
+ g_object_get (G_OBJECT (filter), "child-model", &child_model, NULL);
+ child_path = gtk_tree_model_get_path (child_model, child_iter);
+ g_return_val_if_fail (child_path != NULL, FALSE);
+
+ path = gtk_tree_model_filter_convert_child_path_to_path (filter,
+ child_path);
+ gtk_tree_path_free (child_path);
+
+ if (!path)
+ return FALSE;
+
+ ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (filter), filter_iter, path);
+ gtk_tree_path_free (path);
+
+ return ret;
+#endif
+ }
+
+ static bool sync_tree_views_scroll (GtkTreeView *current_view, GtkTreeView *other_view,
+ GtkTreePath *current_path, bool select_it)
+ {
+ /* What we do here is to scroll the other view to the correspondent
+ package position. If the package isn't present in that view, we
+ iterate it so we get the closest package (with respect to alphabetic
+ sorting). */
+
+ // converts the path from one model to the other
+ GtkTreePath *_path, *other_path;
+ _path = gtk_tree_model_filter_convert_path_to_child_path (
+ GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (current_view)),
+ current_path);
+ if (!_path)
+ return false;
+
+ GtkTreeModel *base_model = gtk_tree_model_filter_get_model (
+ GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (current_view)));
+
+ GtkTreeIter iter, other_iter;
+ gtk_tree_model_get_iter (base_model, &iter, _path);
+ gtk_tree_path_free (_path);
+
+ int timeout = 0;
+ // Try to find a a similar item in the other view to synchronise with
+ while (!compat_gtk_tree_model_filter_convert_child_iter_to_iter (
+ GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (other_view)),
+ &other_iter, &iter))
+ {
+ if (!gtk_tree_model_iter_next (base_model, &iter))
+ return false;
+ // This turns into N^3 very quickly if we search too hard
+ if (timeout++ > 10)
+ return false;
+ select_it = false; // not the same package -- dont select it then
+ }
+
+ other_path = gtk_tree_model_get_path (gtk_tree_view_get_model (other_view),
+ &other_iter);
+
+ GdkRectangle cell_rect, visible_rect;
+ gtk_tree_view_get_cell_area (other_view, other_path, NULL, &cell_rect);
+ gtk_tree_view_get_visible_rect (other_view, &visible_rect);
+ int y = visible_rect.y + cell_rect.y;
+
+ gtk_tree_view_get_cell_area (current_view, current_path, NULL, &cell_rect);
+ y -= cell_rect.y; // offset
+
+ gtk_tree_view_expand_to_path (other_view, other_path);
+ YGUtils::tree_view_smooth_scroll_to_point (other_view, 0, y);
+ if (select_it)
+ gtk_tree_selection_select_path (gtk_tree_view_get_selection (other_view),
+ other_path);
+ gtk_tree_path_free (other_path);
+ return true;
+ }
+
+ static void package_clicked_cb (GtkTreeSelection *selection, PackageSelector *pThis)
+ {
+ IMPL
+ int selected_rows = gtk_tree_selection_count_selected_rows (selection);
+ if (selected_rows == 0)
+ return;
+
+ static bool safeguard = false;
+ if (safeguard)
+ return;
+ safeguard = true;
+
+ GtkTreeView *tree_view = gtk_tree_selection_get_tree_view (selection);
+ bool install_view = tree_view == GTK_TREE_VIEW (pThis->m_installed_view);
+ GtkTreeView *other_view = GTK_TREE_VIEW (install_view ?
+ pThis->m_available_view : pThis->m_installed_view);
+
+ // unselect the other view
+ gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (other_view));
+
+ // select and scroll to the package in the other view (if it's listed there)
+ GtkTreePath *path = 0;
+ gtk_tree_view_get_cursor (tree_view, &path, NULL);
+ if (path) {
+ // function can be called to set some package visible
+ gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0, 0);
+
+ sync_tree_views_scroll (tree_view, other_view, path, selected_rows == 1);
+ gtk_tree_path_free (path);
+ }
+
+ // show package information
+ ZyppSelectablePtr sel = 0;
+ getSelectedPackage (tree_view, &sel);
+
+ ZyppObject install_obj, available_obj;
+ induceObjects (sel, install_obj, available_obj, NULL, NULL);
+
+ ZyppObject &obj = install_view ? install_obj : available_obj;
+ pThis->m_information_widget->setPackage (sel, obj);
+
+ // change the install/remove button label to upgrade, or etc
+ GtkLabel *install_label = GTK_LABEL (pThis->m_install_label),
+ *remove_label = GTK_LABEL (pThis->m_remove_label);
+ if (selected_rows > 1) {
+ gtk_label_set_text (install_label, _("_install"));
+ gtk_label_set_text (remove_label, _("_remove"));
+ }
+ else { // personalize
+ // remove label
+ if (sel && sel->toInstall())
+ gtk_label_set_text (remove_label, _("_undo"));
+ else
+ gtk_label_set_text (remove_label, _("_remove"));
+ // install label
+ if (sel && sel->toDelete())
+ gtk_label_set_text (install_label, _("_undo"));
+ else if (!install_obj)
+ gtk_label_set_text (install_label, _("_install"));
+ else if (available_obj) {
+ int res = zypp::Edition::compare (install_obj->edition(),
+ available_obj->edition());
+ if (res < 0)
+ gtk_label_set_text (install_label, _("_upgrade"));
+ else if (res > 0)
+ gtk_label_set_text (install_label, _("_downgrade"));
+ else
+ gtk_label_set_text (install_label, _("re-_install"));
+ }
+ }
+ gtk_label_set_use_underline (install_label, TRUE);
+ gtk_label_set_use_underline (remove_label, TRUE);
+
+ safeguard = false;
+ }
+
+ // install/remove/update/... selected packages
+ void markSelectedPackage (GtkTreeView *view, bool available, bool installed)
+ {
+ IMPL
+ /* Since the filter model gets changed, get paths for the base model and
+ then do our stuff. */
+ GList *selected = gtk_tree_selection_get_selected_rows (
+ gtk_tree_view_get_selection (view), NULL);
+
+ int selected_len = g_list_length (selected);
+ GtkTreeIter iters [selected_len];
+
+ GtkTreeModel *filter_model = gtk_tree_view_get_model (view);
+ GtkTreeModelFilter *filter = GTK_TREE_MODEL_FILTER (filter_model);
+ GtkTreeModel *model = gtk_tree_model_filter_get_model (filter);
+
+ int i = 0;
+ for (GList *it = selected; it; it = it->next, i++) {
+ GtkTreePath *path = (GtkTreePath *) it->data;
+
+ GtkTreeIter filter_iter, iter;
+ gtk_tree_model_get_iter (filter_model, &filter_iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_filter_convert_iter_to_child_iter (filter, &iter, &filter_iter);
+ iters[i] = iter;
+ }
+ g_list_free (selected);
+ for (i = 0; i < selected_len; i++) {
+ GtkTreeIter *iter = &iters[i];
+ ZyppSelectablePtr sel = 0;
+ gtk_tree_model_get (model, iter, COL_SELECTABLE, &sel, -1);
+ if (sel && mark_selectable (sel, installed) /* install/remove */) {
+ loadPackageRow (model, iter, sel); // update model
+
+ // mark also children (eg. for patterns and languages)
+ GtkTreeIter child;
+ if (gtk_tree_model_iter_children (model, &child, iter)) {
+ do {
+ gtk_tree_model_get (model, &child, COL_SELECTABLE, &sel, -1);
+ if (sel && mark_selectable (sel, installed))
+ loadPackageRow (model, &child, sel);
+ } while (gtk_tree_model_iter_next (model, &child));
+
+ }
+ }
+ }
+
+ m_disk_table->update();
+
+ // select path, so the buttons get updated and all (hacky)
+ GtkTreeView *other_view = GTK_TREE_VIEW (
+ GTK_WIDGET (view) == m_installed_view ? m_available_view : m_installed_view);
+ package_clicked_cb (gtk_tree_view_get_selection (other_view), this);
+ }
+
+ static void install_button_clicked_cb (GtkButton *button, PackageSelector *pThis)
+ {
+ IMPL
+ pThis->markSelectedPackage (GTK_TREE_VIEW (pThis->m_available_view), false, true);
+ gtk_widget_grab_focus (pThis->m_available_view);
+ }
+
+ static void remove_button_clicked_cb (GtkButton *button, PackageSelector *pThis)
+ {
+ IMPL
+ pThis->markSelectedPackage (GTK_TREE_VIEW (pThis->m_installed_view), true, false);
+ gtk_widget_grab_focus (pThis->m_installed_view);
+ }
+
+ static void change_available_version_cb (YGtkCellRendererArrow *renderer,
+ guint arrow_type, const gchar *_path, PackageSelector *pThis)
+ {
+ GtkTreeModel *model = gtk_tree_view_get_model (
+ GTK_TREE_VIEW (pThis->m_available_view));
+ GtkTreePath *path = gtk_tree_path_new_from_string (_path);
+ GtkTreeIter it;
+ gtk_tree_model_get_iter (model, &it, path);
+ gtk_tree_path_free (path);
+
+ GtkTreeIter iter;
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
+ &iter, &it);
+ model = pThis->m_packages_model;
+
+ ZyppSelectablePtr selectable;
+ gtk_tree_model_get (model, &iter, COL_SELECTABLE, &selectable, -1);
+
+ ZyppObject candidate = selectable->candidateObj();
+ for (zypp::ui::Selectable::available_iterator it = selectable->availableBegin();
+ it != selectable->availableEnd(); it++) {
+ int cmp = zypp::Edition::compare ((*it)->edition(), candidate->edition());
+ if (arrow_type == GTK_ARROW_UP) { // upgrade
+ if (cmp > 0)
+ candidate = *it;
+ }
+ else /*if (arrow_type == GTK_ARROW_DOWN)*/ { // downgrade
+ if (cmp < 0)
+ candidate = *it;
+ }
+ }
+ if (!selectable->setCandidate (candidate))
+ y2warning ("Error: Could not %sgrade\n", arrow_type == GTK_ARROW_UP ? "up" : "down");
+ pThis->loadPackageRow (model, &iter, selectable);
+ }
+
+ static gboolean dont_select_groups_cb (GtkTreeSelection *selection, GtkTreeModel *model,
+ GtkTreePath *path, gboolean selected, gpointer data)
+ {
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ ZyppSelectablePtr selectable;
+ gtk_tree_model_get (model, &iter, COL_SELECTABLE, &selectable, -1);
+ return selectable != NULL;
+ }
+ return FALSE;
+ }
+};
+
+// The ordinary package selector that displays all packages
+class YGPackageSelector : public YPackageSelector, public YGWidget
+{
+ PackageSelector *m_package_selector;
+
+ static bool confirm_cb (void *pThis)
+ {
+ return ((YGPackageSelector *)pThis)->checkDelete();
+ }
+
+ bool checkDelete()
+ {
+ bool changed =
+ zyppPool().diffState<zypp::Package >() ||
+ zyppPool().diffState<zypp::Pattern >() ||
+ zyppPool().diffState<zypp::Selection>() ||
+ zyppPool().diffState<zypp::Language >() ||
+ zyppPool().diffState<zypp::Patch >();
+ if (!changed)
+ return true;
+
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new_with_markup
+ (YGUI::ui()->currentWindow(),
+ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE, _("<b>Abandon all changes?</b>"));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
+ GTK_STOCK_QUIT, GTK_RESPONSE_YES, NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_NO);
+ bool ok = gtk_dialog_run (GTK_DIALOG (dialog)) ==
+ GTK_RESPONSE_YES;
+ gtk_widget_destroy (dialog);
+ return ok;
+ }
+
+public:
+ YGPackageSelector (const YWidgetOpt &opt, YGWidget *parent)
+ : YPackageSelector (opt),
+ YGWidget (this, parent, true, YGTK_TYPE_WIZARD, NULL)
+ {
+ setBorder (0);
+
+ YGDialog *dialog = YGUI::ui()->currentYGDialog();
+ dialog->setCloseCallback (confirm_cb, this);
+ GtkWindow *window = dialog->getWindow();
+ gtk_window_resize (window, MAX (680, GTK_WIDGET (window)->allocation.width),
+ MAX (580, GTK_WIDGET (window)->allocation.height));
+
+ YGtkWizard *wizard = YGTK_WIZARD (getWidget());
+
+ ygtk_wizard_set_header_icon (wizard, window,
+ THEMEDIR "/icons/32x32/apps/yast-software.png");
+ ygtk_wizard_set_header_text (wizard, window, "Package Selector");
+ ygtk_wizard_set_help_text (wizard,
+ _("Two pools are presented; one with the available software, the other "
+ "with the installed one. To install software you choose a package "
+ "from the install pool and press Install. Similar method for removal "
+ "of software. When you are done press the Accept button.<br>"
+ "Information on a given package is displayed on the Package Information "
+ "expander at the bottom which may be enlarged.<br>"
+ "A categories view of the software is possible, as well as searching "
+ "for a given package.")
+ );
+
+ ygtk_wizard_set_abort_button_label (wizard, _("_Cancel"));
+ ygtk_wizard_set_abort_button_id (wizard, g_strdup ("cancel"), g_free);
+ ygtk_wizard_set_back_button_label (wizard, "");
+ ygtk_wizard_set_next_button_label (wizard, _("_Accept"));
+ ygtk_wizard_set_next_button_id (wizard, g_strdup ("accept"), g_free);
+ g_signal_connect (G_OBJECT (getWidget()), "action-triggered",
+ G_CALLBACK (wizard_action_cb), this);
+
+ m_package_selector = new PackageSelector (!opt.searchMode.value());
+ gtk_container_add (GTK_CONTAINER (wizard), m_package_selector->getWidget());
+ }
+
+ virtual ~YGPackageSelector()
+ {
+ YGDialog *dialog = YGUI::ui()->currentYGDialog();
+ dialog->unsetCloseCallback();
+ delete m_package_selector;
+ }
+
+protected:
+ static void wizard_action_cb (YGtkWizard *wizard, gpointer id,
+ gint id_type, YGPackageSelector *pThis)
+ {
+ IMPL
+ const gchar *action = (gchar *) id;
+
+ if (!strcmp (action, "accept")) {
+ if (zyppPool().diffState <zypp::Package> ()) {
+ // in case of changes, check problems, ask for confirmation and JFDI.
+ if (pThis->confirmChanges() && solveProblems()) {
+ y2milestone ("Closing PackageSelector with 'accept'");
+ YGUI::ui()->sendEvent (new YMenuEvent (YCPSymbol ("accept")));
+ }
+ }
+ else
+ YGUI::ui()->sendEvent (new YCancelEvent());
+ }
+ else if (!strcmp (action, "cancel")) {
+ y2milestone ("Closing PackageSelector with 'cancel'");
+ if (pThis->checkDelete())
+ YGUI::ui()->sendEvent (new YCancelEvent());
+ }
+ }
+
+ // helper function for confirmChanges
+ static bool isInstalled (const string &package)
+ {
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>();
+ it != zyppPool().byKindEnd <zypp::Package>(); it++) {
+ if ((*it)->hasInstalledObj() || (*it)->toInstall()) {
+ if (package == (*it)->name())
+ return true;
+ ZyppObject obj = (*it)->theObj();
+ const zypp::CapSet &caps = obj->dep (zypp::Dep::PROVIDES);
+ for (zypp::CapSet::const_iterator jt = caps.begin();
+ jt != caps.end(); jt++)
+ if (package == jt->asString())
+ return true;
+ }
+ }
+ return false; // doesn't even exist
+ }
+
+ bool confirmChanges()
+ {
+ IMPL
+ if (zyppPool().empty <zypp::Package> ())
+ return false;
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Changes Summary"),
+ YGUI::ui()->currentWindow(),
+ GtkDialogFlags (GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("C_onfirm"), GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkWidget *install_label, *remove_label, *install_view, *remove_view;
+ install_label = gtk_label_new (_("To install:"));
+ remove_label = gtk_label_new (_("To remove:"));
+ install_view = gtk_tree_view_new();
+ remove_view = gtk_tree_view_new();
+
+ GtkWidget *install_window, *remove_window;
+ install_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (install_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (install_window), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (install_window), install_view);
+ remove_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (remove_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW (remove_window), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (remove_window), remove_view);
+
+ GtkBox *vbox = GTK_BOX (GTK_DIALOG(dialog)->vbox);
+ gtk_box_pack_start (vbox, install_label, FALSE, FALSE, 6);
+ gtk_box_pack_start (vbox, install_window, TRUE, TRUE, 6);
+ gtk_box_pack_start (vbox, remove_label, FALSE, FALSE, 6);
+ gtk_box_pack_start (vbox, remove_window, TRUE, TRUE, 6);
+
+ // create model
+ {
+ GtkTreeStore *install_store = gtk_tree_store_new (1, G_TYPE_STRING);
+ GtkTreeStore *remove_store = gtk_tree_store_new (1, G_TYPE_STRING);
+
+ // install view
+ GtkTreeViewColumn *column;
+ column = gtk_tree_view_column_new_with_attributes (_("Install packages"),
+ gtk_cell_renderer_text_new(), "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (install_view), column);
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (install_view), FALSE);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (install_view),
+ GTK_TREE_MODEL (install_store));
+ g_object_unref (G_OBJECT (install_store));
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (install_view)), GTK_SELECTION_NONE);;
+
+ // remove view
+ column = gtk_tree_view_column_new_with_attributes (_("Remove packages"),
+ gtk_cell_renderer_text_new(), "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (remove_view), column);
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (remove_view), FALSE);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (remove_view),
+ GTK_TREE_MODEL (remove_store));
+ g_object_unref (G_OBJECT (remove_store));
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (remove_view)), GTK_SELECTION_NONE);;
+
+ // construct model
+ for (ZyppPool::const_iterator it = zyppPool().byKindBegin <zypp::Package>();
+ it != zyppPool().byKindEnd <zypp::Package>(); it++)
+ {
+ ZyppSelectable selectable = *it;
+ if (!selectable)
+ continue;
+
+ GtkTreeStore *store;
+ if (selectable->toInstall())
+ store = install_store;
+ else if (selectable->toDelete())
+ store = remove_store;
+ else continue;
+
+ GtkTreeIter iter;
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter, 0, selectable->name().c_str(), -1);
+
+ // show dependencies -- we just ask Zypp for dependencies in the form
+ // of a string (which is the only way to do it anyway).
+ if (store == install_store) {
+ GtkTreeIter dep_iter;
+ ZyppObject object = selectable->theObj();
+ const zypp::CapSet &capSet = object->dep (zypp::Dep::REQUIRES);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++) {
+ // don't show if it is already installed
+ if (isInstalled (it->asString()))
+ continue;
+
+ gtk_tree_store_append (store, &dep_iter, &iter);
+ gtk_tree_store_set (store, &dep_iter,
+ 0, it->asString().c_str(), -1);
+ }
+ }
+
+ // show packages that require this -- we will need to iterate through
+ // all the packages... (not very accurate)
+ else {
+ GtkTreeIter req_iter;
+
+ for (ZyppPool::const_iterator it =
+ zyppPool().byKindBegin <zypp::Package>();
+ it != zyppPool().byKindEnd <zypp::Package>(); it++) {
+ // only show if it is installed
+ if ((*it)->hasInstalledObj() || (*it)->toInstall()) {
+ ZyppSelectable dep_selectable = *it;
+ ZyppObject dep_object = dep_selectable->theObj();
+
+ const zypp::CapSet &capSet = dep_object->dep (zypp::Dep::REQUIRES);
+ for (zypp::CapSet::const_iterator it = capSet.begin();
+ it != capSet.end(); it++) {
+ if (it->asString() == selectable->name()) {
+ gtk_tree_store_append (store, &req_iter, &iter);
+ gtk_tree_store_set (store, &req_iter,
+ 0, dep_selectable->name().c_str(), -1);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400);
+ gtk_widget_show_all (dialog);
+
+ bool confirmed = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT;
+ gtk_widget_destroy (dialog);
+
+ return confirmed;
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+#endif /*DISABLE_PACKAGE_SELECTOR*/
+
+YWidget *
+YGUI::createPackageSelector (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &floppyDevice)
+{
+ // TODO: floppyDevice really needed?
+#ifndef DISABLE_PACKAGE_SELECTOR
+ if (opt.youMode.value())
+ return new YGPatchSelector (opt, YGWidget::get (parent));
+ else
+ return new YGPackageSelector (opt, YGWidget::get (parent));
+#else
+ return NULL;
+#endif
+}
+
+YWidget *
+YGUI::createPkgSpecial (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &subwidget)
+{
+ // same as Qt's
+ y2error ("The GTK+ UI does not support PkgSpecial subwidgets!");
+ return 0;
+}
+
Added: trunk/gtk/src/YGProgressBar.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGProgressBar.cc?rev=425…
==============================================================================
--- trunk/gtk/src/YGProgressBar.cc (added)
+++ trunk/gtk/src/YGProgressBar.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,166 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+
+#include "YProgressBar.h"
+
+class YGProgressBar : public YProgressBar, public YGLabeledWidget
+{
+ bool m_pulse;
+public:
+ YGProgressBar (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString& label,
+ const YCPInteger& maxprogress, const YCPInteger& progress)
+ : YProgressBar (opt, label, maxprogress, progress)
+ , YGLabeledWidget (this, parent, label, YD_VERT, true,
+ GTK_TYPE_PROGRESS_BAR, NULL)
+ {
+ m_pulse = maxprogress->value() <= 0;
+ }
+ // 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).
+
+ virtual ~YGProgressBar() {}
+
+ // YProgressBar
+ virtual void setProgress (const YCPInteger& newProgress)
+ {
+ IMPL
+ if (m_pulse)
+ gtk_progress_bar_pulse (GTK_PROGRESS_BAR (getWidget()));
+ else {
+ float fraction = (float) newProgress->value() / maxProgress->value();
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (getWidget()), fraction);
+ }
+ YProgressBar::setProgress (newProgress);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YProgressBar)
+};
+
+YWidget *
+YGUI::createProgressBar (YWidget* parent, YWidgetOpt& opt,
+ const YCPString& label, const YCPInteger& maxprogress,
+ const YCPInteger& progress)
+{
+ IMPL;
+ return new YGProgressBar (opt, YGWidget::get (parent),
+ label, maxprogress, progress);
+}
+
+#include "YDownloadProgress.h"
+
+class YGDownloadProgress : public YDownloadProgress, public YGLabeledWidget
+{
+ guint timeout_id;
+
+public:
+ YGDownloadProgress (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString& label, const YCPString &filename,
+ int expectedSize)
+ : YDownloadProgress (opt, label, filename, expectedSize)
+ , YGLabeledWidget (this, parent, label, YD_HORIZ, true,
+ GTK_TYPE_PROGRESS_BAR, NULL)
+ {
+ timeout_id = g_timeout_add (250, timeout_cb, this);
+ }
+
+ virtual ~YGDownloadProgress()
+ {
+ g_source_remove (timeout_id);
+ }
+
+ virtual void setExpectedSize (int expectedSize)
+ {
+ YDownloadProgress::setExpectedSize (expectedSize);
+ timeout_cb(this); // force an update
+ }
+
+ static gboolean timeout_cb (void *pData)
+ {
+ YGDownloadProgress *pThis = (YGDownloadProgress*) pData;
+ float fraction = (float) pThis->currentFileSize() / pThis->expectedSize();
+ if (fraction > 1) fraction = 1;
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pThis->getWidget()), fraction);
+ return TRUE;
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YDownloadProgress)
+};
+
+YWidget *
+YGUI::createDownloadProgress (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, const YCPString &filename,
+ int expectedSize)
+{
+ IMPL
+ return new YGDownloadProgress (opt, YGWidget::get (parent),
+ label, filename, expectedSize);
+}
+
+#include "ygtkratiobox.h"
+#include "YMultiProgressMeter.h"
+
+class YGMultiProgressMeter : public YMultiProgressMeter, public YGWidget
+{
+public:
+ YGMultiProgressMeter (const YWidgetOpt &opt, YGWidget *parent,
+ bool horizontal, const YCPList &maxValues)
+ : YMultiProgressMeter (opt, horizontal, maxValues)
+ , YGWidget (this, parent, true,
+ horizontal ? YGTK_TYPE_RATIO_HBOX : YGTK_TYPE_RATIO_VBOX, NULL)
+ {
+// ygtk_ratio_box_set_homogeneous (YGTK_RATIO_BOX (getWidget()), TRUE);
+ ygtk_ratio_box_set_spacing (YGTK_RATIO_BOX (getWidget()), 2);
+
+ for (int i = segments()-1; i >= 0; i--) {
+ 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,
+ maxValue (i), TRUE, TRUE, 0);
+ }
+
+ 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 n = segments()-1;
+ for (GList *i = children; i && n >= 0; i = i->next, n--) {
+ GtkProgressBar *bar = GTK_PROGRESS_BAR (i->data);
+ gfloat fraction = 0;
+ if (currentValue (n) != -1)
+ fraction = 1.0 - ((gfloat) currentValue(n) / maxValue(n));
+ gtk_progress_bar_set_fraction (bar, fraction);
+ }
+ g_list_free (children);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createMultiProgressMeter (YWidget *parent, YWidgetOpt &opt,
+ bool horizontal, const YCPList &maxValues)
+{
+ return new YGMultiProgressMeter (opt, YGWidget::get (parent),
+ horizontal, maxValues);
+}
Added: trunk/gtk/src/YGPushButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGPushButton.cc?rev=4251…
==============================================================================
--- trunk/gtk/src/YGPushButton.cc (added)
+++ trunk/gtk/src/YGPushButton.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,79 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YPushButton.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+class YGPushButton : public YPushButton, public YGWidget
+{
+public:
+ YGPushButton (const YWidgetOpt &opt, YGWidget *parent, YCPString label)
+ : YPushButton (opt, label),
+ YGWidget (this, parent, true, GTK_TYPE_BUTTON, "can-default", TRUE, NULL)
+ {
+ IMPL
+ if (!opt.isShrinkable.value())
+ setMinSizeInChars (10, 0);
+
+ gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
+ setLabel (label);
+
+ g_signal_connect (G_OBJECT (getWidget ()), "clicked",
+ G_CALLBACK (clicked_cb), this);
+ if (opt.isDefaultButton.value())
+ g_signal_connect (G_OBJECT (getWidget ()), "realize",
+ G_CALLBACK (set_default_cb), this);
+ }
+
+ virtual ~YGPushButton() {}
+
+ // YPushButton
+ virtual void setLabel (const YCPString &label)
+ {
+ IMPL
+ string str = YGUtils::mapKBAccel (label->value_cstr());
+ gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
+ YGUtils::setStockIcon (getWidget(), str);
+ YPushButton::setLabel (label);
+ }
+
+ virtual void setIcon (const YCPString &icon_name)
+ {
+ IMPL
+ string path = icon_name->value();
+ if (path[0] != '/')
+ path = ICON_DIR + 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 (GTK_BUTTON (getWidget()), image);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ else
+ y2warning ("YGPushButton: Couldn't load icon image: %s.\n"
+ "Reason: %s", path.c_str(), error->message);
+ }
+
+ static void set_default_cb (GtkButton *button, YGPushButton *pThis)
+ { gtk_widget_grab_default (GTK_WIDGET (button)); }
+
+ static void clicked_cb (GtkButton *button, YGPushButton *pThis)
+ { pThis->emitEvent (YEvent::Activated, false); }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createPushButton (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ return new YGPushButton (opt, YGWidget::get (parent), label);
+}
+
Added: trunk/gtk/src/YGRadioButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGRadioButton.cc?rev=425…
==============================================================================
--- trunk/gtk/src/YGRadioButton.cc (added)
+++ trunk/gtk/src/YGRadioButton.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,243 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YEvent.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 "YRadioButtonGroup.h"
+#include "YRadioButton.h"
+
+class YGRadioButton : public YRadioButton, public YGWidget
+{
+ bool m_isBold;
+
+public:
+
+ YGRadioButton (const YWidgetOpt &opt,
+ YGWidget *parent,
+ YCPString label,
+ YRadioButtonGroup *rbg,
+ bool checked)
+ : YRadioButton (opt, label, rbg),
+ YGWidget (this, parent, true, getCheckRadioButtonType(), NULL)
+ {
+ IMPL
+ setBorder (0);
+ setValue (YCPBoolean (checked));
+
+ m_isBold = opt.boldFont.value();
+ gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
+ setLabel (label);
+
+ g_signal_connect (G_OBJECT (getWidget()), "toggled",
+ G_CALLBACK (toggled_cb), this);
+ }
+
+ // YRadioButton
+ virtual void setLabel (const YCPString &text)
+ {
+ // NOTE: we can't just set a gtk_widget_modify() at the initialization
+ // because each gtk_button_set_label() creates a new label
+ IMPL
+ string str = YGUtils::mapKBAccel(text->value_cstr());
+ if (m_isBold)
+ str = "<b>" + str + "</b>";
+ gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
+ YRadioButton::setLabel (text);
+
+ GtkWidget *label = gtk_bin_get_child (GTK_BIN (getWidget()));
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ }
+
+ virtual void setValue (const YCPBoolean &checked)
+ {
+ IMPL
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) toggled_cb, this);
+
+ if (checked->value())
+ buttonGroup()->uncheckOtherButtons (this);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (getWidget()),
+ checked->value());
+
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) toggled_cb, this);
+ }
+
+ virtual YCPBoolean getValue()
+ {
+ IMPL
+ return YCPBoolean (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON (getWidget())));
+ }
+
+ // YWidget
+ YGWIDGET_IMPL_COMMON
+
+ // callbacks
+ static void toggled_cb (GtkButton *button, YGRadioButton *pThis)
+ {
+ IMPL
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+ pThis->buttonGroup()->uncheckOtherButtons (pThis);
+ else {
+ g_signal_handlers_block_by_func (button, (gpointer) toggled_cb, pThis);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+ g_signal_handlers_unblock_by_func (button, (gpointer) toggled_cb, pThis);
+ }
+
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+};
+
+YWidget *
+YGUI::createRadioButton (YWidget *parent, YWidgetOpt &opt,
+ YRadioButtonGroup *rbg, const YCPString &label,
+ bool checked)
+{
+ IMPL;
+ return new YGRadioButton (opt, YGWidget::get (parent), label, rbg, checked);
+}
+
+// YRadioButtonGroup
+
+class YGRadioButtonGroup : public YRadioButtonGroup, public YGWidget
+{
+public:
+ YGRadioButtonGroup(const YWidgetOpt &opt,
+ YGWidget *parent)
+ : YRadioButtonGroup (opt),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ { }
+
+ YGWIDGET_IMPL_COMMON
+ YGWIDGET_IMPL_CHILD_ADDED (m_widget)
+ YGWIDGET_IMPL_CHILD_REMOVED (m_widget)
+};
+
+YContainerWidget *
+YGUI::createRadioButtonGroup (YWidget *parent, YWidgetOpt &opt)
+{
+ IMPL;
+ return new YGRadioButtonGroup (opt, YGWidget::get (parent));
+}
+
+#include "YCheckBox.h"
+
+class YGCheckBox : public YCheckBox, public YGWidget
+{
+ bool m_isBold;
+
+public:
+ YGCheckBox(const YWidgetOpt &opt,
+ YGWidget *parent,
+ const YCPString &label_str,
+ bool checked)
+ : YCheckBox (opt, label_str),
+ YGWidget (this, parent, true, GTK_TYPE_CHECK_BUTTON, NULL)
+ {
+ IMPL
+ setBorder (0);
+ m_isBold = opt.boldFont.value();
+
+ gtk_button_set_use_underline (GTK_BUTTON (getWidget()), TRUE);
+ setLabel (label_str);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (getWidget()), checked);
+
+ g_signal_connect (G_OBJECT (getWidget ()), "toggled",
+ G_CALLBACK (toggled_cb), this);
+ }
+
+ // YCheckButton
+ virtual void setLabel (const YCPString &text)
+ {
+ IMPL
+ string str = YGUtils::mapKBAccel(text->value_cstr());
+ if (m_isBold)
+ str = "<b>" + str + "</b>";
+ gtk_button_set_label (GTK_BUTTON (getWidget()), str.c_str());
+ YCheckBox::setLabel (text);
+
+ GtkWidget *label = gtk_bin_get_child (GTK_BIN (getWidget()));
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ }
+
+ virtual void setValue (const YCPValue &val)
+ {
+ IMPL;
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (getWidget());
+
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) toggled_cb, this);
+
+ if (val->isBoolean()) {
+ gtk_toggle_button_set_inconsistent (button, FALSE);
+ gtk_toggle_button_set_active (button, val->asBoolean()->value());
+ }
+ else
+ gtk_toggle_button_set_inconsistent (button, TRUE);
+
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) toggled_cb, this);
+ }
+
+ virtual YCPValue getValue()
+ {
+ IMPL;
+
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (getWidget());
+
+ if (gtk_toggle_button_get_inconsistent (button))
+ return YCPVoid();
+ else
+ return YCPBoolean (gtk_toggle_button_get_active (button));
+ }
+
+ static void toggled_cb (GtkBox *box, YGCheckBox *pThis)
+ {
+ IMPL
+ GtkToggleButton *button = GTK_TOGGLE_BUTTON (box);
+ if (gtk_toggle_button_get_inconsistent (button)) {
+ gtk_toggle_button_set_inconsistent (button, false);
+ pThis->setValue (YCPBoolean (true));
+ }
+
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createCheckBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ bool checked)
+{
+ IMPL;
+ return new YGCheckBox (opt, YGWidget::get (parent), label, checked);
+}
Added: trunk/gtk/src/YGTable.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGTable.cc?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGTable.cc (added)
+++ trunk/gtk/src/YGTable.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,523 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+/* A generic widget for table related widgets. */
+class YGTableView : public YGScrolledWidget
+{
+protected:
+ int m_colsNb;
+
+public:
+ YGTableView (YWidget *y_widget, YGWidget *parent,
+ const YWidgetOpt &opt, YCPString label)
+ : YGScrolledWidget (y_widget, parent, label, YD_VERT, true,
+ GTK_TYPE_TREE_VIEW, NULL)
+ {
+ IMPL
+ m_colsNb = 0;
+
+ /* 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 (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (getWidget())), GTK_SELECTION_BROWSE);
+
+ // let the derivates do the event hooks. They have subtile differences.
+ }
+
+ void initModel (const vector <GType> &types, bool show_headers)
+ {
+ IMPL
+ // turn vector into an array; last column dedicated to the row id
+ m_colsNb = types.size();
+ GType types_array [m_colsNb+1];
+ for (unsigned int i = 0; i < types.size(); i++)
+ types_array [i] = types[i];
+ types_array[m_colsNb] = G_TYPE_INT;
+
+ GtkListStore *list = gtk_list_store_newv (m_colsNb+1, types_array);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (getWidget()), GTK_TREE_MODEL (list));
+ g_object_unref (G_OBJECT (list));
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (getWidget()), show_headers);
+ }
+
+ void insertColumn (int col_nb, string header, GType type)
+ {
+ IMPL
+ GtkTreeViewColumn *column = 0;
+
+ // The allignment of the column items
+ gfloat xalign = 0.0;
+ if (header.length()) {
+ if (header[0] == 'R')
+ xalign = 1.0;
+ else if (header[0] == 'C')
+ xalign = 0.5;
+ // else if (header[0] == 'L')
+ header = header.substr(1);
+ }
+
+ if (type == G_TYPE_STRING) {
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
+ g_object_set (renderer, "xalign", xalign, NULL);
+ // set the last column, the expandable one, as wrapable
+ if (col_nb == m_colsNb-1 && col_nb >= 3)
+ g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ column = gtk_tree_view_column_new_with_attributes (header.c_str(),
+ renderer, "text", col_nb, NULL);
+ }
+ else if (type == G_TYPE_BOOLEAN) { // toggle button
+ GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
+ g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (col_nb));
+ g_object_set (renderer, "xalign", xalign, NULL);
+ column = gtk_tree_view_column_new_with_attributes (header.c_str(),
+ renderer, "active", col_nb, NULL);
+
+ g_signal_connect (G_OBJECT (renderer), "toggled",
+ G_CALLBACK (toggled_cb), this);
+ }
+ else if (type == GDK_TYPE_PIXBUF) {
+ GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new();
+ g_object_set (renderer, "xalign", xalign, NULL);
+ column = gtk_tree_view_column_new_with_attributes (header.c_str(),
+ renderer, "pixbuf", col_nb, NULL);
+ }
+ else
+ g_error ("YGTable: no support for column of given type");
+
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_insert_column (GTK_TREE_VIEW (getWidget()), column, col_nb);
+ }
+
+ void setSearchCol (int col)
+ {
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (getWidget()), col);
+ }
+
+protected:
+ inline GtkListStore *getStore()
+ { return GTK_LIST_STORE (getModel()); }
+ inline GtkTreeModel *getModel()
+ { return gtk_tree_view_get_model (GTK_TREE_VIEW (getWidget())); }
+
+protected:
+ /* NOTE: gtk_list_store_insert() doesn't necessarly put the row in the
+ requested position. For instance, if the number of rows is smaller than
+ the one requested, it just appends it. So, we must translate YCP rows
+ numbering to the ones we set. We'll call YCP rows as ids.
+ Besides, if we do sorting, paths will get changed. */
+
+ bool getRowOf (GtkTreeIter *iter, int id) {
+ if (!gtk_tree_model_get_iter_first (getModel(), iter))
+ return false;
+
+ int _id = -1;
+ do {
+ gtk_tree_model_get (getModel(), iter, m_colsNb, &_id, -1);
+ if (_id == id)
+ return true;
+ } while (gtk_tree_model_iter_next (getModel(), iter));
+ return false;
+ }
+
+ int getIdOf (int row) {
+ GtkTreeIter iter;
+ if (!gtk_tree_model_iter_nth_child (getModel(), &iter, NULL, row))
+ return -1;
+
+ int id;
+ gtk_tree_model_get (getModel(), &iter, m_colsNb, &id, -1);
+ return id;
+ }
+
+ void addRow (int id)
+ {
+ IMPL
+ GtkTreeIter iter;
+ gtk_list_store_append (getStore(), &iter);
+ gtk_list_store_set (getStore(), &iter, m_colsNb, id, -1);
+ }
+
+ void setItemText (string text, int id, int col)
+ {
+ IMPL
+ GtkTreeIter iter;
+ if (getRowOf (&iter, id))
+ gtk_list_store_set (getStore(), &iter, col, text.c_str(), -1);
+ }
+
+ void setItemBool (gboolean state, int id, int col)
+ {
+ IMPL
+ GtkTreeIter iter;
+ if (getRowOf (&iter, id))
+ gtk_list_store_set (getStore(), &iter, col, state, -1);
+ }
+
+ void setItemIcon (string icon, int id, int col)
+ {
+ IMPL
+ GtkTreeIter iter;
+ if (getRowOf (&iter, id)) {
+ GdkPixbuf *pixbuf;
+ if (icon[0] != '/')
+ icon = ICON_DIR + icon;
+
+ GError *error = 0;
+ pixbuf = gdk_pixbuf_new_from_file (icon.c_str(), &error);
+ if (!pixbuf)
+ y2warning ("YGTable: Could not load icon: %s.\n"
+ "Because %s", icon.c_str(), error->message);
+
+ gtk_list_store_set (getStore(), &iter, col, pixbuf, -1);
+ }
+ }
+
+ void deleteRows()
+ {
+ IMPL
+ blockEvents();
+ gtk_list_store_clear (getStore());
+ unblockEvents();
+ }
+
+ int getCurrentRow()
+ {
+ IMPL
+ GtkTreePath *path;
+ gtk_tree_view_get_cursor (GTK_TREE_VIEW(getWidget()), &path, NULL);
+ if (path == NULL)
+ return -1;
+
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (getModel(), &iter, path);
+ gtk_tree_path_free (path);
+
+ int id;
+ gtk_tree_model_get (getModel(), &iter, m_colsNb, &id, -1);
+ return id;
+ }
+
+ void setCurrentRow (int id)
+ {
+ IMPL
+ blockEvents();
+ GtkTreeIter iter;
+ if (getRowOf (&iter, id)) {
+ GtkTreePath *path = gtk_tree_model_get_path (getModel(), &iter);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (getWidget()), path, NULL, false);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (getWidget()), path, NULL,
+ TRUE, 0.5, 0.5);
+ gtk_tree_path_free (path);
+ }
+ unblockEvents();
+ }
+
+ void blockEvents()
+ {
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) selected_cb, this);
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) selected_delayed_cb, this);
+ }
+ void unblockEvents()
+ {
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) selected_cb, this);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) selected_delayed_cb, this);
+ }
+
+ // toggled by user (through clicking on the renderer or some other action)
+ void toggle (GtkTreePath *path, gint column)
+ {
+ IMPL
+ GtkTreeIter iter;
+ if (!gtk_tree_model_get_iter (getModel(), &iter, path))
+ return;
+ gboolean state;
+
+ gtk_tree_model_get (getModel(), &iter, column, &state, -1);
+ gtk_list_store_set (getStore(), &iter, column, !state, -1);
+
+ emitEvent (YEvent::ValueChanged);
+ }
+
+ static void selected_cb (GtkTreeView *tree_view, YGTableView* pThis)
+ {
+ IMPL
+ pThis->emitEvent (YEvent::SelectionChanged);
+ }
+
+ static void selected_delayed_cb (GtkTreeView *tree_view, YGTableView* pThis)
+ {
+ IMPL
+ pThis->emitEvent (YEvent::SelectionChanged, true, true, false);
+ }
+
+ static void activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
+ GtkTreeViewColumn *column, YGTableView* pThis)
+ {
+ IMPL
+ pThis->emitEvent (YEvent::Activated);
+ }
+
+ static void toggled_cb (GtkCellRendererToggle *renderer, gchar *path_str,
+ YGTableView *pThis)
+ {
+ IMPL
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer), "column"));
+ pThis->toggle (path, column);
+ gtk_tree_path_free (path);
+ }
+};
+
+#include "YTable.h"
+
+class YGTable : public YTable, public YGTableView
+{
+public:
+ YGTable (const YWidgetOpt &opt, YGWidget *parent,
+ vector <string> headers)
+ : YTable (opt, headers.size()),
+ YGTableView (this, parent, opt, YCPString(""))
+ {
+ IMPL
+ vector <GType> types;
+ types.assign (numCols(), G_TYPE_STRING);
+ initModel (types, true);
+ for (int i = 0; i < numCols(); i++)
+ insertColumn (i, headers[i], types[i]);
+
+ setLabelVisible (false);
+
+ if (!opt.keepSorting.value())
+ YGUtils::tree_view_set_sortable (GTK_TREE_VIEW (getWidget()), 0);
+ if (numCols() >= 3)
+ gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (getWidget()), TRUE);
+
+ g_signal_connect (G_OBJECT (getWidget()), "row-activated",
+ G_CALLBACK (activated_cb), (YGTableView*) this);
+ if (opt.immediateMode.value())
+ g_signal_connect (G_OBJECT (getWidget()), "cursor-changed",
+ G_CALLBACK (selected_cb), (YGTableView*) this);
+ }
+
+ virtual void itemAdded (vector<string> elements, int index)
+ {
+ IMPL
+ addRow (index);
+ for (unsigned int c = 0; c < elements.size(); c++)
+ setItemText (elements[c], index, c);
+
+ // always have one row selected
+ if (getCurrentRow() == -1)
+ setCurrentRow (index);
+ }
+
+ virtual void itemsCleared()
+ { IMPL; deleteRows(); }
+
+ virtual void cellChanged (int index, int colnum, const YCPString& text)
+ { IMPL; setItemText (text->value(), index, colnum); }
+
+ virtual int getCurrentItem()
+ { IMPL; return getCurrentRow(); }
+
+ virtual void setCurrentItem (int index)
+ { IMPL; setCurrentRow (index); }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createTable (YWidget *parent, YWidgetOpt & opt,
+ vector<string> headers)
+{
+ return new YGTable (opt, YGWidget::get (parent), headers);
+}
+
+#include "YSelectionBox.h"
+
+class YGSelectionBox : public YSelectionBox, public YGTableView
+{
+public:
+ YGSelectionBox (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label)
+ : YSelectionBox (opt, label),
+ YGTableView (this, parent, opt, label)
+ {
+ /* we'll have to wait for 09 to get nicer to construct vectors :P */
+ vector <GType> types;
+ types.push_back (GDK_TYPE_PIXBUF);
+ types.push_back (G_TYPE_STRING);
+ initModel (types, false);
+
+ insertColumn (1, "", G_TYPE_STRING);
+ setSearchCol (1);
+ // pixbuf column will be added later, if needed
+
+ g_signal_connect (G_OBJECT (getWidget()), "row-activated",
+ G_CALLBACK (activated_cb), (YGTableView*) this);
+ if (opt.immediateMode.value())
+ g_signal_connect (G_OBJECT (getWidget()), "cursor-changed",
+ G_CALLBACK (selected_cb), (YGTableView*) this);
+ else
+ g_signal_connect (G_OBJECT (getWidget()), "cursor-changed",
+ G_CALLBACK (selected_delayed_cb), (YGTableView*) this);
+ }
+
+ // YSelectionBox
+ virtual int getCurrentItem()
+ { IMPL; return getCurrentRow(); }
+
+ virtual void setCurrentItem (int index)
+ { IMPL; setCurrentRow (index); }
+
+ // YSelectionWidget
+ virtual void itemAdded (const YCPString &str, int index, bool selected)
+ {
+ IMPL
+ addRow (index);
+
+ if (hasIcons()) {
+ if (m_colsNb == 1) // make space for pixbufs
+ insertColumn (0, "", GDK_TYPE_PIXBUF);
+ setItemIcon (itemIcon (index)->value(), index, 0);
+ }
+ setItemText (str->value(), index, 1);
+
+ if (selected)
+ setCurrentRow (index);
+ }
+
+ virtual void deleteAllItems()
+ { IMPL; deleteRows(); }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createSelectionBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ IMPL
+ return new YGSelectionBox (opt, YGWidget::get (parent), label);
+}
+
+#include "YMultiSelectionBox.h"
+
+class YGMultiSelectionBox : public YMultiSelectionBox, public YGTableView
+{
+public:
+ YGMultiSelectionBox (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label)
+ : YMultiSelectionBox (opt, label),
+ YGTableView (this, parent, opt, label)
+ {
+ vector <GType> types;
+ types.push_back (G_TYPE_BOOLEAN);
+ types.push_back (GDK_TYPE_PIXBUF);
+ types.push_back (G_TYPE_STRING);
+ initModel (types, false);
+
+ insertColumn (0, "", G_TYPE_BOOLEAN);
+ insertColumn (2, "", G_TYPE_STRING);
+ setSearchCol (2);
+ // pixbuf column will be added later, if needed
+
+ g_signal_connect (G_OBJECT (getWidget()), "cursor-changed",
+ G_CALLBACK (selected_cb), (YGTableView*) this);
+ // Let the user toggle, using space/enter or double click (not an event).
+ g_signal_connect_after (G_OBJECT (getWidget()), "row-activated",
+ G_CALLBACK (multi_activated_cb), this);
+ }
+
+ // YMultiSelectionBox
+ virtual int getCurrentItem()
+ { IMPL; return getCurrentRow(); }
+
+ virtual void setCurrentItem (int index)
+ { IMPL; setCurrentRow (index); }
+
+ // YSelectionWidget
+ virtual void itemAdded (const YCPString &str, int index, bool selected)
+ {
+ IMPL
+ addRow (index);
+
+ if (hasIcons()) {
+ if (m_colsNb == 2) // make space for pixbufs
+ insertColumn (1, "", GDK_TYPE_PIXBUF);
+ setItemIcon (itemIcon (index)->value(), index, 1);
+ }
+ setItemBool (selected, index, 0);
+ setItemText (str->value(), index, 2);
+ }
+
+ virtual void deleteAllItems()
+ { IMPL; deleteRows(); }
+
+ // Toggle related methods follow
+ /* Returns the state of the toggle at the row "index".
+ Pass -1 for query only. 0 and 1 to set it false or true. */
+ bool itemSelected (int id, int state)
+ {
+ IMPL
+ GtkTreeIter iter;
+ if (!getRowOf (&iter, id))
+ throw "Row doesn't exist";
+
+ if (state != -1)
+ gtk_list_store_set (getStore(), &iter, 0, state, -1);
+ gtk_tree_model_get (getModel(), &iter, 0, &state, -1);
+ return state;
+ }
+
+ virtual bool itemIsSelected (int index)
+ {
+ IMPL
+ bool state = 0;
+ try { state = itemSelected (index, -1); }
+ catch (char *str) { y2error ("%s - itemIsSelected(%d): %s - ignoring",
+ YMultiSelectionBox::widgetClass(), index, str); }
+ return state;
+ }
+
+ virtual void selectItem (int index)
+ {
+ IMPL
+ try { itemSelected (index, 1); }
+ catch (char *str) { y2error ("%s - selectItem(%d): %s - ignoring",
+ YMultiSelectionBox::widgetClass(), index, str); }
+ }
+
+ virtual void deselectAllItems()
+ {
+ for (int i = 0; ; i++)
+ try { itemSelected (i, false); }
+ catch (...) { break; }
+ }
+
+ static void multi_activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
+ GtkTreeViewColumn *column, YGMultiSelectionBox* pThis)
+ {
+ IMPL
+ pThis->toggle (path, 0);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createMultiSelectionBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ IMPL
+ return new YGMultiSelectionBox (opt, YGWidget::get (parent), label);
+}
Added: trunk/gtk/src/YGTextEntry.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGTextEntry.cc?rev=42515…
==============================================================================
--- trunk/gtk/src/YGTextEntry.cc (added)
+++ trunk/gtk/src/YGTextEntry.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,74 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YTextEntry.h"
+#include "YGWidget.h"
+#include "ygtkfieldentry.h"
+
+class YGTextEntry : public YTextEntry, public YGLabeledWidget
+{
+public:
+ YGTextEntry (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, const YCPString &text)
+ : YTextEntry (opt, label),
+ YGLabeledWidget (this, parent, label, YD_HORIZ, true,
+ YGTK_TYPE_FILTER_ENTRY, NULL)
+ {
+ gtk_entry_set_activates_default (GTK_ENTRY (getWidget()), TRUE);
+ setText (text);
+
+ if (opt.passwordMode.value())
+ gtk_entry_set_visibility (GTK_ENTRY (getWidget()), FALSE);
+
+ // Signals to know of any text modification
+ g_signal_connect (G_OBJECT (getWidget()), "changed",
+ G_CALLBACK (text_changed_cb), this);
+ }
+
+ virtual ~YGTextEntry() {}
+
+ // YTextEntry
+ virtual YCPString getText()
+ {
+ return YCPString (gtk_entry_get_text (GTK_ENTRY (getWidget())));
+ }
+
+ virtual void setText (const YCPString &text)
+ {
+ /* No need to check for valid chars as that's the responsible of the YCP
+ application programmer. */
+ gtk_entry_set_text (GTK_ENTRY (getWidget()), text->value_cstr());
+ }
+
+ virtual void setInputMaxLength (const YCPInteger &numberOfChars)
+ {
+ gtk_entry_set_width_chars (GTK_ENTRY (getWidget()),
+ numberOfChars->asInteger()->value());
+ }
+
+ virtual void setValidChars (const YCPString &validChars)
+ {
+ ygtk_filter_entry_set_valid_chars (YGTK_FILTER_ENTRY (getWidget()),
+ validChars->value_cstr());
+ YTextEntry::setValidChars (validChars);
+ }
+
+ static void text_changed_cb (GtkEditable *editable, YGTextEntry *pThis)
+ {
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YTextEntry)
+};
+
+YWidget *
+YGUI::createTextEntry (YWidget *parent, YWidgetOpt & opt,
+ const YCPString & label, const YCPString & text)
+{
+ return new YGTextEntry (opt, YGWidget::get (parent), label, text);
+}
Added: trunk/gtk/src/YGTime.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGTime.cc?rev=42515&view…
==============================================================================
--- trunk/gtk/src/YGTime.cc (added)
+++ trunk/gtk/src/YGTime.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,229 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+#include "ygtkfieldentry.h"
+
+#include "YTime.h"
+
+class YGTime : public YTime, public YGLabeledWidget
+{
+public:
+ YGTime (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, const YCPString &time)
+ : YTime (opt, label),
+ YGLabeledWidget (this, parent, label, YD_HORIZ, true,
+ YGTK_TYPE_FIELD_ENTRY, NULL)
+ {
+ IMPL
+ ygtk_field_entry_add_field (YGTK_FIELD_ENTRY (getWidget()), ':',
+ 2, "0123456789");
+ ygtk_field_entry_add_field (YGTK_FIELD_ENTRY (getWidget()), ':',
+ 2, "0123456789");
+ setNewTime (time);
+
+ gtk_widget_show_all (getWidget());
+ g_signal_connect (G_OBJECT (getWidget()), "field-entry-changed",
+ G_CALLBACK (value_changed_cb), this);
+ }
+
+ virtual ~YGTime() {}
+
+ // YTime
+ virtual void setNewTime (const YCPString &time)
+ {
+ IMPL
+ char hours[3], mins[3];
+ sscanf (time->value_cstr(), "%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 YCPString getTime()
+ {
+ IMPL
+ 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));
+ YCPString str = YCPString (time);
+ g_free (time);
+ return str;
+ }
+
+ // callbacks
+ static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb,
+ YGTime *pThis)
+ { IMPL; pThis->emitEvent (YEvent::ValueChanged); }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YTime)
+};
+
+YWidget *
+YGUI::createTime (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, const YCPString &time)
+{
+ IMPL
+ return new YGTime (opt, YGWidget::get (parent), label, time);
+}
+
+#include "YDate.h"
+#include "ygtkmenubutton.h"
+
+class YGDate : public YDate, public YGLabeledWidget
+{
+ GtkWidget *m_entry, *m_calendar, *m_popup_calendar;
+
+public:
+ YGDate (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, const YCPString &date)
+ : YDate (opt, label),
+ YGLabeledWidget (this, parent, label, YD_HORIZ, true, GTK_TYPE_HBOX, NULL)
+ {
+ IMPL
+ m_entry = ygtk_field_entry_new();
+ ygtk_field_entry_add_field (YGTK_FIELD_ENTRY (m_entry), '-', 4, "0123456789");
+ ygtk_field_entry_add_field (YGTK_FIELD_ENTRY (m_entry), '-', 2, "0123456789");
+ ygtk_field_entry_add_field (YGTK_FIELD_ENTRY (m_entry), '-', 2, "0123456789");
+
+ GtkWidget *menu_button = ygtk_menu_button_new();
+ m_calendar = gtk_calendar_new();
+ gtk_widget_show (m_calendar);
+ GtkWidget *popup = ygtk_popup_window_new (m_calendar);
+ ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (menu_button), popup);
+
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (getWidget()), menu_button, FALSE, TRUE, 6);
+ gtk_widget_show_all (getWidget());
+
+ setNewDate (date);
+ g_signal_connect (G_OBJECT (m_entry), "field-entry-changed",
+ G_CALLBACK (value_changed_cb), this);
+
+ g_signal_connect (G_OBJECT (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);
+ }
+
+ virtual ~YGDate() {}
+
+ GtkCalendar *getCalendar()
+ { return GTK_CALENDAR (m_calendar); }
+
+ YGtkFieldEntry *getEntry()
+ { return YGTK_FIELD_ENTRY (m_entry); }
+
+ // YDate
+ virtual void setNewDate (const YCPString &date)
+ {
+ IMPL
+ char year[5], month[3], day[3];
+ sscanf (date->value_cstr(), "%4s-%2s-%2s", year, month, day);
+
+ gtk_calendar_select_month (getCalendar(), atoi (month)-1, atoi (year));
+ gtk_calendar_select_day (getCalendar(), atoi (day));
+
+ YGtkFieldEntry *entry = getEntry();
+ ygtk_field_entry_set_field_text (entry, 0, year);
+ ygtk_field_entry_set_field_text (entry, 1, month);
+ ygtk_field_entry_set_field_text (entry, 2, day);
+ }
+
+ virtual YCPString getDate()
+ {
+ IMPL
+ const gchar *year, *month, *day;
+ YGtkFieldEntry *entry = getEntry();
+ year = ygtk_field_entry_get_field_text (entry, 0);
+ month = ygtk_field_entry_get_field_text (entry, 1);
+ day = ygtk_field_entry_get_field_text (entry, 2);
+
+ gchar *time = g_strdup_printf ("%04d-%02d-%02d", atoi (year),
+ atoi (month), atoi (day));
+ YCPString str = YCPString (time);
+ g_free (time);
+ return str;
+ }
+
+ // callbacks
+ static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb,
+ YGDate *pThis)
+ {
+ IMPL
+ int year, month, day;
+ year = atoi (ygtk_field_entry_get_field_text (pThis->getEntry(), 0));
+ month = atoi (ygtk_field_entry_get_field_text (pThis->getEntry(), 1));
+ day = atoi (ygtk_field_entry_get_field_text (pThis->getEntry(), 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, YGDate *pThis)
+ {
+ IMPL
+ 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->getEntry(),
+ (gpointer) value_changed_cb, pThis);
+
+ YGtkFieldEntry *entry = pThis->getEntry();
+ 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->getEntry(),
+ (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));
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YDate)
+};
+
+YWidget *
+YGUI::createDate (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, const YCPString &date)
+{
+ IMPL
+ return new YGDate (opt, YGWidget::get (parent), label, date);
+}
Added: trunk/gtk/src/YGTree.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGTree.cc?rev=42515&view…
==============================================================================
--- trunk/gtk/src/YGTree.cc (added)
+++ trunk/gtk/src/YGTree.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,156 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YEvent.h"
+#include "YTree.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+class YGTree : public YTree, public YGScrolledWidget
+{
+public:
+ YGTree (const YWidgetOpt &opt, YGWidget *parent, YCPString label)
+ : YTree (opt, label)
+ , YGScrolledWidget (this, parent, label, YD_VERT, true,
+ GTK_TYPE_TREE_VIEW, NULL)
+ {
+ GtkTreeStore *tree = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(getWidget()), GTK_TREE_MODEL(tree));
+ g_object_unref (G_OBJECT (tree));
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (getWidget()),
+ 0, "", gtk_cell_renderer_text_new(), "text", 0, NULL);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (getWidget()), FALSE);
+
+ // Events
+ if (opt.notifyMode.value()) {
+ g_signal_connect (G_OBJECT (getWidget()), "row-activated",
+ G_CALLBACK (activated_cb), this);
+ g_signal_connect (G_OBJECT (getWidget()), "cursor-changed",
+ G_CALLBACK (selected_cb), this);
+ }
+ else
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (getWidget())), GTK_SELECTION_NONE);
+ }
+
+ virtual ~YGTree() { }
+
+ inline GtkTreeModel *getModel()
+ { return gtk_tree_view_get_model (GTK_TREE_VIEW (getWidget())); }
+ inline GtkTreeStore *getStore()
+ { return GTK_TREE_STORE (getModel()); }
+
+ // YTree
+ void addItems (const YTreeItemList &items, GtkTreeIter *parent)
+ {
+ GtkTreeIter iter;
+ for (unsigned int i = 0; i < items.size(); i++) {
+ gtk_tree_store_append (getStore(), &iter, parent);
+ gtk_tree_store_set (getStore(), &iter, 0,
+ items[i]->getText()->value_cstr(), 1, items[i], -1);
+
+ // store pointer to GtkTreePath for use in setCurrentItem()
+ { // need to create a path cause iterator would only return the path as a string
+ GtkTreePath* path = gtk_tree_model_get_path (getModel(), &iter);
+ // get current index...
+ gint depth = gtk_tree_path_get_depth (path);
+ gint *index = gtk_tree_path_get_indices (path) + depth - 1;
+ items[i]->setData (GINT_TO_POINTER (*index));
+ gtk_tree_path_free (path);
+ }
+
+ if (parent && items[i]->parent()->isOpenByDefault()) {
+ GtkTreePath *path = gtk_tree_model_get_path (getModel(), &iter);
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (getWidget()), path);
+ gtk_tree_path_free(path);
+ }
+
+ addItems (items[i]->itemList(), &iter);
+ }
+ }
+
+ virtual void rebuildTree()
+ {
+ gtk_tree_store_clear (getStore());
+ addItems (items, NULL);
+ }
+
+protected:
+ virtual const YTreeItem *getCurrentItem() const
+ {
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ gtk_tree_view_get_cursor
+ (GTK_TREE_VIEW(const_cast<YGTree *>(this)->getWidget()),
+ &path, &column);
+ if (path == NULL || column == NULL)
+ return NULL;
+
+ GtkTreeIter iter;
+ YTreeItem *item = 0;
+ gtk_tree_model_get_iter
+ (const_cast<YGTree *>(this)->getModel(), &iter, path);
+ gtk_tree_model_get
+ (const_cast<YGTree *>(this)->getModel(), &iter, 1, &item, -1);
+
+ return item;
+ }
+
+ /* Constructs a GtkTreePath to the item.
+ path argument must have been created and unset. */
+ void getItemPath (GtkTreePath *path, YTreeItem *item)
+ {
+ if (item == NULL)
+ return;
+ getItemPath (path, item->parent());
+ gtk_tree_path_append_index (path, GPOINTER_TO_INT (item->data()));
+ }
+
+ virtual void setCurrentItem (YTreeItem *item)
+ {
+ IMPL
+ GtkTreePath *path = gtk_tree_path_new();
+ getItemPath (path, item);
+
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) selected_cb, this);
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (getWidget()), path);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW(getWidget()), path, NULL, FALSE);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) selected_cb, this);
+
+ gtk_tree_path_free (path);
+ }
+
+ virtual void deleteAllItems()
+ {
+ gtk_tree_store_clear (getStore());
+ YTree::deleteAllItems();
+ }
+
+ static void selected_cb (GtkTreeView *tree_view, YWidget* pThis)
+ {
+ if (pThis->getNotify() && !YGUI::ui()->eventPendingFor(pThis))
+ YGUI::ui()->sendEvent (new YWidgetEvent (pThis, YEvent::SelectionChanged));
+ }
+
+ static void activated_cb (GtkTreeView *tree_view, GtkTreePath *path,
+ GtkTreeViewColumn *column, YGTree* pThis)
+ {
+ if (pThis->getNotify())
+ YGUI::ui()->sendEvent (new YWidgetEvent (pThis, YEvent::Activated));
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YTree)
+};
+
+YWidget *
+YGUI::createTree (YWidget *parent, YWidgetOpt & opt, const YCPString & label)
+{
+ return new YGTree (opt, YGWidget::get (parent), label);
+}
+
Added: trunk/gtk/src/YGUI.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUI.cc?rev=42515&view=a…
==============================================================================
--- trunk/gtk/src/YGUI.cc (added)
+++ trunk/gtk/src/YGUI.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,770 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <stdio.h>
+#include <ycp/y2log.h>
+#include <YEvent.h>
+#include <YDialog.h>
+#include <YMacroRecorder.h>
+#include "YGUI.h"
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YGDialog.h"
+#include <glib/gthread.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define DEFAULT_MACRO_FILE_NAME "macro.ycp"
+#define BUSY_CURSOR_TIMEOUT 250
+
+YGUI::YGUI (int argc, char ** argv,
+ bool with_threads,
+ const char *macro_file) :
+ YUI (with_threads),
+ busy_timeout (0),
+ m_done_init (false),
+ m_argc (0),
+ m_argv (NULL)
+{
+ IMPL
+ m_have_wm = true;
+ m_no_border = m_fullscreen = false;
+ m_default_size.width = m_default_size.height = 0;
+
+ m_argc = argc;
+ m_argv = g_new0 (char *, argc);
+ memcpy (m_argv, argv, sizeof (char *) * argc);
+ if (!with_threads)
+ checkInit();
+
+#ifdef IMPL_DEBUG
+ fprintf (stderr, "I'm initialized '%s' - come & get me !\n",
+ with_threads ? "with threads !" : "no threads");
+#endif
+
+ for (int i = 1; i < m_argc; i++)
+ {
+ const char *argp = m_argv[i];
+ if (!argp) continue;
+ if (argp[0] != '-') {
+ printf ("Warning: Unknown argument '%s'\n", argp);
+ continue;
+ }
+ argp++;
+ if (argp[0] == '-') argp++;
+
+ if (!strcmp (argp, "no-wm"))
+ m_have_wm = false;
+ else if (!strcmp (argp, "fullscreen"))
+ m_fullscreen = true;
+ else if (!strcmp (argp, "noborder"))
+ m_no_border = true;
+ else if (!strcmp (argp, "geometry")) {
+ argp = argv [++i];
+ if (i == argc)
+ printf ("Warning: no value passed to --geometry\n");
+ else if (sscanf (argp, "%dx%d", &m_default_size.width,
+ &m_default_size.height) == EOF) {
+ printf ("Warning: invalid --geometry value: %s\n", argp);
+ m_default_size.width = m_default_size.height = 0;
+ }
+ }
+ else if (!strcmp (argp, "help")) {
+ printf (
+ "Command line options for the YaST2 Gtk UI:\n"
+ "\n"
+ "--no-wm assume no window manager is running\n"
+ "--noborder no window manager border for main dialogs\n"
+ "--fullscreen use full screen for main dialogs\n"
+ "--geomtry WxH sets a default size of W per H to main dialogs\n"
+ "--nothreads run without additional UI threads\n"
+ "--help prints this help text\n"
+ "\n"
+ );
+ exit (0);
+ }
+ else
+ printf ("Warning: Unknown argument '--%s'\n", argp);
+ }
+
+ if (macro_file)
+ playMacro (macro_file);
+
+ // without this none of the (default) threading action works ...
+ topmostConstructorHasFinished();
+}
+
+YGUI::~YGUI()
+{
+ IMPL
+ g_free (m_argv);
+}
+
+static gboolean
+ycp_wakeup_fn (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ *(int *)data = TRUE;
+ return TRUE;
+}
+
+void YGUI::checkInit()
+{
+ if (!m_done_init) {
+ gtk_init (&m_argc, &m_argv);
+ m_done_init = TRUE;
+ }
+}
+
+void
+YGUI::idleLoop (int fd_ycp)
+{
+ IMPL
+ // 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)
+{
+ IMPL
+ if (!pThis->pendingEvent())
+ pThis->sendEvent (new YTimeoutEvent());
+ return FALSE;
+}
+
+void
+YGUI::sendEvent (YEvent *event)
+{
+ m_event_handler.sendEvent (event);
+ g_main_context_wakeup (NULL);
+}
+
+// utility that implements both userInput() and pollInput()
+YEvent *
+YGUI::waitInput (unsigned long timeout_ms, bool block)
+{
+ IMPL
+ if (!currentYGDialog())
+ return NULL;
+
+ if (block)
+ normalCursor(); // waiting for input, so no more busy
+
+ guint timeout = 0;
+ YEvent *event = NULL;
+
+ 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)) ;
+
+ 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
+ busy_timeout = g_timeout_add (BUSY_CURSOR_TIMEOUT, busy_timeout_cb, this);
+
+ return event;
+}
+
+YEvent *
+YGUI::userInput (unsigned long timeout_ms)
+{
+ return waitInput (timeout_ms, true);
+}
+
+YEvent *YGUI::pollInput()
+{
+ return waitInput (0, false);
+}
+
+// dialog bits
+
+static GdkScreen *getScreen ()
+{
+ return gdk_display_get_default_screen (gdk_display_get_default());
+}
+
+int YGUI::getDisplayWidth()
+{
+ IMPL
+ return gdk_screen_get_width (getScreen());
+}
+
+int YGUI::getDisplayHeight()
+{
+ IMPL
+ return gdk_screen_get_height (getScreen());
+}
+
+int YGUI::getDefaultSize (YUIDimension dim)
+{
+ if (dim == YD_HORIZ) {
+ if (!m_default_size.width) {
+ if (m_fullscreen)
+ m_default_size.width = getDisplayWidth();
+ else
+ m_default_size.width = MIN (600, getDisplayWidth());
+ }
+ return m_default_size.width;
+ }
+ else { // YD_VERT
+ if (!m_default_size.height) {
+ if (m_fullscreen)
+ m_default_size.height = getDisplayHeight();
+ else
+ m_default_size.height = MIN (450, getDisplayHeight());
+ }
+ return m_default_size.height;
+ }
+}
+
+// YWidget layout units -> pixels conversion. Same as yast-qt's.
+long YGUI::deviceUnits (YUIDimension dim, float size)
+{
+ if (dim == YD_HORIZ) return (long) ((size * (640.0/80)) + 0.5);
+ else return (long) ((size * (480.0/25)) + 0.5);
+}
+
+float YGUI::layoutUnits (YUIDimension dim, long device_units)
+{
+ float size = (float) device_units;
+ if (dim == YD_HORIZ) return size * (80/640.0);
+ else return size * (25/480.0);
+}
+
+static void errorMsg (const char *msg)
+{
+ GtkWidget* dialog = gtk_message_dialog_new
+ (NULL, GtkDialogFlags (0), GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK, "%s", msg);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+void YGUI::internalError (const char *msg)
+{
+ errorMsg (msg);
+ abort(); // going down
+}
+
+/* File/directory dialogs. */
+#include <sstream>
+
+static YCPValue askForFileOrDirectory (GtkFileChooserAction action,
+ const YCPString &path, const YCPString &filter_pattern,
+ const YCPString &title)
+{
+ IMPL
+ GtkWidget *dialog;
+ dialog = gtk_file_chooser_dialog_new (title->value_cstr(),
+ YGUI::ui()->currentWindow(), action, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ action == GTK_FILE_CHOOSER_ACTION_SAVE ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ // Yast likes to pass the path and suggested filename as a whole. We will need to
+ // split that up for GTK+.
+ string dirpath (path->value()), filename;
+ if (!dirpath.empty()) {
+ string::size_type i;
+ // we don't support local paths
+ if (dirpath [0] != '/') {
+ filename = dirpath;
+ dirpath = "";
+ }
+ else if (!(g_file_test (dirpath.c_str(), G_FILE_TEST_IS_DIR))) {
+ i = dirpath.find_last_of ("/");
+ if (i == string::npos) {
+ filename = dirpath;
+ dirpath = "";
+ }
+ else {
+ string path (dirpath);
+ dirpath = path.substr (0, i+1);
+ filename = path.substr (i+1);
+ }
+ }
+
+ // check if dirpath and filename are valid
+ if (!dirpath.empty())
+ if (!g_file_test (dirpath.c_str(), G_FILE_TEST_IS_DIR)) {
+ y2warning ("Path passed to file dialog isn't valid: '%s'", path->value_cstr());
+ dirpath = "";
+ }
+ i = filename.find ("/");
+ if (i != string::npos) {
+ y2warning ("Path passed to file dialog isn't valid: '%s'", path->value_cstr());
+ filename = "";
+ }
+ }
+
+ if (!dirpath.empty())
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dirpath.c_str());
+ if (!filename.empty())
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename.c_str());
+
+ string filter_str (filter_pattern->value());
+ if (filter_str != "" && filter_str != "*") {
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name (filter, filter_str.c_str());
+ // cut filter_pattern into chuncks like GTK likes
+ std::istringstream stream (filter_str);
+ while (!stream.eof()) {
+ string str;
+ stream >> str;
+ if (!str.empty() && str [str.size()-1] == ',')
+ str.erase (str.size()-1);
+ gtk_file_filter_add_pattern (filter, str.c_str());
+ }
+ gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+ }
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+ char* filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ YCPString ret (filename);
+ g_free (filename);
+
+ gtk_widget_destroy (dialog);
+ return ret;
+ }
+ gtk_widget_destroy (dialog);
+ return YCPVoid();
+}
+
+YCPValue YGUI::askForExistingDirectory (const YCPString &path,
+ const YCPString &title)
+{
+ IMPL
+ return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, path,
+ YCPString (""), title);
+}
+
+YCPValue YGUI::askForExistingFile (const YCPString &path,
+ const YCPString &filter, const YCPString &title)
+{
+ IMPL
+ return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_OPEN, path, filter, title);
+}
+
+YCPValue YGUI::askForSaveFileName (const YCPString &path,
+ const YCPString &filter, const YCPString &title)
+{
+ IMPL
+ return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE, path, filter, title);
+}
+
+bool YGUI::textMode() IMPL_RET(false)
+bool YGUI::hasImageSupport() IMPL_RET(true)
+bool YGUI::hasLocalImageSupport() IMPL_RET(true)
+bool YGUI::hasAnimationSupport() IMPL_RET(true)
+bool YGUI::hasIconSupport() IMPL_RET(true)
+bool YGUI::hasFullUtf8Support() IMPL_RET(true)
+bool YGUI::richTextSupportsTable() IMPL_RET(false)
+bool YGUI::leftHandedMouse() IMPL_RET(false)
+
+gboolean YGUI::busy_timeout_cb (gpointer data)
+{
+ YGUI *pThis = (YGUI *) data;
+ pThis->busyCursor();
+ pThis->busy_timeout = 0;
+ return FALSE;
+}
+
+void YGUI::busyCursor()
+{
+ YGDialog *dialog = currentYGDialog();
+ if (dialog)
+ dialog->busyCursor();
+}
+
+void YGUI::normalCursor()
+{
+ if (busy_timeout) {
+ g_source_remove (busy_timeout);
+ busy_timeout = 0;
+ }
+
+ YGDialog *dialog = currentYGDialog();
+ if (dialog)
+ dialog->normalCursor();
+}
+
+void YGUI::redrawScreen()
+{
+ gtk_widget_queue_draw (GTK_WIDGET (currentWindow()));
+}
+
+YCPValue YGUI::runPkgSelection (YWidget *packageSelector)
+{
+ y2milestone ("Running package selection...");
+
+ // TODO: we may have to do some trickery here to disable close button
+ // and auto activate dialogs (whatever that is)
+// _wm_close_blocked = true;
+// _auto_activate_dialogs = false;
+
+ YCPValue input = YCPVoid();
+ try {
+ input = evaluateUserInput();
+ }
+ catch (const std::exception &e) {
+ y2error ("Caught std::exception: %s", e.what());
+ y2error ("This is a libzypp problem. Do not file a bug against the UI!");
+ }
+ catch (...) {
+ y2error ("Caught unspecified exception.");
+ y2error ("This is a libzypp problem. Do not file a bug against the UI!");
+ }
+
+// _auto_activate_dialogs = true;
+// _wm_close_blocked = false;
+ y2milestone ("Package selection done - returning %s", input->toString().c_str());
+
+ return input;
+}
+
+void YGUI::makeScreenShot (string filename)
+{
+ IMPL
+ bool interactive = filename.empty();
+
+ GtkWidget *widget = GTK_WIDGET (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 ("Couldn't take a 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 = moduleName();
+ if (!baseName)
+ baseName = "scr";
+
+ int nb;
+ map <string, int>::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);
+ }
+ y2debug ("screenshot: %s", filename.c_str());
+
+ YCPValue ret = askForSaveFileName (YCPString (filename.c_str()),
+ YCPString ("*.png"),
+ YCPString ("Save screenshot to"));
+ if (!ret->isString()) { // user dismissed the dialog
+ y2debug ("Save screen shot canceled by user");
+ goto makeScreenShot_ret;
+ }
+
+ filename = ret->asString()->value();
+ screenShotNb.erase (baseName);
+ screenShotNb[baseName] = nb + 1;
+ }
+
+ y2debug ("Saving screen shot to %s", filename.c_str());
+ if (gdk_pixbuf_save (shot, filename.c_str(), "png", &error, NULL)) {
+ y2error ("Couldn't save screen shot %s", filename.c_str());
+ if (interactive) {
+ string msg = "Couldn't save screenshot to file " + filename
+ + " - " + error->message;
+ errorMsg (msg.c_str());
+ }
+ goto makeScreenShot_ret;
+ }
+
+ if (recordingMacro()) {
+ // save the taking of the screenshot and its name to the macro
+ macroRecorder->beginBlock();
+ currentDialog()->saveUserInput (macroRecorder);
+ macroRecorder->recordMakeScreenShot (true, filename.c_str());
+ macroRecorder->recordUserInput (YCPVoid());
+ macroRecorder->endBlock();
+ }
+
+ makeScreenShot_ret:
+ g_object_unref (G_OBJECT (shot));
+}
+
+void YGUI::beep()
+{
+ gdk_beep();
+ GtkWindow *window = currentWindow();
+ if (window)
+ gtk_window_present (window);
+}
+
+YCPString YGUI::glyph (const YCPSymbol &symbol)
+{
+ string sym = symbol->symbol();
+ if (sym == YUIGlyph_ArrowLeft)
+ return YCPString ("\u2190");
+ if (sym == YUIGlyph_ArrowRight)
+ return YCPString ("\u2192");
+ if (sym == YUIGlyph_ArrowUp)
+ return YCPString ("\u2191");
+ if (sym == YUIGlyph_ArrowDown)
+ return YCPString ("\u2193");
+ if (sym == YUIGlyph_CheckMark)
+ return YCPString ("\u2714");
+ if (sym == YUIGlyph_BulletArrowRight)
+ return YCPString ("\u279c");
+ if (sym == YUIGlyph_BulletCircle)
+ return YCPString ("\u274d");
+ if (sym == YUIGlyph_BulletSquare)
+ return YCPString ("\u274f");
+ return YCPString ("");
+}
+
+void YGUI::toggleRecordMacro()
+{
+ if (recordingMacro()) {
+ stopRecordMacro();
+ 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 {
+ YCPValue ret = askForSaveFileName (YCPString (DEFAULT_MACRO_FILE_NAME),
+ YCPString ("*.ycp"),
+ YCPString ("Select Macro File to Record to"));
+ if (ret->isString()) {
+ YCPString filename = ret->asString();
+ recordMacro (filename->value_cstr());
+ }
+ }
+}
+
+void YGUI::askPlayMacro()
+{
+ YCPValue ret = askForExistingFile (YCPString (DEFAULT_MACRO_FILE_NAME),
+ YCPString ("*.ycp"), YCPString ("Select Macro File to Play"));
+
+ if (ret->isString()) {
+ busyCursor();
+ YCPString filename = ret->asString();
+
+ playMacro (filename->value_cstr());
+ sendEvent (new YEvent()); // flush
+ }
+}
+
+void YGUI::askSaveLogs()
+{
+ YCPValue file = askForSaveFileName (YCPString ("/tmp/y2logs.tgz"),
+ YCPString ("*.tgz *.tar.gz"), YCPString ("Save y2logs to..."));
+
+ if (file->isString()) {
+ std::string command = "/sbin/save_y2logs";
+ command += " '" + file->asString()->value() + "'";
+ y2milestone ("Saving y2logs: %s", command.c_str());
+ int ret = system (command.c_str());
+ if (ret == 0)
+ y2milestone ("y2logs saved to %s", file->asString()->value_cstr());
+ else {
+ char *error = g_strdup_printf (
+ "Error: couldn't save y2logs: \"%s\" (exit value: %d)",
+ command.c_str(), ret);
+ y2error (error);
+ errorMsg (error);
+ g_free (error);
+ }
+ }
+}
+
+// debug dialogs
+
+static void destroy_dialog (GtkDialog *dialog, gint arg)
+{ IMPL; gtk_widget_destroy (GTK_WIDGET (dialog)); }
+
+void dumpYastTree (YWidget *widget)
+{
+ IMPL
+ struct inner {
+ static void dumpYastTree (YWidget *widget, GtkTreeStore *store,
+ GtkTreeIter *parent_node)
+ {
+ YGWidget *ygwidget;
+ if (!widget || !(ygwidget = YGWidget::get (widget)))
+ return;
+
+ GtkTreeIter iter;
+ gtk_tree_store_append (store, &iter, parent_node);
+
+ YContainerWidget *container = dynamic_cast <YContainerWidget *> (widget);
+ gchar *stretch = g_strdup_printf ("%d x %d",
+ ygwidget->isStretchable (YD_HORIZ), ygwidget->isStretchable (YD_VERT));
+ gchar *weight = g_strdup_printf ("%ld x %ld",
+ widget->weight (YD_HORIZ), widget->weight (YD_VERT));
+ gtk_tree_store_set (store, &iter, 0, widget->widgetClass(),
+ 1, ygwidget->getDebugLabel().c_str(), 2, stretch, 3, weight, -1);
+ g_free (stretch);
+ g_free (weight);
+
+ if (container)
+ for (int i = 0; i < container->numChildren(); i++)
+ dumpYastTree (container->child (i), store, &iter);
+ }
+ };
+
+ GtkTreeStore *store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_STRING);
+ inner::dumpYastTree (widget, store, NULL);
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons ("YWidgets Tree", NULL,
+ GtkDialogFlags (GTK_DIALOG_NO_SEPARATOR), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), -1, 400);
+
+ GtkWidget *view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view),
+ gtk_tree_view_column_new_with_attributes ("Type",
+ gtk_cell_renderer_text_new(), "text", 0, NULL));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view),
+ gtk_tree_view_column_new_with_attributes ("Label",
+ gtk_cell_renderer_text_new(), "text", 1, NULL));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view),
+ gtk_tree_view_column_new_with_attributes ("Stretch",
+ gtk_cell_renderer_text_new(), "text", 2, NULL));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (view),
+ gtk_tree_view_column_new_with_attributes ("Weight",
+ gtk_cell_renderer_text_new(), "text", 3, NULL));
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
+ gtk_tree_view_set_enable_tree_lines (GTK_TREE_VIEW (view), TRUE);
+
+ GtkWidget *scroll_win = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll_win),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_win),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ gtk_container_add (GTK_CONTAINER (scroll_win), view);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scroll_win);
+ gtk_widget_show_all (dialog);
+
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (destroy_dialog), 0);
+}
+
+#include <YRichText.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 <YRichText *> (widget);
+ if (rtext) {
+ std::string text = rtext->getText()->value();
+ char *xml = ygutils_convert_to_xhmlt_and_subst (text.c_str(), NULL);
+
+ GtkWidget *view = gtk_text_view_new();
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
+ gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ gtk_text_buffer_set_text (buffer, xml, -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);
+
+ g_free (xml);
+ }
+
+ YContainerWidget *container = dynamic_cast <YContainerWidget *> (widget);
+ if (container)
+ for (int i = 0; i < container->numChildren(); i++)
+ dumpYastHtml (container->child (i), box);
+ }
+ };
+
+ IMPL
+ 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 (destroy_dialog), 0);
+}
+
Added: trunk/gtk/src/YGUI.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUI.h?rev=42515&view=au…
==============================================================================
--- trunk/gtk/src/YGUI.h (added)
+++ trunk/gtk/src/YGUI.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,313 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGUI_H
+#define YGUI_H
+
+#include <gtk/gtk.h>
+#include <YSimpleEventHandler.h>
+#include <YUI.h>
+
+using std::string;
+using std::vector;
+
+/* Comment the following line to disable debug messages */
+// #define IMPL_DEBUG
+#define LOC fprintf (stderr, "%s (%s)\n", G_STRLOC, G_STRFUNC)
+#ifdef IMPL_DEBUG
+ #define IMPL { LOC; }
+#else
+ #define IMPL { }
+#endif
+#define IMPL_NULL { IMPL; return NULL; }
+#define IMPL_VOID { IMPL; return YCPVoid(); }
+#define IMPL_RET(a) { IMPL; return (a); }
+
+#define ICON_DIR THEMEDIR "/icons/22x22/apps/"
+
+/* Compatibility */
+#if YAST2_VERSION > 2014004
+# define YAST2_YGUI_CHECKBOX_FRAME 1
+#elif YAST2_VERSION >= 2014000
+# define YAST2_YGUI_CHECKBOX_FRAME 0
+#elif YAST2_VERSION > 2013032
+# define YAST2_YGUI_CHECKBOX_FRAME 1
+#else
+# define YAST2_YGUI_CHECKBOX_FRAME 0
+#endif
+
+class YGDialog;
+
+class YGUI: public YUI
+{
+public:
+ YGUI (int argc, char **argv,
+ bool with_threads, const char *macro_file);
+ virtual ~YGUI();
+
+ static YGUI *ui() { return (YGUI *)YUI::ui(); }
+
+ // non abstract loop bits:
+ virtual void blockEvents (bool block = true) IMPL
+ virtual bool eventsBlocked() const IMPL_RET (false)
+ virtual void internalError (const char *msg);
+ virtual void idleLoop (int fd_ycp);
+ virtual YEvent * waitInput (unsigned long timeout_ms, bool block);
+ virtual YEvent * userInput (unsigned long timeout_millisec);
+ virtual YEvent * pollInput();
+
+ virtual void showDialog (YDialog *dialog);
+ virtual void closeDialog (YDialog *dialog);
+ // Non abstract virtuals:
+ virtual YCPValue setLanguage (const YCPTerm & term) IMPL_VOID
+
+ // event pieces:
+ private:
+ YSimpleEventHandler m_event_handler;
+ public:
+ void sendEvent (YEvent *event);
+ YEvent *pendingEvent() const { return m_event_handler.pendingEvent(); }
+ bool eventPendingFor (YWidget *widget) const { return m_event_handler.eventPendingFor (widget); }
+
+ // container widgets
+ virtual YDialog *createDialog (YWidgetOpt &opt);
+ virtual YContainerWidget *createSplit (YWidget *parent, YWidgetOpt &opt, YUIDimension dimension);
+ virtual YContainerWidget *createReplacePoint (YWidget *parent, YWidgetOpt &opt);
+ virtual YContainerWidget *createAlignment (YWidget *parent, YWidgetOpt &opt,
+ YAlignmentType halign,
+ YAlignmentType valign);
+ virtual YContainerWidget *createSquash (YWidget *parent, YWidgetOpt &opt,
+ bool hsquash, bool vsquash);
+ virtual YContainerWidget *createRadioButtonGroup (YWidget *parent, YWidgetOpt &opt);
+ virtual YContainerWidget *createFrame (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label);
+#if YAST2_YGUI_CHECKBOX_FRAME
+ virtual YContainerWidget *createCheckBoxFrame( YWidget *parent, YWidgetOpt & opt, const YCPString & label, bool checked );
+#endif
+
+ // leaf widgets
+ virtual YWidget *createEmpty (YWidget *parent, YWidgetOpt &opt);
+ virtual YWidget *createSpacing (YWidget *parent, YWidgetOpt &opt, float size,
+ bool horizontal, bool vertical);
+ virtual YWidget *createLabel (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &text);
+ virtual YWidget *createRichText (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &text);
+ virtual YWidget *createLogView (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, int visibleLines,
+ int maxLines);
+ virtual YWidget *createPushButton (YWidget *parent, YWidgetOpt &opt,
+ const YCPString & label);
+ virtual YWidget *createMenuButton (YWidget *parent, YWidgetOpt &opt,
+ const YCPString & label);
+ virtual YWidget *createRadioButton (YWidget *parent, YWidgetOpt &opt,
+ YRadioButtonGroup *rbg,
+ const YCPString &label, bool checked);
+ virtual YWidget *createCheckBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, bool checked);
+ virtual YWidget *createTextEntry (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, const YCPString &text);
+ virtual YWidget *createMultiLineEdit (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ const YCPString &text);
+ virtual YWidget *createSelectionBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label);
+ virtual YWidget *createMultiSelectionBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label);
+ virtual YWidget *createComboBox (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label);
+ virtual YWidget *createTree (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label);
+ virtual YWidget *createTable (YWidget *parent, YWidgetOpt &opt,
+ std::vector<std::string> header);
+ virtual YWidget *createProgressBar (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ const YCPInteger &maxprogress,
+ const YCPInteger &progress);
+ virtual YWidget *createImage (YWidget *parent, YWidgetOpt &opt,
+ YCPByteblock imagedata, YCPString defaulttext);
+ virtual YWidget *createImage (YWidget *parent, YWidgetOpt &opt,
+ YCPString file_name, YCPString defaulttext);
+ virtual YWidget *createIntField (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, int minValue,
+ int maxValue, int initialValue);
+
+ // Package selector
+ virtual YWidget *createPackageSelector (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &floppyDevice);
+ virtual YWidget *createPkgSpecial (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &subwidget);
+ virtual YCPValue runPkgSelection (YWidget *packageSelector);
+
+/*
+ // FIXME: do we need to implement these new bits ?
+
+ // New package selector bits ...
+ bool hasPatternSelector();
+ YWidget * createPatternSelector ( YWidget * parent,
+ YWidgetOpt & opt );
+
+ bool hasSimplePatchSelector();
+ YWidget * createSimplePatchSelector( YWidget * parent,
+ YWidgetOpt & opt );
+*/
+
+ // Optional widgets
+ virtual YWidget *createDummySpecialWidget (YWidget *parent, YWidgetOpt &opt)
+ IMPL_NULL;
+ virtual bool hasDummySpecialWidget() { return false; }
+
+ virtual YWidget *createDownloadProgress (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ const YCPString &filename,
+ int expectedSize);
+ virtual bool hasDownloadProgress() { return true; }
+
+ virtual YWidget *createBarGraph (YWidget *parent, YWidgetOpt &opt);
+ virtual bool hasBarGraph() { return true; }
+
+ virtual YWidget *createColoredLabel (YWidget *parent, YWidgetOpt &opt,
+ YCPString label, YColor foreground,
+ YColor background, int margin);
+ virtual bool hasColoredLabel() { return true; }
+
+ virtual YWidget *createDate (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, const YCPString &date);
+ virtual bool hasDate() { return true; }
+
+ virtual YWidget *createTime (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, const YCPString &time);
+ virtual bool hasTime() { return true; }
+
+ virtual YWidget *createDumbTab (YWidget *parent, YWidgetOpt &opt);
+ virtual bool hasDumbTab() { return true; }
+
+ virtual YWidget *createMultiProgressMeter (YWidget *parent, YWidgetOpt &opt,
+ bool horizontal, const YCPList & maxValues);
+ virtual bool hasMultiProgressMeter() { return true; }
+
+ virtual YWidget *createSlider (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, int min,
+ int max, int initial);
+ virtual bool hasSlider() { return true; }
+
+ virtual YWidget *createPartitionSplitter (YWidget *parent,
+ YWidgetOpt &opt,
+ int usedSize,
+ int totalFreeSize,
+ int newPartSize,
+ int minNewPartSize,
+ int minFreeSize,
+ const YCPString &usedLabel,
+ const YCPString &freeLabel,
+ const YCPString &newPartLabel,
+ const YCPString &freeFieldLabel,
+ const YCPString &newPartFieldLabel);
+ virtual bool hasPartitionSplitter() { return true; }
+
+ virtual YWidget *createPatternSelector (YWidget *parent, YWidgetOpt &opt) IMPL_NULL;
+ virtual bool hasPatternSelector() { return false; }
+
+ virtual YWidget *createWizard (YWidget *parent,
+ YWidgetOpt &opt,
+ const YCPValue &backButtonId,
+ const YCPString &backButtonLabel,
+ const YCPValue &abortButtonId,
+ const YCPString &abortButtonLabel,
+ const YCPValue &nextButtonId,
+ const YCPString &nextButtonLabel);
+ virtual bool hasWizard() { return true; }
+
+
+ virtual int getDisplayWidth();
+ virtual int getDisplayHeight();
+ // let's fool YWidgets here because it tries to be smart if our default
+ // dialog size is too small
+ virtual int getDefaultWidth() { return 10000; }
+ virtual int getDefaultHeight() { return 10000; }
+ // Dunno where this is used in practice, but these can be got by a YCP
+ // apps, so better implement them.
+ virtual int getDisplayDepth() { return 24; }
+ virtual long getDisplayColors() { return 256*256*256; }
+
+ virtual long deviceUnits (YUIDimension dim, float size);
+ virtual float layoutUnits (YUIDimension dim, long device_units);
+
+ virtual bool textMode();
+ virtual bool hasImageSupport();
+ virtual bool hasLocalImageSupport();
+ virtual bool hasAnimationSupport();
+ virtual bool hasIconSupport();
+ virtual bool hasFullUtf8Support();
+ virtual bool richTextSupportsTable();
+ virtual bool leftHandedMouse();
+
+ virtual YCPString glyph (const YCPSymbol &glyph);
+ virtual void redrawScreen();
+
+ // convience function to be used rather than currentDialog()
+ // NULL if there is no dialog at the moment.
+ GtkWindow *currentWindow();
+ YGDialog *currentYGDialog();
+
+ virtual void busyCursor();
+ virtual void normalCursor();
+
+ guint busy_timeout; // for busy cursor
+ static gboolean busy_timeout_cb (gpointer data);
+
+ virtual void beep();
+ virtual void makeScreenShot (string filename);
+
+ /* File/directory dialogs. */
+ virtual YCPValue askForExistingDirectory (const YCPString &startDir,
+ const YCPString &headline);
+ virtual YCPValue askForExistingFile (const YCPString &startWith,
+ const YCPString &filter,
+ const YCPString &headline);
+ virtual YCPValue askForSaveFileName (const YCPString &startWith,
+ const YCPString &filter,
+ const YCPString &headline);
+
+ // Starts macro recording and asks for a filename to save it to
+ // If there is already one in progress, it just resumes/pauses as appropriate
+ // activated by Ctrl-Shift-Alt-M
+ void toggleRecordMacro();
+
+ // Plays a macro, opening a dialog first to ask for the filename
+ // activated by Ctrl-Shift-Alt-P
+ void askPlayMacro();
+
+ // On Shift-F8, run save_logs
+ void askSaveLogs();
+
+ private:
+ // window-related arguments
+ bool m_have_wm, m_no_border, m_fullscreen;
+ GtkRequisition m_default_size;
+
+ // for delayed gtk+ init in the right thread
+ bool m_done_init;
+ int m_argc;
+ char **m_argv;
+ void checkInit();
+
+ // for screenshots:
+ map <string, int> screenShotNb;
+ string screenShotNameTemplate;
+
+ public:
+ // Helpers for internal use [ visibility hidden ]
+ int getDefaultSize (YUIDimension dim);
+ bool setFullscreen() const { return m_fullscreen || !m_have_wm; }
+ bool hasWM() const { return m_have_wm; }
+ bool unsetBorder() const { return m_no_border; }
+};
+
+// debug helpers.
+void dumpYastTree (YWidget *widget);
+void dumpYastHtml (YWidget *widget);
+
+#endif // YGUI_H
+
Added: trunk/gtk/src/YGUtils.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUtils.cc?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGUtils.cc (added)
+++ trunk/gtk/src/YGUtils.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,779 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+
+string YGUtils::mapKBAccel (const char *src)
+{
+ // we won't use use replace since we also want to escape _ to __
+ string str;
+ int length = strlen (src);
+ str.reserve (length);
+
+ for (int i = 0; i < length; i++) {
+ if (src[i] == '_')
+ str += "__";
+ else if (src[i] == '&')
+ str += '_';
+ else
+ str += src[i];
+ }
+ return str;
+}
+
+string YGUtils::filterText (const char* text, int length, const char *valid_chars)
+{
+ if (length == -1)
+ length = strlen (text);
+ if (valid_chars[0] == '\0')
+ return string(text);
+
+ string str;
+ str.reserve (length);
+ for (int i = 0; text[i] && i < length; i++) {
+ for (int j = 0; valid_chars[j]; j++)
+ if(text[i] == valid_chars[j]) {
+ str += text[i];
+ break;
+ }
+ }
+ return str;
+}
+
+void YGUtils::filterText (GtkEditable *editable, int pos, int length,
+ const char *valid_chars)
+{
+ gchar *text = gtk_editable_get_chars (editable, pos, pos + length);
+ string str = filterText (text, length, valid_chars);
+ if (length == -1)
+ length = strlen (text);
+
+ if (str != text) { // invalid text
+ // delete current text
+ gtk_editable_delete_text (editable, pos, length);
+ // insert correct text
+ gtk_editable_insert_text (editable, str.c_str(), str.length(), &pos);
+
+ g_signal_stop_emission_by_name (editable, "insert_text");
+ gdk_beep(); // BEEP!
+ }
+
+ g_free (text);
+}
+
+void YGUtils::replace (string &str, const char *mouth, int mouth_len, const char *food)
+{
+ unsigned int i = 0;
+ while ((i = str.find (mouth, i)) != string::npos)
+ {
+ str.erase (i, mouth_len);
+ str.insert (i, food);
+ }
+}
+
+void YGUtils::scrollTextViewDown(GtkTextView *text_view)
+{
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (text_view);
+ GtkTextIter end_iter;
+ gtk_text_buffer_get_end_iter (buffer, &end_iter);
+ GtkTextMark *end_mark;
+ end_mark = gtk_text_buffer_create_mark
+ (buffer, NULL, &end_iter, FALSE);
+ gtk_text_view_scroll_to_mark (text_view,
+ end_mark, 0.0, FALSE, 0, 0);
+ gtk_text_buffer_delete_mark (buffer, end_mark);
+}
+
+/* Strings can ask for not being escape with the comment
+ <!-- DT:Rich --> */
+static bool dont_escape (const string &str)
+{
+ const char *comment = "<!-- DT:Rich -->";
+ if (str.length() < sizeof (comment))
+ return false;
+ for (unsigned int i = 0; i < sizeof (comment); i++)
+ if (str[i] != comment[i])
+ return false;
+ return true;
+}
+
+string YGUtils::escape_markup (const string &str, bool break_lines)
+{
+ if (dont_escape (str))
+ return string (str);
+
+ string ret;
+ ret.reserve (str.length());
+ for (unsigned int i = 0; i < str.length(); i++) {
+ char ch = str[i];
+ switch (ch) {
+ case '<':
+ ret += "<";
+ break;
+ case '>':
+ ret += ">";
+ break;
+ case '&':
+ ret += "&";
+ break;
+ case '\n':
+ ret += "<br/>";
+ break;
+ default:
+ ret += ch;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+#if 0
+string YGUtils::escape_break_lines (const string &str, bool paragraph_mode)
+{
+ if (dont_escape (str))
+ return str;
+ string res;
+ res.reserve (str.length() + 6);
+ if (paragraph_mode)
+ res = "<p>";
+ /* on paragraph mode, dont break when there is no text on the paragraph.
+ otherwise, just dont break at the start of the text. */
+ bool dont_break = true;
+ for (unsigned int i = 0; i != str.length(); i++) {
+ char ch = str[i];
+ if (paragraph_mode && ch == '\n' && str[i-1] == '\n') {
+ if (!dont_break)
+ res += "</p><p>";
+ dont_break = true;
+ }
+ else if (!paragraph_mode && ch == '\n') {
+ if (!dont_break)
+ res += "<br>";
+ }
+ else {
+ res += ch;
+ dont_break = false;
+ }
+ }
+ if (paragraph_mode)
+ res += "</p>";
+ return res;
+}
+#endif
+
+#define PROD_ENTITY "&product;"
+
+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;
+
+ for (unsigned int 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;
+}
+
+
+// We have to:
+// + manually substitute the product entity.
+// + rewrite <br> and <hr> tags
+// + deal with <a attrib=noquotes>
+gchar *ygutils_convert_to_xhmlt_and_subst (const char *instr, const char *product)
+{
+ GString *outp = g_string_new ("");
+ GQueue *tag_queue = g_queue_new();
+ int i = 0;
+
+ skipSpace (instr, i);
+
+ // We must add an outer tag to make GMarkup happy
+ gboolean addOuterTag = TRUE;
+// gboolean addOuterTag = FALSE;
+// if ((addOuterTag = (instr[i] != '<')))
+ 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, '/');
+
+ // Add quoting for un-quoted attributes
+ for (int j = 0; j < (signed) tag->len; j++) {
+ if (tag->str[j] == '=') {
+ if (tag->str[j+1] != '"') {
+ g_string_insert_c (tag, j+1, '"');
+ for (j++; !g_ascii_isspace (tag->str[j]) && tag->str[j]; j++) ;
+ g_string_insert_c (tag, j, '"');
+ }
+ }
+ }
+
+ // 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);
+ }
+/*
+ else if (instr[i] == '&' &&
+ !g_ascii_strncasecmp (instr + i, PROD_ENTITY,
+ sizeof (PROD_ENTITY) - 1)) {
+ // 1 Magic entity
+ g_string_append (outp, product);
+ i += sizeof (PROD_ENTITY) - 2;
+ }
+*/
+ // non-break space entity
+ else if (instr[i] == '&' &&
+ !g_ascii_strncasecmp (instr + i, " ",
+ sizeof (" ") - 1)) {
+ // Replace this by a white-space
+ g_string_append (outp, " ");
+ i += sizeof (" ") - 2;
+ }
+
+#if 0
+ // removing new-lines chars sure isn't a xhtml conversion
+ // but it's still valid xhtml and GtkTextView appreciates it
+ else if (/*cut_breaklines &&*/ instr[i] == '\n') {
+ // In HTML a breakline should be treated as a white space when
+ // not in the start of a paragraph.
+ if (i > 0 && instr[i-1] != '>' && !g_ascii_isspace (instr[i-1]))
+ g_string_append_c (outp, ' ');
+ }
+#endif
+
+ else // Normal text
+ g_string_append_c (outp, instr[i]);
+ }
+
+ emit_unclosed_tags_for (outp, tag_queue, "", 0);
+ g_queue_free (tag_queue);
+
+ if (addOuterTag)
+ g_string_append (outp, "</body>");
+
+ gchar *ret = g_string_free (outp, FALSE);
+ return ret;
+}
+
+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, 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));
+
+ gtk_widget_modify_font (widget, font);
+ pango_font_description_free (font);
+}
+
+int ygutils_getCharsWidth (GtkWidget *widget, int chars_nb)
+{ return YGUtils::getCharsWidth (widget, chars_nb); }
+int ygutils_getCharsHeight (GtkWidget *widget, int chars_nb)
+{ return YGUtils::getCharsHeight (widget, chars_nb); }
+void ygutils_setWidgetFont (GtkWidget *widget, PangoWeight weight, double scale)
+{ YGUtils::setWidgetFont (widget, weight, scale); }
+
+int YGUtils::strcmp (const char *str1, const char *str2)
+{
+ // (if you think this is ugly, just wait for the Perl version! :P)
+ const char *i, *j;
+ for (i = str1, j = str2; *i && *j; i++, j++) {
+ // number comparasion
+ if (isdigit (*i) && isdigit (*j)) {
+ int n1, n2;
+ for (n1 = 0; isdigit (*i); i++)
+ n1 = (*i - '0') + (n1 * 10);
+ for (n2 = 0; isdigit (*j); j++)
+ n2 = (*j - '0') + (n2 * 10);
+
+ if (n1 != n2)
+ return n1 - n2;
+
+ // prepare for loop
+ i--; j--;
+ }
+
+ // regular character comparasion
+ else if (g_ascii_tolower (*i) != g_ascii_tolower(*j))
+ return g_ascii_tolower (*i) - g_ascii_tolower (*j);
+ }
+ if (*i)
+ return -1;
+ if (*j)
+ return 1;
+ return 0; // identicals
+}
+
+bool YGUtils::contains (const string &haystack, const string &needle)
+{
+ unsigned int i, j;
+ for (i = 0; i < haystack.length(); i++) {
+ for (j = 0; j < needle.length() && i+j < haystack.length(); j++)
+ if (g_ascii_tolower (haystack[i+j]) != g_ascii_tolower (needle[j]))
+ break;
+ if (j == needle.length())
+ return true;
+ }
+ return false;
+}
+
+std::list <string> YGUtils::splitString (const string &str, char separator)
+{
+ std::list <string> parts;
+ unsigned int i, j;
+ for (j = 0, i = 0; i < str.length(); i++)
+ if (str[i] == separator) {
+ parts.push_back (str.substr (j, i - j));
+ j = ++i;
+ }
+ parts.push_back (str.substr (j));
+ return parts;
+}
+
+void YGUtils::print_model (GtkTreeModel *model, int string_col)
+{
+ fprintf (stderr, "printing model...\n");
+ int depth = 0;
+ GtkTreeIter iter;
+
+ if (!gtk_tree_model_get_iter_first (model, &iter)) {
+ fprintf (stderr, "Couldn't even get a first iterator\n");
+ return;
+ }
+
+ while (true)
+ {
+ // print node
+ gchar *package_name = 0;
+ gtk_tree_model_get (model, &iter, string_col, &package_name, -1);
+ for (int i = 0; i < depth*4; i++)
+ fprintf (stderr, " ");
+ fprintf (stderr, "%s\n", package_name);
+ g_free (package_name);
+
+ if (gtk_tree_model_iter_has_child (model, &iter)) {
+ GtkTreeIter parent = iter;
+ gtk_tree_model_iter_children (model, &iter, &parent);
+ depth++;
+ }
+ else {
+ if (gtk_tree_model_iter_next (model, &iter))
+ ; // continue
+ else {
+ // let's see if there is a parent
+ GtkTreeIter child = iter;
+ if (gtk_tree_model_iter_parent (model, &iter, &child) &&
+ gtk_tree_model_iter_next (model, &iter))
+ depth--;
+ else
+ break;
+ }
+ }
+ }
+}
+
+void YGUtils::tree_view_radio_toggle_cb (GtkCellRendererToggle *renderer,
+ gchar *path_str, GtkTreeModel *model)
+{
+ // Toggle the box
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+ gint *column = (gint*) g_object_get_data (G_OBJECT (renderer), "column");
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ // Disable radio buttons from the same parent
+ GtkTreeIter parent_iter, child_iter;
+ if (gtk_tree_model_iter_parent (model, &parent_iter, &iter) &&
+ gtk_tree_model_iter_children (model, &child_iter, &parent_iter)) {
+ do gtk_tree_store_set (GTK_TREE_STORE (model), &child_iter, column, FALSE, -1);
+ while (gtk_tree_model_iter_next (model, &child_iter));
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter, column, TRUE, -1);
+ }
+}
+
+gint YGUtils::sort_compare_cb (GtkTreeModel *model, GtkTreeIter *a,
+ GtkTreeIter *b, gpointer data)
+{
+ IMPL
+ gint col = GPOINTER_TO_INT (data);
+ gchar *str1 = 0, *str2 = 0;
+ gtk_tree_model_get (model, a, col, &str1, -1);
+ gtk_tree_model_get (model, b, col, &str2, -1);
+ gint cmp = 0;
+ if (str1 && str2)
+ cmp = YGUtils::strcmp (str1, str2);
+
+ if (str1)
+ g_free (str1);
+ if (str2)
+ g_free (str2);
+ return cmp;
+}
+
+static void header_clicked_cb (GtkTreeViewColumn *column, GtkTreeSortable *sortable)
+{
+ IMPL
+ GtkTreeViewColumn *last_sorted =
+ (GtkTreeViewColumn *) g_object_get_data (G_OBJECT (sortable), "last-sorted");
+ int id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (column), "id"));
+
+ GtkSortType sort = GTK_SORT_ASCENDING;
+ if (last_sorted != column) {
+ if (last_sorted)
+ gtk_tree_view_column_set_sort_indicator (last_sorted, FALSE);
+ gtk_tree_view_column_set_sort_indicator (column, TRUE);
+ g_object_set_data (G_OBJECT (sortable), "last-sorted", column);
+ }
+ else {
+ sort = gtk_tree_view_column_get_sort_order (column);
+ sort = sort == GTK_SORT_ASCENDING ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
+ }
+
+ gtk_tree_view_column_set_sort_order (column, sort);
+ gtk_tree_sortable_set_sort_column_id (sortable, id, sort);
+}
+
+void YGUtils::tree_view_set_sortable (GtkTreeView *view, int default_sort_col)
+{
+ IMPL
+ g_assert (gtk_tree_view_get_headers_visible (view));
+
+ /* Set all string columns clickable. */
+ GtkTreeSortable *sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (view));
+ // we need a pointer, this function is used by different stuff, so to we'll
+ // use g_object_*_data() to do of garbage collector
+ g_object_set_data (G_OBJECT (sortable), "last-sorted", NULL);
+
+ GList *columns = gtk_tree_view_get_columns (view);
+ for (GList *i = g_list_first (columns); i; i = i->next) {
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data;
+ int col_nb = g_list_position (columns, i);
+
+ // check if it really is a string column
+ bool string_col = false;
+ GList *renderers = gtk_tree_view_column_get_cell_renderers (column);
+ for (GList *j = g_list_first (renderers); j; j = j->next)
+ if (GTK_IS_CELL_RENDERER_TEXT (j->data)) {
+ string_col = true;
+ break;
+ }
+ g_list_free (renderers);
+ if (!string_col)
+ continue;
+
+ // set sortable and clickable
+ gtk_tree_sortable_set_sort_func (sortable, col_nb, sort_compare_cb,
+ GINT_TO_POINTER (col_nb), NULL);
+ g_object_set_data (G_OBJECT (column), "id", GINT_TO_POINTER (col_nb));
+ gtk_tree_view_column_set_clickable (column, TRUE);
+ g_signal_connect (G_OBJECT (column), "clicked",
+ G_CALLBACK (header_clicked_cb), sortable);
+ if (col_nb == default_sort_col)
+ header_clicked_cb (column, sortable);
+ }
+ g_list_free (columns);
+}
+
+GValue YGUtils::floatToGValue (float num)
+{
+ GValue value = { 0 };
+ g_value_init (&value, G_TYPE_FLOAT);
+ g_value_set_float (&value, num);
+ return value;
+}
+
+#define SCROLLING_TIME 700
+#define SCROLLING_STEP 100
+struct ScrollData {
+ int orix, oriy, diffx, diffy, time;
+ GtkTreeView *view;
+};
+
+static gboolean scroll_timeout (gpointer _data) {
+ ScrollData *data = (ScrollData *) _data;
+ data->time += SCROLLING_STEP;
+
+ int x = data->orix + data->diffx;
+ int y = ((data->diffy * data->time) / SCROLLING_TIME) + data->oriy;
+
+ gtk_tree_view_scroll_to_point (data->view, x, y);
+ return data->time < SCROLLING_TIME;
+}
+
+void YGUtils::tree_view_smooth_scroll_to_point (GtkTreeView *view, gint x, gint y) {
+ GdkRectangle rect;
+ gtk_tree_view_get_visible_rect (view, &rect);
+ if (rect.x == x && rect.y == y)
+ return;
+
+ ScrollData *data = (ScrollData *) g_malloc (sizeof (ScrollData));
+ data->orix = rect.x;
+ data->oriy = rect.y;
+ data->diffx = x - rect.x;
+ data->diffy = y - rect.y;
+ data->time = 0;
+ data->view = view;
+
+ static int id = 0;
+ if (id)
+ g_source_remove (id);
+ id = g_timeout_add_full (G_PRIORITY_DEFAULT, SCROLLING_STEP, scroll_timeout, data, g_free);
+}
+
+#define ENGLISH_STOCK_ITEMS
+
+#ifdef ENGLISH_STOCK_ITEMS
+struct StockMap { const char *ycp_label, *gtk_stock; };
+static const StockMap stockMap[] = {
+ // keep them sorted!
+ {"Abort", GTK_STOCK_CANCEL },
+ {"Accept", GTK_STOCK_APPLY },
+ {"Add", GTK_STOCK_ADD },
+ {"Back", GTK_STOCK_GO_BACK },
+ {"Cancel", GTK_STOCK_CANCEL },
+ {"Configure", GTK_STOCK_PREFERENCES },
+ {"Continue", GTK_STOCK_OK },
+ {"Delete", GTK_STOCK_DELETE },
+ {"Down", GTK_STOCK_GO_DOWN },
+ {"Edit", GTK_STOCK_EDIT },
+ {"Launch", GTK_STOCK_EXECUTE },
+ {"Next", GTK_STOCK_GO_FORWARD },
+ {"No", GTK_STOCK_NO },
+ {"OK", GTK_STOCK_OK },
+ {"Quit", GTK_STOCK_QUIT },
+ {"Search", GTK_STOCK_FIND },
+ {"Up", GTK_STOCK_GO_UP },
+ {"Yes", GTK_STOCK_YES },
+};
+#define STOCKMAP_SIZE (sizeof (stockMap)/sizeof(StockMap))
+static int strcmp_cb (const void *a, const void *b)
+{ return strcmp ((char *) a, ((StockMap *) b)->ycp_label); }
+
+void YGUtils::setStockIcon (GtkWidget *button, std::string ycp_str)
+{
+ // is English the current locale?
+ static bool firstTime = true, isEnglish;
+ if (firstTime) {
+ char *lang = getenv ("LANG");
+ isEnglish = !lang || (!*lang) || !strcmp (lang, "C") ||
+ (lang[0] == 'e' && lang[1] == 'n') ||
+ !strcmp (lang, "POSIX");
+ firstTime = false;
+ }
+ if (!isEnglish)
+ return;
+
+ unsigned int i = 0;
+ while ((i = ycp_str.find ('_', i)) != string::npos)
+ ycp_str.erase (i, 1);
+
+ bool failed = true;
+ void *ptr;
+ ptr = bsearch (ycp_str.c_str(), stockMap, STOCKMAP_SIZE,
+ sizeof(stockMap[0]), strcmp_cb);
+ if (ptr) {
+ const char *stock = ((StockMap *) ptr)->gtk_stock;
+ GdkPixbuf *pixbuf;
+ pixbuf = gtk_widget_render_icon (button, stock,
+ GTK_ICON_SIZE_BUTTON, NULL);
+ if (pixbuf) {
+ GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ g_object_unref (G_OBJECT (pixbuf));
+ failed = false;
+ }
+ }
+ if (failed)
+ gtk_button_set_image (GTK_BUTTON (button), NULL);
+}
+
+void ygutils_setStockIcon (GtkWidget *button, const char *ycp_str)
+{ YGUtils::setStockIcon (button, ycp_str); }
+
+#else
+void ygutils_setStockIcon (GtkWidget *button, const char *ycp_str) {}
+#endif
+
Added: trunk/gtk/src/YGUtils.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGUtils.h?rev=42515&view…
==============================================================================
--- trunk/gtk/src/YGUtils.h (added)
+++ trunk/gtk/src/YGUtils.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,96 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGUTILS_H
+#define YGUTILS_H
+
+#include <string>
+#include <list>
+#include <gtk/gtktextview.h>
+#include <gtk/gtkeditable.h>
+
+/* 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). */
+ string mapKBAccel (const char *src);
+
+ /* Filters characters that are not on the valids_chars array from the text string
+ Length is used to tell the length of text, in case it isn't NUL
+ terminated (you may pass -1, if it is).
+ Use the compare string member if you want to see if there was any change. */
+ string filterText (const char* text, int length, const char* valid_chars);
+
+ /* Convenience call for widgets that implement GtkEditable interface.
+ This function inserts and deletes text, if needed, so you may want
+ to block those signals, if you have them set. */
+ void filterText (GtkEditable *editable, int pos, int length,
+ const char *valid_chars);
+
+ /* Replaces every 'mouth' by 'food' in 'str'. */
+ void replace (string &str, const char *mouth, int mouth_len, const char *food);
+
+ /* Escapes markup text (eg. changes '<' by '\<').
+ If break_line is true, the break line character will be transformed in <br/> */
+ string escape_markup (const string &str, bool break_line = false);
+
+ /* Adds functionality to GtkTextView to scroll to bottom. */
+ void scrollTextViewDown(GtkTextView *text_view);
+
+ /* 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, PangoWeight weight, double scale);
+
+ /* A more sane strcmp() from the user point of view that honors numbers.
+ i.e. "20" < "100" */
+ int strcmp (const char *str1, const char *str2);
+
+ /* Checks if a std::string contains some other string (case insensitive). */
+ bool contains (const string &haystack, const string &needle);
+
+ /* Splits a string into parts as separated by the separator characters.
+ eg: splitString ("Office/Writer", '/') => { "Office", "Writer" } */
+ std::list <string> splitString (const string &str, char separator);
+
+ /* Prints a GtkTreeModel for debugging purposes. */
+ void print_model (GtkTreeModel *model, int string_col);
+
+ /* To be used as a callback to sort tree views. */
+ gint sort_compare_cb (GtkTreeModel *model, GtkTreeIter *a,
+ GtkTreeIter *b, gpointer data);
+
+ /* To be used as a callback for a GtkTreeView with toggle cells. */
+ void tree_view_radio_toggle_cb (GtkCellRendererToggle *renderer,
+ gchar *path_str, GtkTreeModel *model);
+
+ /* Goes through all GtkTreeView columns and checks for TextCellRenderers,
+ setting those columns as sortable. */
+ void tree_view_set_sortable (GtkTreeView *view, int default_sort_col);
+
+ /* Like gtk_tree_view_scroll_to_point(), but does smooth scroll. */
+ void tree_view_smooth_scroll_to_point (GtkTreeView *view, gint x, gint y);
+
+ /* Converts stuff to GValues */
+ GValue floatToGValue (float num);
+
+ void setStockIcon (GtkWidget *button, std::string ycp_str);
+};
+
+extern "C" {
+ int ygutils_getCharsWidth (GtkWidget *widget, int chars_nb);
+ int ygutils_getCharsHeight (GtkWidget *widget, int chars_nb);
+ void ygutils_setWidgetFont (GtkWidget *widget, PangoWeight weight, double scale);
+
+ /* Convert html to xhtml (or at least try) */
+ gchar *ygutils_convert_to_xhmlt_and_subst (const char *instr, const char *product);
+ void ygutils_setStockIcon (GtkWidget *button, const char *ycp_str);
+};
+
+#endif // YGUTILS_H
+
Added: trunk/gtk/src/YGWidget.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGWidget.cc?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/YGWidget.cc (added)
+++ trunk/gtk/src/YGWidget.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,312 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <stdarg.h>
+#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
+
+/* YGWidget follows */
+
+YGWidget::YGWidget(YWidget *y_widget, YGWidget *parent, bool show,
+ GtkType type, const char *property_name, ...)
+ : m_y_widget (y_widget)
+{
+ va_list args;
+ va_start (args, property_name);
+ construct (y_widget, parent, show, type, property_name, args);
+ va_end (args);
+}
+
+void YGWidget::construct (YWidget *y_widget, YGWidget *parent, bool _show,
+ 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)
+ 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);
+ }
+
+ y_widget->setWidgetRep ((void *) this);
+ if (parent)
+ y_widget->setParent (parent->m_y_widget);
+
+#ifdef IMPL_DEBUG
+ fprintf (stderr, "Set YWidget %p rep to %p\n", y_widget, this);
+#endif
+
+ // Split by two so that with another widget it will have full border...
+ setBorder (DEFAULT_BORDER / 2);
+
+ if (_show)
+ show();
+}
+
+YGWidget::~YGWidget()
+{
+ IMPL
+ gtk_widget_destroy (m_adj_size);
+ g_object_unref (G_OBJECT (m_adj_size));
+}
+
+void YGWidget::show()
+{
+ gtk_widget_show (m_widget);
+}
+
+YGWidget *YGWidget::get (YWidget *y_widget)
+{
+ if (!y_widget || !y_widget->widgetRep()) {
+#ifdef IMPL_DEBUG
+ if (y_widget)
+ fprintf (stderr, "Widget '%s' (label: '%s') not supported\n",
+ y_widget->widgetClass(), y_widget->debugLabel().c_str());
+ else
+ fprintf (stderr, "YGWidget::get() on null\n");
+#endif
+ return NULL;
+ }
+ return (YGWidget *) (y_widget->widgetRep());
+}
+
+bool YGWidget::doSetKeyboardFocus()
+{
+ IMPL
+ gtk_widget_grab_focus (GTK_WIDGET (getWidget()));
+ return gtk_widget_is_focus (GTK_WIDGET (getWidget()));
+}
+
+void YGWidget::doSetEnabling (bool enabled)
+{
+ gtk_widget_set_sensitive (getWidget(), enabled);
+}
+
+void YGWidget::emitEvent(YEvent::EventReason reason, bool if_notify,
+ bool if_not_pending, bool immediate)
+{
+ struct inner
+ {
+ static gboolean dispatchEvent (gpointer data)
+ {
+ YWidgetEvent *event = (YWidgetEvent *) data;
+ if (!YGUI::ui()->eventPendingFor (event->widget()))
+ YGUI::ui()->sendEvent (event);
+ return FALSE;
+ }
+ };
+
+ if (!if_notify || m_y_widget->getNotify())
+ {
+ if (!immediate)
+ g_timeout_add (250, inner::dispatchEvent, new YWidgetEvent (m_y_widget, reason));
+ else if (!if_not_pending || !YGUI::ui()->eventPendingFor (m_y_widget))
+ {
+ if (immediate)
+ YGUI::ui()->sendEvent (new YWidgetEvent (m_y_widget, reason));
+ }
+ }
+}
+
+void YGWidget::setBorder (unsigned int border)
+{
+ IMPL
+ gtk_container_set_border_width (GTK_CONTAINER (m_adj_size), border);
+}
+
+void YGWidget::setMinSize (unsigned int width, unsigned int height)
+{
+ IMPL
+ ygtk_adj_size_set_min (YGTK_ADJ_SIZE (m_adj_size), width, height);
+}
+
+void YGWidget::setMinSizeInChars (unsigned int width, unsigned int height)
+{
+ IMPL
+ if (width)
+ width = YGUtils::getCharsWidth (getWidget(), width);
+ if (height)
+ height = YGUtils::getCharsHeight (getWidget(), height);
+ setMinSize (width, height);
+}
+
+void YGWidget::sync_stretchable (YWidget *child)
+{
+ IMPL
+ YWidget *parent = m_y_widget->yParent();
+ if (parent)
+ // tell parent to sync too!
+ YGWidget::get (parent)->sync_stretchable (m_y_widget);
+}
+
+// JEEZ. WHEN the hell will yast-ui code fix their damn code.
+#if 1
+/* Checks everywhere in a container to see if there are children (so
+ he is completely initialized) so that we may ask him for stretchable()
+ because some YContainerWidgets crash when they don't have children. */
+#include "YSplit.h"
+static bool safe_stretchable (YWidget *widget)
+{
+ YContainerWidget *container = dynamic_cast <YContainerWidget *> (widget);
+ if (container) {
+ YSplit *split = dynamic_cast <YSplit *> (widget);
+ // in the case of YSplit its safe to ask for stretchability with no kids
+ if (split) {
+ if (!split->hasChildren())
+ return true;
+ }
+ else
+ if (!container->hasChildren())
+ return false;
+
+ for (int i = 0; i < container->numChildren(); i++)
+ if (!safe_stretchable (container->child (i)))
+ return false;
+ }
+ return true;
+}
+#else
+static bool safe_stretchable (YWidget *widget)
+{
+ return true;
+}
+#endif
+
+bool YGWidget::isStretchable (YUIDimension dim)
+{
+ if (safe_stretchable (m_y_widget))
+ return m_y_widget->stretchable (dim);
+ return false;
+}
+
+/* YGLabeledWidget follows */
+
+YGLabeledWidget::YGLabeledWidget (YWidget *y_widget, YGWidget *parent,
+ YCPString label_text, YUIDimension label_ori,
+ bool show, GType type,
+ const char *property_name, ...)
+ : YGWidget (y_widget, parent, show,
+ label_ori == YD_VERT ? GTK_TYPE_VBOX : GTK_TYPE_HBOX,
+ "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);
+ if(show) {
+ 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 YCPString &label)
+{
+ string str = YGUtils::mapKBAccel (label->value_cstr());
+ if (str.empty()) {
+ gtk_widget_hide (m_label);
+ }
+ else {
+ gtk_widget_show (m_label);
+
+ // add a ':' at the end
+ int last = str.length()-1;
+ if (str [last] != ':' && str [last] != '.' && str [last] != ' ')
+ str += ':';
+
+ // set it as upper case
+ unsigned int first = (str [0] == '_') ? 1 : 0;
+ if (str [first] >= 'a' && str [first] <= 'z')
+ str [first] += 'A' - 'a';
+
+ gtk_label_set_text (GTK_LABEL (m_label), str.c_str());
+ gtk_label_set_use_underline (GTK_LABEL (m_label), TRUE);
+ }
+}
+
+/* YGScrolledWidget follows */
+#define MAX_SCROLL_WIDTH 120
+
+YGScrolledWidget::YGScrolledWidget (YWidget *y_widget, YGWidget *parent,
+ bool show, GType type,
+ const char *property_name, ...)
+ : YGLabeledWidget (y_widget, parent, YCPString (""), YD_VERT, show,
+ YGTK_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 *y_widget, YGWidget *parent,
+ YCPString label_text, YUIDimension label_ori,
+ bool show, GType type,
+ const char *property_name, ...)
+ : YGLabeledWidget (y_widget, parent, label_text, label_ori, show,
+ YGTK_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);
+ ygtk_scrolled_window_set_auto_policy (YGTK_SCROLLED_WINDOW (YGLabeledWidget::getWidget()),
+ hpolicy == GTK_POLICY_AUTOMATIC ? MAX_SCROLL_WIDTH : 0, 0);
+}
+
Added: trunk/gtk/src/YGWidget.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGWidget.h?rev=42515&vie…
==============================================================================
--- trunk/gtk/src/YGWidget.h (added)
+++ trunk/gtk/src/YGWidget.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,151 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#ifndef YGWIDGET_H
+#define YGWIDGET_H
+
+#include <gtk/gtk.h>
+#include <stdarg.h>
+#include "YGUI.h"
+#include "YEvent.h"
+
+class YGWidget
+{
+public:
+ YGWidget(YWidget *y_widget, YGWidget *parent, bool show,
+ GType type, const char *property_name, ...);
+ virtual ~YGWidget();
+
+ virtual GtkWidget *getWidget() { return m_widget; }
+ const char *getWidgetName() const
+ { return const_cast <YWidget *> (m_y_widget)->widgetClass(); }
+ // YWidget::debugLabel() sucks for most widgets -- let's allow it to be overload
+ virtual string getDebugLabel() const
+ { // container debug labels are worse than useless
+ if (dynamic_cast <YContainerWidget *> (m_y_widget) == NULL)
+ return const_cast <YWidget *> (m_y_widget)->debugLabel(); return string(); }
+ void show();
+
+ // containers should use this call rather than getWidget()
+ GtkWidget *getLayout() { return m_adj_size; }
+
+ // Get the YGWidget associated with a YWidget
+ static YGWidget *get (YWidget *y_widget);
+
+ // for YWidget
+ virtual bool doSetKeyboardFocus();
+ virtual void doSetEnabling (bool enabled);
+
+ // Event handling
+ void emitEvent(YEvent::EventReason reason, bool if_notify = true,
+ bool if_not_pending = false, bool immediate = true);
+
+ // Aesthetics
+ void setBorder (unsigned int border); // in pixels
+ void setMinSize (unsigned int min_width, unsigned int min_height);
+ void setMinSizeInChars (unsigned int min_width, unsigned int min_height);
+
+ // whenever the stretchable property may change (eg. when adding a child
+ // for a container), call this function to make sure it is honored.
+ virtual void sync_stretchable (YWidget *child = 0);
+
+ // should be used instead of YWidget::stretchable() as this has some safeguards
+ // against crashes that some YContainerWidgets lead to
+ bool isStretchable (YUIDimension dim);
+
+protected:
+ GtkWidget *m_widget; // associated GtkWidget -- use getWidget()
+ YWidget *m_y_widget; // associated YWidget
+ GtkWidget *m_adj_size; // installed on m_widget, allows better size constrains
+
+ void construct (YWidget *y_widget, YGWidget *parent,
+ bool show, GType type,
+ const char *property_name, va_list args);
+};
+
+/*
+ * Macros to help implement proxies between common YWidget virtual
+ * methods and the (multiply inherited) YGWidget base implementation
+ * for GTK+.
+ */
+#define YGWIDGET_IMPL_COMMON \
+ virtual bool setKeyboardFocus() \
+ { return doSetKeyboardFocus(); } \
+ virtual void setEnabling (bool enabled) \
+ { doSetEnabling (enabled); } \
+ virtual long nicesize (YUIDimension dim) { return 0; } \
+ virtual void moveChild (YWidget *child, long x, long y) {} \
+ virtual void setSize (long width, long height) {}
+
+// for containers
+// We can't use childAdded, since some classes don't want this called
+// for some children.
+#define YGWIDGET_IMPL_CHILD_ADDED(container) \
+ virtual void addChild (YWidget *ychild) { \
+ YContainerWidget::addChild (ychild); \
+ GtkWidget *child = YGWidget::get (ychild)->getLayout(); \
+ gtk_container_add (GTK_CONTAINER (container), child); \
+ sync_stretchable(); \
+ }
+#define YGWIDGET_IMPL_CHILD_REMOVED(container) \
+ virtual void childRemoved (YWidget *ychild) { \
+ GtkWidget *child = YGWidget::get (ychild)->getLayout(); \
+ gtk_container_remove (GTK_CONTAINER (container), child); \
+ }
+
+/* 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 *y_widget, YGWidget *parent,
+ YCPString label_text, YUIDimension label_ori,
+ bool show, GType type, const char *property_name, ...);
+ virtual ~YGLabeledWidget () {}
+
+ virtual GtkWidget* getWidget() { return m_field; }
+
+ void setLabelVisible(bool show);
+ void setBuddy (GtkWidget *widget);
+ virtual void doSetLabel (const YCPString &label);
+
+ YUIDimension orientation() { return m_orientation; }
+ GtkWidget *getLabelWidget() { return m_label; }
+
+ protected:
+ GtkWidget *m_label, *m_field;
+ YUIDimension m_orientation;
+};
+
+#define YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(ParentClass) \
+ virtual void setLabel (const YCPString &label) { \
+ IMPL \
+ doSetLabel (label); \
+ ParentClass::setLabel (label); \
+ }
+
+/* This is a convenience class for widgets that need scrollbars. */
+class YGScrolledWidget : public YGLabeledWidget
+{
+ public:
+ YGScrolledWidget(YWidget *y_widget, YGWidget *parent,
+ bool show, GType type, const char *property_name, ...);
+ // if you want a label, use:
+ YGScrolledWidget(YWidget *y_widget, YGWidget *parent,
+ YCPString label_text, YUIDimension label_ori,
+ bool show, GType type, const char *property_name, ...);
+ virtual ~YGScrolledWidget () {}
+
+ virtual 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: trunk/gtk/src/YGWizard.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGWizard.cc?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/YGWizard.cc (added)
+++ trunk/gtk/src/YGWizard.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,374 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+#include "YGUtils.h"
+#include "ygtkwizard.h"
+#include "YWizard.h"
+#include "YPushButton.h"
+
+class YGWizard : public YWizard, public YGWidget
+{
+ bool m_verboseCommands;
+
+ /* 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 (GtkWidget *widget, const YCPString &label, const YCPValue &id)
+ : YPushButton (YWidgetOpt(), label)
+ { m_widget = widget; setId (id); setLabel (label); }
+
+ void setLabel (const YCPString &label) {
+ string str = YGUtils::mapKBAccel (label->value_cstr());
+ gtk_button_set_label (GTK_BUTTON (m_widget), str.c_str());
+ str.empty() ? gtk_widget_hide (m_widget) : gtk_widget_show (m_widget);
+ YGUtils::setStockIcon (m_widget, str);
+ YPushButton::setLabel (label);
+ }
+
+ long nicesize (YUIDimension dim) { return 0; }
+ void setEnabling (bool enable) {
+ gtk_widget_set_sensitive (m_widget, enable);
+ YWidget::setEnabling (enable);
+ }
+
+ private:
+ GtkWidget *m_widget;
+ };
+
+ YGWButton *m_back_button, *m_abort_button, *m_next_button;
+ // release notes button would be a little more hassle to support; yast-qt
+ // doesn't support it too anyway.
+
+public:
+ YGWizard (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPValue &backButtonId, const YCPString &backButtonLabel,
+ const YCPValue &abortButtonId, const YCPString &abortButtonLabel,
+ const YCPValue &nextButtonId, const YCPString &nextButtonLabel)
+ : YWizard (opt, backButtonId, backButtonLabel,
+ abortButtonId, abortButtonLabel,
+ nextButtonId, nextButtonLabel),
+ YGWidget (this, parent, true, YGTK_TYPE_WIZARD, NULL)
+ {
+ IMPL
+ setBorder (0);
+ m_verboseCommands = false;
+
+ //** Application area
+ {
+ // We set a YReplacePoint as child with a certain id and it will then be
+ // replaced by the actual content. We put a YEmpty on it because it would
+ // crash otherwise (stretchable() functions should really check for
+ // hasChildren() first!).
+
+ YWidgetOpt opt, stretchOpt;
+ stretchOpt.isHStretchable.setValue( true );
+ stretchOpt.isVStretchable.setValue( true );
+
+ YWidget *align, *rp, *empty;
+ align = YGUI::ui()->createAlignment (this, stretchOpt,
+ YAlignCenter, YAlignCenter);
+ rp = YGUI::ui()->createReplacePoint (align, opt);
+ rp->setId (YCPSymbol (YWizardContentsReplacePointID));
+ empty = YGUI::ui()->createEmpty (rp, opt);
+
+ ((YContainerWidget *) align)->addChild (rp);
+ ((YContainerWidget *) rp)->addChild (empty);
+ this->addChild (align);
+ }
+
+ YGtkWizard *ygtk_wizard = YGTK_WIZARD (getWidget());
+
+ //** Steps/tree pane
+ bool steps_enabled = opt.stepsEnabled.value();
+ bool tree_enabled = opt.treeEnabled.value();
+ if (steps_enabled && tree_enabled) {
+ y2error ("YGWizard doesn't support both steps and tree enabled at the "
+ "same time.\nDisabling the steps...");
+ steps_enabled = false;
+ }
+ if (steps_enabled)
+ ygtk_wizard_enable_steps (ygtk_wizard);
+ if (tree_enabled)
+ ygtk_wizard_enable_tree (ygtk_wizard);
+
+ //** Setting the bottom buttons
+ m_back_button = new YGWButton (ygtk_wizard->m_back_button, backButtonLabel,
+ backButtonId);
+ m_abort_button = new YGWButton (ygtk_wizard->m_abort_button, abortButtonLabel,
+ abortButtonId);
+ m_next_button = new YGWButton (ygtk_wizard->m_next_button, nextButtonLabel,
+ nextButtonId);
+ YContainerWidget::addChild (m_back_button);
+ YContainerWidget::addChild (m_abort_button);
+ YContainerWidget::addChild (m_next_button);
+
+ ygtk_wizard_set_back_button_id (ygtk_wizard, new YCPValue (backButtonId),
+ delete_data_cb);
+ ygtk_wizard_set_abort_button_id (ygtk_wizard, new YCPValue (abortButtonId),
+ delete_data_cb);
+ ygtk_wizard_set_next_button_id (ygtk_wizard, new YCPValue (nextButtonId),
+ delete_data_cb);
+
+ //** 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);
+ }
+
+ ~YGWizard()
+ {
+ delete m_back_button;
+ delete m_abort_button;
+ delete m_next_button;
+ }
+
+ /* The purpose of this function is to do some sanity checks, besides
+ the simple test "cmd->name() == func".
+ args_type is a reverse hexadecimal number where
+ any = 0, string = 1, boolean = 2. */
+ static bool isCommand (const YCPTerm &cmd, const char *func,
+ guint args_nb, guint args_type)
+ {
+ if (cmd->name() == func) {
+ if ((unsigned) cmd->size() != args_nb) {
+ y2error ("YGWizard: expected %d arguments for the '%s' command. %d given.",
+ args_nb, func, cmd->size());
+ return false;
+ }
+
+ guint i, t;
+ for (i = 0, t = args_type; i < args_nb; i++, t >>= 4)
+ switch (t % 0x4) {
+ case 0x1:
+ if (!cmd->value(i)->isString()) {
+ y2error ("YGWizard: expected string as the %d argument for "
+ "the '%s' command.", i+1, func);
+ return false;
+ }
+ break;
+ case 0x2:
+ if (!cmd->value(i)->isBoolean()) {
+ y2error ("YGWizard: expected boolean as the %d argument for "
+ "the '%s' command.", i+1, func);
+ return false;
+ }
+ break;
+ }
+ return true;
+ }
+ return false;
+ }
+
+#define getStdStringArg(cmd, arg) (cmd->value(arg)->asString()->value())
+#define getCStringArg(cmd, arg) (cmd->value(arg)->asString()->value_cstr())
+#define getBoolArg(cmd, arg) (cmd->value(arg)->asBoolean()->value())
+#define getAnyArg(cmd, arg) (cmd->value(arg))
+
+ YCPValue command (const YCPTerm &cmd)
+ {
+ IMPL
+ if (m_verboseCommands)
+ y2milestone ("Processing wizard command: %s\n", cmd->name().c_str());
+
+ YGtkWizard *wizard = YGTK_WIZARD (getWidget());
+ if (isCommand (cmd, "SetHelpText", 1, 0x1))
+ ygtk_wizard_set_help_text (wizard, getCStringArg (cmd, 0));
+
+ else if (isCommand (cmd, "AddTreeItem", 3, 0x111)) {
+ if (!ygtk_wizard_add_tree_item (wizard, getCStringArg (cmd, 0),
+ getCStringArg (cmd, 1), getCStringArg (cmd, 2))) {
+ y2error ("YGWizard: there is no tree item with id '%s'",
+ getCStringArg (cmd, 0));
+ return YCPBoolean (false);
+ }
+ }
+ else if (isCommand (cmd, "DeleteTreeItems", 0, 0))
+ ygtk_wizard_clear_tree (wizard);
+ else if (isCommand (cmd, "SelectTreeItem", 1, 0x1)) {
+ if (!ygtk_wizard_select_tree_item (wizard, getCStringArg (cmd, 0))) {
+ y2error ("YGWizard: there is no tree item with id '%s'",
+ getCStringArg (cmd, 0));
+ return YCPBoolean (false);
+ }
+ }
+
+ else if (isCommand (cmd, "SetDialogHeading", 1, 0x1))
+ ygtk_wizard_set_header_text (wizard, YGUI::ui()->currentWindow(),
+ getCStringArg (cmd, 0));
+ else if (isCommand (cmd, "SetDialogIcon", 1, 0x1)) {
+ if (!ygtk_wizard_set_header_icon (wizard,
+ YGUI::ui()->currentWindow(), getCStringArg (cmd, 0))) {
+ y2warning ("YGWizard: could not load image: %s", getCStringArg (cmd, 0));
+// return YCPBoolean (false); - installer relies on this succeeding
+ }
+ }
+
+ else if (isCommand (cmd, "SetAbortButtonLabel", 1, 0x1) ||
+ isCommand (cmd, "SetCancelButtonLabel", 1, 0x1)) {
+ string str = YGUtils::mapKBAccel(getCStringArg (cmd, 0));
+ ygtk_wizard_set_abort_button_label (wizard, str.c_str());
+ }
+ else if (isCommand (cmd, "SetBackButtonLabel", 1, 0x1)) {
+ string str = YGUtils::mapKBAccel(getCStringArg (cmd, 0));
+ ygtk_wizard_set_back_button_label (wizard, str.c_str());
+ }
+ else if (isCommand (cmd, "SetNextButtonLabel", 1, 0x1) ||
+ isCommand (cmd, "SetAcceptButtonLabel", 1, 0x1)) {
+ string str = YGUtils::mapKBAccel(getCStringArg (cmd, 0));
+ ygtk_wizard_set_next_button_label (wizard, str.c_str());
+ }
+
+ else if (isCommand (cmd, "SetAbortButtonID", 1, 0x0)) {
+ YCPValue *id = new YCPValue (getAnyArg (cmd, 0));
+ ygtk_wizard_set_abort_button_id (wizard, id, delete_data_cb);
+ m_abort_button->setId (*id);
+ }
+ else if (isCommand (cmd, "SetBackButtonID", 1, 0x0)) {
+ YCPValue *id = new YCPValue (getAnyArg (cmd, 0));
+ ygtk_wizard_set_back_button_id (wizard, id, delete_data_cb);
+ m_back_button->setId (*id);
+ }
+ else if (isCommand (cmd, "SetNextButtonID", 1, 0x0)) {
+ YCPValue *id = new YCPValue (getAnyArg (cmd, 0));
+ ygtk_wizard_set_next_button_id (wizard, id, delete_data_cb);
+ m_next_button->setId (*id);
+ }
+
+ else if (isCommand (cmd, "EnableAbortButton", 1, 0x2))
+ ygtk_wizard_enable_abort_button (wizard, getBoolArg (cmd, 0));
+ else if (isCommand (cmd, "EnableBackButton", 1, 0x2))
+ ygtk_wizard_enable_back_button (wizard, getBoolArg (cmd, 0));
+ else if (isCommand (cmd, "EnableNextButton", 1, 0x2))
+ ygtk_wizard_enable_next_button (wizard, getBoolArg (cmd, 0));
+
+ else if (isCommand (cmd, "ProtectNextButton", 1, 0x2))
+ ygtk_wizard_protect_next_button (wizard, getBoolArg (cmd, 0));
+
+ else if (isCommand (cmd, "SetFocusToNextButton", 0, 0))
+ ygtk_wizard_focus_next_button (wizard);
+ else if (isCommand (cmd, "SetFocusToBackButton", 0, 0))
+ ygtk_wizard_focus_back_button (wizard);
+
+ else if (isCommand (cmd, "AddMenu", 2, 0x11)) {
+ string str = YGUtils::mapKBAccel(getCStringArg (cmd, 0));
+ ygtk_wizard_add_menu (wizard, str.c_str(), getCStringArg (cmd, 1));
+ }
+ else if (isCommand (cmd, "AddMenuEntry", 3, 0x111)) {
+ string str = YGUtils::mapKBAccel(getCStringArg (cmd, 1));
+ if (!ygtk_wizard_add_menu_entry (wizard, getCStringArg (cmd, 0),
+ str.c_str(), getCStringArg (cmd, 2))) {
+ y2error ("YGWizard: there is no menu item with id '%s'",
+ getCStringArg (cmd, 0));
+ return YCPBoolean (false);
+ }
+ }
+ else if (isCommand (cmd, "AddSubMenu", 3, 0x111)) {
+ string str = YGUtils::mapKBAccel(getCStringArg (cmd, 1));
+ if (!ygtk_wizard_add_sub_menu (wizard, getCStringArg (cmd, 0),
+ str.c_str(), getCStringArg (cmd, 2))) {
+ y2error ("YGWizard: there is no menu item with id '%s'",
+ getCStringArg (cmd, 0));
+ return YCPBoolean (false);
+ }
+ }
+ else if (isCommand (cmd, "AddMenuSeparator", 3, 0x111)) {
+ if (!ygtk_wizard_add_menu_separator (wizard, getCStringArg (cmd, 0))) {
+ y2error ("YGWizard: there is no menu item with id '%s'",
+ getCStringArg (cmd, 0));
+ return YCPBoolean (false);
+ }
+ }
+
+ else if (isCommand (cmd, "SetVerboseCommands", 1, 0x2))
+ m_verboseCommands = getBoolArg (cmd, 0);
+ else if (isCommand (cmd, "Ping", 0, 0))
+ y2debug ("YGWizard is active");
+
+ else if (isCommand (cmd, "AddStepHeading", 1, 0x1))
+ ygtk_wizard_add_step_header (wizard, getCStringArg (cmd, 0));
+ else if (isCommand (cmd, "AddStep", 2, 0x11))
+ ygtk_wizard_add_step (wizard, getCStringArg (cmd, 0), getCStringArg (cmd, 1));
+ else if (isCommand (cmd, "SetCurrentStep", 1, 0x1)) {
+ if (!ygtk_wizard_set_current_step (wizard, getCStringArg (cmd, 0))) {
+ y2error ("YGWizard: there is no step with id %s.", getCStringArg (cmd, 0));
+ return YCPBoolean (false);
+ }
+ }
+ else if (isCommand (cmd, "UpdateSteps", 0, 0))
+ ;
+ else if (isCommand (cmd, "DeleteSteps", 0, 0))
+ ygtk_wizard_clear_steps (wizard);
+
+ else if (isCommand (cmd, "ShowReleaseNotesButton", 2, 0x01)) {
+ string label = YGUtils::mapKBAccel(getCStringArg (cmd, 0));
+ ygtk_wizard_set_release_notes_button_label (wizard, label.c_str(),
+ new YCPValue (getAnyArg (cmd, 1)), delete_data_cb);
+ }
+ else if (isCommand (cmd, "HideReleaseNotesButton", 0, 0))
+ ygtk_wizard_show_release_notes_button (wizard, FALSE);
+
+ else if (isCommand (cmd, "RetranslateInternalButtons", 0, 0))
+ ; // we don't need this as we don't use switch buttons
+
+ else {
+ y2error ("Unsupported wizard command (or invalid arguments): %s\n",
+ cmd->name().c_str());
+ return YCPBoolean (false);
+ }
+ return YCPBoolean (true);
+ }
+
+ virtual YCPString currentTreeSelection()
+ {
+ YGtkWizard *wizard = YGTK_WIZARD (getWidget());
+ const char *selected = ygtk_wizard_get_tree_selection (wizard);
+ if (selected)
+ return YCPString (selected);
+ return YCPString ("");
+ }
+
+ static void action_triggered_cb (YGtkWizard *wizard, gpointer id,
+ gint id_type, YGWizard *pThis)
+ {
+ IMPL
+ if ((GType) id_type == G_TYPE_STRING) {
+ YCPString _id ((char *) id);
+ YGUI::ui()->sendEvent (new YMenuEvent (YCPValue (_id)));
+ }
+ else
+ YGUI::ui()->sendEvent (new YMenuEvent (*((YCPValue *) id)));
+ }
+
+ static void delete_data_cb (gpointer data)
+ { delete (YCPValue*) data; }
+
+
+ YGWIDGET_IMPL_COMMON
+ YGWIDGET_IMPL_CHILD_ADDED (getWidget())
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YWidget *
+YGUI::createWizard (YWidget *parent, YWidgetOpt &opt,
+ const YCPValue &backButtonId, const YCPString &backButtonLabel,
+ const YCPValue &abortButtonId, const YCPString &abortButtonLabel,
+ const YCPValue &nextButtonId, const YCPString &nextButtonLabel)
+{
+ return new YGWizard (opt, YGWidget::get (parent),
+ backButtonId, backButtonLabel,
+ abortButtonId, abortButtonLabel,
+ nextButtonId, nextButtonLabel);
+}
Added: trunk/gtk/src/YGi18n.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGi18n.h?rev=42515&view=…
==============================================================================
--- trunk/gtk/src/YGi18n.h (added)
+++ trunk/gtk/src/YGi18n.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,38 @@
+/*---------------------------------------------------------------------\
+| |
+| __ __ ____ _____ ____ |
+| \ \ / /_ _/ ___|_ _|___ \ |
+| \ V / _` \___ \ | | __) | |
+| | | (_| |___) || | / __/ |
+| |_|\__,_|____/ |_| |_____| |
+| |
+| core system |
+| (C) SuSE GmbH |
+\----------------------------------------------------------------------/
+
+ File: YGi18n.h
+
+ Author: Jiri Srain <jsrain(a)suse.cz>
+
+/-*/
+
+// -*- c++ -*-
+
+#ifndef YGi18n_h
+#define YGi18n_h
+
+#include <libintl.h>
+
+
+inline const char * _( const char * msgid )
+{
+ return ( !msgid || !*msgid ) ? "" : gettext(msgid );
+}
+
+inline const char * _( const char * msgid1, const char * msgid2, unsigned long int n )
+{
+ return ngettext(msgid1, msgid2, n );
+}
+
+
+#endif // YGi18n_h
Added: trunk/gtk/src/computer.xpm
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/computer.xpm?rev=42515&v…
==============================================================================
--- trunk/gtk/src/computer.xpm (added)
+++ trunk/gtk/src/computer.xpm Thu Nov 29 18:25:41 2007
@@ -0,0 +1,186 @@
+/* XPM */
+static char const * computer_xpm[] = {
+"24 24 159 2",
+" c None",
+". c #82847F",
+"+ c #787A76",
+"@ c #E4E4E2",
+"# c #D2D3D0",
+"$ c #E0E0E0",
+"% c #DDDDDC",
+"& c #364878",
+"* c #DADDD8",
+"= c #D4D5D3",
+"- c #DEDEDD",
+"; c #7685A7",
+"> c #7584A6",
+", c #7484A5",
+"' c #7283A4",
+") c #7181A4",
+"! c #7081A3",
+"~ c #6F80A2",
+"{ c #6E7EA1",
+"] c #6C7DA0",
+"^ c #68799E",
+"/ c #C2C4BF",
+"( c #C6C7C5",
+"_ c #DFE0DF",
+": c #7586A7",
+"< c #7585A7",
+"[ c #7485A7",
+"} c #7283A6",
+"| c #7182A5",
+"1 c #7182A4",
+"2 c #6F80A3",
+"3 c #6E80A3",
+"4 c #6C7EA2",
+"5 c #6B7DA1",
+"6 c #5A6E96",
+"7 c #E3E5E1",
+"8 c #D6D6D5",
+"9 c #7688A9",
+"0 c #7586A8",
+"a c #7386A7",
+"b c #7285A6",
+"c c #7284A6",
+"d c #7082A5",
+"e c #7081A5",
+"f c #6E81A4",
+"g c #566B95",
+"h c #49618D",
+"i c #445C8A",
+"j c #C6C7C4",
+"k c #DEDFDD",
+"l c #7688AA",
+"m c #7587A9",
+"n c #7487A8",
+"o c #7386A8",
+"p c #7285A7",
+"q c #7084A6",
+"r c #7082A6",
+"s c #516793",
+"t c #47608D",
+"u c #47608C",
+"v c #D6D8D5",
+"w c #DFE0DE",
+"x c #7589AB",
+"y c #7588AA",
+"z c #7387A9",
+"A c #7285A8",
+"B c #7085A8",
+"C c #4E6793",
+"D c #4A6390",
+"E c #496390",
+"F c #BCBEB9",
+"G c #C7C8C6",
+"H c #E0E1DF",
+"I c #768BAC",
+"J c #758AAC",
+"K c #7488AB",
+"L c #7387AA",
+"M c #5F779E",
+"N c #506B95",
+"O c #4C6793",
+"P c #4C6692",
+"Q c #4C6693",
+"R c #D9DAD8",
+"S c #E1E3E0",
+"T c #778BAE",
+"U c #748AAC",
+"V c #57729B",
+"W c #4F6A96",
+"X c #4E6A95",
+"Y c #4E6A96",
+"Z c #4F6995",
+"` c #4E6996",
+" . c #DADBD9",
+".. c #E2E3E1",
+"+. c #516E99",
+"@. c #516D99",
+"#. c #516D98",
+"$. c #506D99",
+"%. c #DCDEDB",
+"&. c #E5E6E4",
+"*. c #DDE0DB",
+"=. c #DFDFDC",
+"-. c #E6E7E4",
+";. c #D3D6D0",
+">. c #E0E3DE",
+",. c #BABDB7",
+"'. c #E0E1DE",
+"). c #DBDBD9",
+"!. c #E6E8E5",
+"~. c #E5E7E5",
+"{. c #E5E7E4",
+"]. c #E5E6E3",
+"^. c #E5E5E2",
+"/. c #E4E5E2",
+"(. c #E3E4E2",
+"_. c #E3E3E2",
+":. c #E2E3E2",
+"<. c #C9CCC7",
+"[. c #898C86",
+"}. c #838580",
+"|. c #C3C4C0",
+"1. c #D3D4D1",
+"2. c #DCDDDB",
+"3. c #CBCCC8",
+"4. c #BCBDB9",
+"5. c #B6B7B3",
+"6. c #7F817C",
+"7. c #868883",
+"8. c #878984",
+"9. c #888A85",
+"0. c #A2A2A2",
+"a. c #B0B1AF",
+"b. c #CCCCCA",
+"c. c #ACACAB",
+"d. c #ADADAC",
+"e. c #C7C7C7",
+"f. c #C0C0BF",
+"g. c #969695",
+"h. c #7F817D",
+"i. c #7E807B",
+"j. c #A4A4A3",
+"k. c #BDBDBB",
+"l. c #A9A9A9",
+"m. c #A9AAA9",
+"n. c #AAAAA9",
+"o. c #CBCBCA",
+"p. c #A9A9A8",
+"q. c #CDCDCC",
+"r. c #A4A5A3",
+"s. c #A6A6A6",
+"t. c #959793",
+"u. c #EDEEED",
+"v. c #E1E1E0",
+"w. c #E3E4E1",
+"x. c #E1E1DF",
+"y. c #DFE1DE",
+"z. c #E1E2E1",
+"A. c #E2E4E2",
+"B. c #747671",
+" ",
+" . . . . . . . . . . . . . . . . + ",
+" . @ # # # # # # # # # # # # # # $ . ",
+" . % & & & & & & & & & & & & & * = . ",
+" . - & ; > , ' ) ! ~ { ] ] ^ & / ( . ",
+" . _ & : < [ } | 1 2 3 4 5 6 & 7 8 . ",
+" . - & 9 0 a b c d e f g h i & / j . ",
+" . k & l m n o p q r s t t u & 7 v . ",
+" . w & x y z z A B C D E D E & F G . ",
+" . H & I J K L M N O P P O Q & 7 R . ",
+" . S & T I U V W X Y Z Y ` W & 7 .. ",
+" . ..& +.@.#.@.@.@.#.@.+.#.$.& 7 %.. ",
+" . &.& & & & & & & & & & & & & *.=.. ",
+" . -.;.7 7 7 >.,.,.,.*.>.>.>.>.;.'.. ",
+" . ).!.~.{.{.&.&.].^././.(._.:.:.<.. ",
+" . . . . . . . . [.[.[.[.[.[.[.}. ",
+" . |.1.2.2.1.3.|.4.5.6.. }.7.8.8. ",
+" 9.9.9.9.9.9.9.9.9.9.9.9.9.9. 8. ",
+" 9.0.a.b.c.c.c.c.c.c.d.0.e.f.g.9.h.i. ",
+" 9.j.G k.l.m.m.n.n.n.n.o.p.p.q.r.s.t. ",
+" 9.u.v.w.x.x.H x.x.x.x.x.:.y.y.z.&.A...9. ",
+" 7.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.B. ",
+" ",
+" "};
Added: trunk/gtk/src/dummy.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/dummy.cc?rev=42515&view=…
==============================================================================
--- trunk/gtk/src/dummy.cc (added)
+++ trunk/gtk/src/dummy.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,12 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <YGUI.h>
+
+int main (int argc, char **argv)
+{
+ YGUI(argc, argv, false, "foo");
+ return 0;
+}
Added: trunk/gtk/src/test.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/test.cc?rev=42515&view=a…
==============================================================================
--- trunk/gtk/src/test.cc (added)
+++ trunk/gtk/src/test.cc Thu Nov 29 18:25:41 2007
@@ -0,0 +1,186 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <stdio.h>
+#include <YUI.h>
+#include <gtk/gtk.h>
+#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;
+}
+
+bool testFilterText ()
+{
+ fprintf (stderr, "Test filter text\t");
+ struct {
+ const char *in;
+ const char *valid;
+ const char *out;
+ } aTests[] = {
+ { "Foo", "F", "F" },
+ { "Foo", "Fo", "Foo" },
+ { "Baa", "a", "aa" },
+ { "Kuckles", "Ks", "Ks" },
+ { NULL, NULL }
+ };
+ for (int i = 0; aTests[i].in; i++) {
+ string filtered = YGUtils::filterText
+ (aTests[i].in, strlen (aTests[i].in), aTests[i].valid);
+ if (filtered != aTests[i].out) {
+ fprintf (stderr, "Mis-filtered text '%s' vs '%s'\n",
+ filtered.c_str(), aTests[i].out);
+ return false;
+ }
+ fprintf (stderr, "%d ", i);
+ }
+ fprintf (stderr, "\n");
+ 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>" },
+ // product substitution
+ { "&product;", "<body>foo</body>" },
+ { " <p>&product;</p>", "<body><p>foo</p></body>" },
+ // outer tag
+ { "some text", "<body>some text</body>" },
+ // unquoted attributes
+ { "<foo baa=Foo></foo>", "<body><foo baa=\"Foo\"></foo></body>" },
+ // break tags
+ { "<br>", "<body><br/></body>" },
+ { "<hr>", "<body><hr/></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><unclosed foo=\"baa\"></unclosed></body>" },
+ // unclosed 'early close' tags
+ { "<i>Some<p>text<p> here<p></i>",
+ "<body><i>Some<p>text</p><p> here</p><p></p></i></body>" },
+ { "<ul><li>foo<li>baa",
+ "<body><ul><li>foo</li><li>baa</li></ul></body>" },
+ { "no outer<p>unclosed<p>several<b>unclosed bold",
+ "<body>no outer<p>unclosed</p><p>several<b>unclosed bold</b></p></body>" },
+ // multiple white spacing -- proper HTML would had collapsed those multiple
+ // spaces -- not important anyway
+ { "one day I will do", "<body>one day I will do</body>" },
+ // comment
+ { "we need <b>to <!-- really need to? --> do something</b> about it.",
+ "<body>we need <b>to do something</b> about it.</body>" },
+ { NULL, NULL }
+ };
+ for (int i = 0; aTests[i].in; i++) {
+ gchar *out = ygutils_convert_to_xhmlt_and_subst (aTests[i].in, "foo");
+ if (strcmp (out, aTests[i].out)) {
+ fprintf (stderr, "Mis-converted entry %d XML '%s' should be '%s'\n",
+ i, out, aTests[i].out);
+ return false;
+ }
+ fprintf (stderr, "%d ", i);
+ g_free (out);
+ }
+ fprintf (stderr, "\n");
+ return true;
+}
+
+bool testStrCmp()
+{
+ fprintf (stderr, "Test our strcmp\t");
+ struct {
+ const char *in1, *in2;
+ int out;
+ } aTests[] = {
+ { "aaa", "aaaa", 1 },
+ { "29", "235", -1 },
+ { "aA", "Aa", 0 },
+ { "200rt9", "200rT9", 0 },
+ { NULL, NULL }
+ };
+ for (int i = 0; aTests[i].in1; i++) {
+ int ret = YGUtils::strcmp(aTests[i].in1, aTests[i].in2);
+ if (ret * aTests[i].out < 0 || (ret && !aTests[i].out) || (!ret && aTests[i].out)) {
+ fprintf (stderr, "Mis-mapped str comp '%d' vs '%d' ('%s' to '%s')\n",
+ ret, aTests[i].out, aTests[i].in1, aTests[i].in2);
+ return false;
+ }
+ fprintf (stderr, "%d ", i);
+ }
+ fprintf (stderr, "\n");
+ return true;
+}
+
+bool testMarkupEscape()
+{
+ fprintf (stderr, "Test markup escape\t");
+ struct {
+ const char *in;
+ const char *out;
+ bool escape_br;
+ } aTests[] = {
+ { "< text />", "< text />" },
+ { "um\ndois\ntres", "um\ndois\ntres" },
+ { NULL, NULL }
+ };
+ for (int i = 0; aTests[i].in; i++) {
+ string out = YGUtils::escape_markup (aTests[i].in);
+ if (out != aTests[i].out) {
+ fprintf (stderr, "Mis-converted entry %d XML '%s' should be '%s'\n",
+ i, out.c_str(), aTests[i].out);
+ return false;
+ }
+ fprintf (stderr, "%d ", i);
+ }
+ fprintf (stderr, "\n");
+ return true;
+}
+
+int main (int argc, char **argv)
+{
+ bool bSuccess = true;
+
+ bSuccess &= testMapKBAccel();
+ bSuccess &= testFilterText();
+ bSuccess &= testXHtmlConvert();
+ bSuccess &= testStrCmp();
+ bSuccess &= testMarkupEscape();
+
+ return !bSuccess;
+}
Added: trunk/gtk/src/ygdkmngloader.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygdkmngloader.c?rev=4251…
==============================================================================
--- trunk/gtk/src/ygdkmngloader.c (added)
+++ trunk/gtk/src/ygdkmngloader.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,410 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGdkMngLoader image loader */
+// check the header file for information about this loader
+
+#include "ygdkmngloader.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/mman.h>
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+/* A few chunks ids */
+#define MNG_UINT_MHDR 0x4d484452L
+#define MNG_UINT_BACK 0x4241434bL
+#define MNG_UINT_PLTE 0x504c5445L
+#define MNG_UINT_tRNS 0x74524e53L
+#define MNG_UINT_IHDR 0x49484452L
+#define MNG_UINT_IDAT 0x49444154L
+#define MNG_UINT_IEND 0x49454e44L
+#define MNG_UINT_MEND 0x4d454e44L
+#define MNG_UINT_FRAM 0x4652414dL
+#define MNG_UINT_LOOP 0x4c4f4f50L
+#define MNG_UINT_ENDL 0x454e444cL
+#define MNG_UINT_TERM 0x5445524dL
+
+//** Utilities to read the MNG file
+
+typedef struct DataStream {
+ const guint8 *data;
+ const long size;
+ long offset;
+} DataStream;
+static DataStream data_stream_constructor (const guint8 *raw_data, long size)
+{
+ DataStream data = { raw_data, size, 0 };
+ return data;
+}
+
+static gboolean read_signature (DataStream *data)
+{
+ if (data->offset+8 > data->size)
+ return FALSE;
+ data->offset += 8;
+ return memcmp (data->data + data->offset-8, "\212MNG\r\n\032\n", 8) == 0;
+}
+
+static gboolean read_uint8 (DataStream *data, guint8 *value)
+{
+ if (data->offset+1 > data->size)
+ return FALSE;
+ *value = data->data [data->offset++];
+ return TRUE;
+}
+
+static gboolean read_uint32 (DataStream *data, guint32 *value)
+{
+ if (data->offset+4 > data->size)
+ return FALSE;
+ *value = data->data[data->offset+0] << 24;
+ *value |= data->data[data->offset+1] << 16;
+ *value |= data->data[data->offset+2] << 8;
+ *value |= data->data[data->offset+3];
+ data->offset += 4;
+ return TRUE;
+}
+
+static gboolean read_data (DataStream *data, guint32 size, GdkPixbufLoader *loader,
+ GError **error)
+{
+ if (data->offset+size > data->size)
+ {
+ g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ "Unexpected end of file when reading PNG chunk");
+ return FALSE;
+ }
+ gboolean ret;
+ ret = gdk_pixbuf_loader_write (loader, data->data + data->offset, size, error);
+ data->offset += size;
+ return ret;
+}
+
+static void image_prepared_cb (GdkPixbufLoader *loader, YGdkMngPixbuf *mng_pixbuf)
+{
+ GdkPixbuf *pix = gdk_pixbuf_loader_get_pixbuf (loader);
+ mng_pixbuf->frames = g_list_append (mng_pixbuf->frames, pix);
+}
+
+//** YGdkMngPixbuf
+
+G_DEFINE_TYPE (YGdkMngPixbuf, ygdk_mng_pixbuf, GDK_TYPE_PIXBUF_ANIMATION)
+
+static void ygdk_mng_pixbuf_init (YGdkMngPixbuf *pixbuf)
+{
+}
+
+gboolean ygdk_mng_pixbuf_is_file_mng (const gchar *filename)
+{
+ FILE *file = fopen (filename, "rb");
+ if (!file)
+ goto is_file_mng_failed;
+
+ guchar raw_data [8];
+ if (fread (raw_data, 1, 8, file) < 8)
+ goto is_file_mng_failed;
+
+ gboolean ret = ygdk_mng_pixbuf_is_data_mng (raw_data, 8);
+ fclose (file);
+ return ret;
+
+is_file_mng_failed:
+ fclose (file);
+ return FALSE;
+}
+
+gboolean ygdk_mng_pixbuf_is_data_mng (const guint8 *raw_data, long size)
+{
+ DataStream data = data_stream_constructor (raw_data, size);
+ return read_signature (&data);
+}
+
+#define SET_ERROR(msg) { error = TRUE; \
+ g_set_error (error_msg, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, msg); }
+
+GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_file (const gchar *filename,
+ GError **error_msg)
+{
+ gboolean error = FALSE;
+ FILE *file = fopen (filename, "rb");
+ if (!file)
+ {
+ SET_ERROR ("Could not open specified file")
+ return NULL;
+ }
+
+ fseek (file, 0, SEEK_END);
+ long file_size = ftell (file);
+ fseek (file, 0, SEEK_SET);
+
+ GdkPixbufAnimation *mng_pixbuf = 0;
+ guchar *data = mmap (NULL, file_size, PROT_READ, MAP_PRIVATE,
+ fileno (file), 0);
+ if (data == MAP_FAILED)
+ SET_ERROR ("Could not map file")
+ else
+ {
+ mng_pixbuf = ygdk_mng_pixbuf_new_from_data (data, file_size, error_msg);
+ munmap (data, file_size);
+ }
+ fclose (file);
+ return mng_pixbuf;
+}
+
+GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_data (const guint8 *raw_data, long size,
+ GError **error_msg)
+{
+ DataStream data = data_stream_constructor (raw_data, size);
+
+ gboolean error = FALSE;
+ if (!read_signature (&data))
+ {
+ SET_ERROR ("Not a MNG file")
+ return NULL;
+ }
+
+ YGdkMngPixbuf *mng_pixbuf = g_object_new (YGDK_TYPE_MNG_PIXBUF, NULL);
+ mng_pixbuf->iteration_max = 0x7fffffff;
+
+ guint32 chunk_size, chunk_id;
+ long chunk_offset;
+ GdkPixbufLoader *loader = NULL; /* currently loading... */
+ gboolean first_read = TRUE;
+
+ do {
+ error = !read_uint32 (&data, &chunk_size);
+ error = error || !read_uint32 (&data, &chunk_id);
+ if (error)
+ {
+ SET_ERROR ("Unexpected end of file on new chunk")
+ break;
+ }
+ chunk_offset = data.offset + chunk_size + 4/*CRC*/;
+
+ if (first_read && chunk_id != MNG_UINT_MHDR)
+ {
+ SET_ERROR ("MHDR chunk must come first")
+ break;
+ }
+
+ // not currently reading a PNG stream
+ if (!loader)
+ {
+ switch (chunk_id)
+ {
+ case MNG_UINT_MHDR:
+ if (!first_read)
+ {
+ SET_ERROR ("Only one MHDR chunk allowed")
+ break;
+ }
+
+ if (chunk_size == 7*4)
+ {
+ // Read MHDR chunk data
+ error = !read_uint32 (&data, &mng_pixbuf->frame_width);
+ error = error || !read_uint32 (&data, &mng_pixbuf->frame_height);
+ error = error || !read_uint32 (&data, &mng_pixbuf->ticks_per_second);
+ if (error)
+ SET_ERROR ("Unexpected end of file on MHDR chunk")
+ /* Next atttributes: Nominal_layer_count, Nominal_frame_count,
+ Nominal_play_time, Simplicity_profile */
+ else if (mng_pixbuf->frame_width <= 0 ||
+ mng_pixbuf->frame_height <= 0 ||
+ mng_pixbuf->ticks_per_second < 0)
+ SET_ERROR ("Invalid MHDR parameter")
+//fprintf(stderr, "ticks per second: %d\n", mng_pixbuf->ticks_per_second);
+ }
+ else
+ SET_ERROR ("MHDR chunk must be 28 bytes long")
+ break;
+ case MNG_UINT_IHDR:
+ loader = gdk_pixbuf_loader_new_with_type ("png", NULL);
+ g_signal_connect (G_OBJECT (loader), "area-prepared",
+ G_CALLBACK (image_prepared_cb), mng_pixbuf);
+ gdk_pixbuf_loader_set_size (loader, mng_pixbuf->frame_width,
+ mng_pixbuf->frame_height);
+
+ {
+ const guchar sig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
+ if(!gdk_pixbuf_loader_write (loader, sig, 8, error_msg))
+ {
+ error = TRUE;
+ break;
+ }
+ }
+ break;
+ case MNG_UINT_TERM:
+ if (chunk_size > 1)
+ {
+ // Read TERM chunk data
+ guint8 t;
+ error = !read_uint8 (&data, &t); // term action
+ if (t == 3 && chunk_size == 2+8)
+ {
+ error = error || !read_uint8 (&data, &t); // after term action
+ error = error || !read_uint32 (&data, &mng_pixbuf->last_frame_delay);
+ error = error || !read_uint32 (&data, &mng_pixbuf->iteration_max);
+ if (error)
+ SET_ERROR ("Unexpected end of file on TERM chunk")
+ }
+ else
+ SET_ERROR ("TERM chunk must be 10 bytes when term action is 3")
+ }
+ else
+ SET_ERROR ("TERM chunk must have at least 1 byte")
+ break;
+ case MNG_UINT_BACK:
+ // TODO:
+ break;
+ case MNG_UINT_IDAT:
+ case MNG_UINT_IEND:
+ if (loader != NULL)
+ SET_ERROR ("Corrupted PNG chunk closures")
+ break;
+ case MNG_UINT_MEND:
+ default:
+ break;
+ }
+ }
+
+ if (error)
+ break;
+
+ // loading a PNG stream
+ if (loader)
+ {
+ data.offset -= 8;
+ if (!read_data (&data, chunk_size+8+4, loader, error_msg))
+ error = TRUE;
+ else if (chunk_id == MNG_UINT_IEND)
+ {
+ if (!gdk_pixbuf_loader_close (loader, error_msg))
+ {
+ error = TRUE;
+ break;
+ }
+ loader = NULL;
+ }
+ }
+
+ data.offset = chunk_offset;
+ first_read = FALSE;
+ } while (chunk_id != MNG_UINT_MEND && !error);
+
+ if (error)
+ {
+ g_object_unref (G_OBJECT (mng_pixbuf));
+ return NULL;
+ }
+ return GDK_PIXBUF_ANIMATION (mng_pixbuf);
+}
+
+#undef SET_ERROR
+
+static gboolean ygdk_mng_pixbuf_is_static_image (GdkPixbufAnimation *anim)
+{
+ YGdkMngPixbuf *mng_anim = YGDK_MNG_PIXBUF (anim);
+ return g_list_length (mng_anim->frames) == 1;
+}
+
+static GdkPixbuf *ygdk_mng_pixbuf_get_static_image (GdkPixbufAnimation *anim)
+{
+ YGdkMngPixbuf *mng_anim = YGDK_MNG_PIXBUF (anim);
+ return g_list_nth_data (mng_anim->frames, 0);
+}
+
+static void ygdk_mng_pixbuf_get_size (GdkPixbufAnimation *anim, int *width, int *height)
+{
+ YGdkMngPixbuf *mng_anim = YGDK_MNG_PIXBUF (anim);
+ if (width) *width = mng_anim->frame_width;
+ if (height) *height = mng_anim->frame_height;
+}
+
+static GdkPixbufAnimationIter *ygdk_mng_pixbuf_get_iter (GdkPixbufAnimation *anim,
+ const GTimeVal *start_time)
+{
+ YGdkMngPixbufIter *iter = g_object_new (YGDK_TYPE_MNG_PIXBUF_ITER, NULL);
+ iter->mng_pixbuf = YGDK_MNG_PIXBUF( anim );
+ iter->cur_frame = 0;
+ return GDK_PIXBUF_ANIMATION_ITER( iter );
+}
+
+static void ygdk_mng_pixbuf_class_init (YGdkMngPixbufClass *klass)
+{
+ ygdk_mng_pixbuf_parent_class = g_type_class_peek_parent (klass);
+
+ GdkPixbufAnimationClass *pixbuf_class = GDK_PIXBUF_ANIMATION_CLASS (klass);
+ pixbuf_class->is_static_image = ygdk_mng_pixbuf_is_static_image;
+ pixbuf_class->get_static_image = ygdk_mng_pixbuf_get_static_image;
+ pixbuf_class->get_size = ygdk_mng_pixbuf_get_size;
+ pixbuf_class->get_iter = ygdk_mng_pixbuf_get_iter;
+}
+
+//** YGdkMngPixbufIter
+
+G_DEFINE_TYPE (YGdkMngPixbufIter, ygdk_mng_pixbuf_iter, GDK_TYPE_PIXBUF_ANIMATION_ITER)
+
+static void ygdk_mng_pixbuf_iter_init (YGdkMngPixbufIter *iter)
+{
+}
+
+static GdkPixbuf *ygdk_mng_pixbuf_iter_get_pixbuf (GdkPixbufAnimationIter *iter)
+{
+ YGdkMngPixbufIter *mng_iter = YGDK_MNG_PIXBUF_ITER (iter);
+ return g_list_nth_data (mng_iter->mng_pixbuf->frames, mng_iter->cur_frame);
+}
+
+static gboolean ygdk_mng_pixbuf_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter)
+{
+ return FALSE;
+}
+
+static int ygdk_mng_pixbuf_iter_get_delay_time (GdkPixbufAnimationIter *iter)
+{
+ YGdkMngPixbufIter *mng_iter = YGDK_MNG_PIXBUF_ITER (iter);
+ int delay = 1000.0 / mng_iter->mng_pixbuf->ticks_per_second;
+ if (mng_iter->cur_frame == g_list_length (mng_iter->mng_pixbuf->frames)-1)
+ delay += mng_iter->mng_pixbuf->last_frame_delay;
+ return delay;
+}
+
+static gboolean ygdk_mng_pixbuf_iter_advance (GdkPixbufAnimationIter *iter,
+ const GTimeVal *current_time)
+{
+ YGdkMngPixbufIter *mng_iter = YGDK_MNG_PIXBUF_ITER (iter);
+ YGdkMngPixbuf *mng_pixbuf = mng_iter->mng_pixbuf;
+ if (!mng_pixbuf->frames)
+ return FALSE;
+
+ gboolean can_advance = TRUE;
+ int frames_len = g_list_length (mng_pixbuf->frames);
+ if (mng_iter->cur_frame+1 == frames_len)
+ {
+ if (mng_pixbuf->iteration_max == 0x7fffffff ||
+ mng_iter->cur_iteration < mng_pixbuf->iteration_max)
+ mng_iter->cur_iteration++;
+ else
+ can_advance = FALSE;
+ }
+
+ if (can_advance)
+ mng_iter->cur_frame = (mng_iter->cur_frame+1) % frames_len;
+ return can_advance;
+}
+
+static void ygdk_mng_pixbuf_iter_class_init (YGdkMngPixbufIterClass *klass)
+{
+ ygdk_mng_pixbuf_iter_parent_class = g_type_class_peek_parent (klass);
+
+ GdkPixbufAnimationIterClass *iter_class = GDK_PIXBUF_ANIMATION_ITER_CLASS (klass);
+ iter_class->get_delay_time = ygdk_mng_pixbuf_iter_get_delay_time;
+ iter_class->get_pixbuf = ygdk_mng_pixbuf_iter_get_pixbuf;
+ iter_class->on_currently_loading_frame = ygdk_mng_pixbuf_iter_on_currently_loading_frame;
+ iter_class->advance = ygdk_mng_pixbuf_iter_advance;
+}
+
Added: trunk/gtk/src/ygdkmngloader.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygdkmngloader.h?rev=4251…
==============================================================================
--- trunk/gtk/src/ygdkmngloader.h (added)
+++ trunk/gtk/src/ygdkmngloader.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,80 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* GdkPixbuf doesn't support MNG files... MNG extends PNG adding movie playback
+ capabilities.
+ This code aims for MNG-VLC (smallest subset of the format), though
+ it isn't completely compliable.
+*/
+
+#ifndef YGDK_MNG_PIXBUF_H
+#define YGDK_MNG_PIXBUF_H
+
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gdk-pixbuf/gdk-pixbuf-animation.h>
+G_BEGIN_DECLS
+
+#define YGDK_TYPE_MNG_PIXBUF (ygdk_mng_pixbuf_get_type ())
+#define YGDK_MNG_PIXBUF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGDK_TYPE_MNG_PIXBUF, YGdkMngPixbuf))
+#define YGDK_MNG_PIXBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGDK_TYPE_MNG_PIXBUF, YGdkMngPixbufClass))
+#define YGDK_IS_MNG_PIXBUF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGDK_TYPE_MNG_PIXBUF))
+#define YGDK_IS_MNG_PIXBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGDK_TYPE_MNG_PIXBUF))
+#define YGDK_MNG_PIXBUF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGK_TYPE_MNG_PIXBUF, YGdkMngPixbufClass))
+
+typedef struct YGdkMngPixbuf
+{
+ GdkPixbufAnimation parent;
+
+ // private: (use GdkPixbufAnimation API)
+ GList *frames; // of GdkPixbufs
+ // MHDR header
+ guint32 frame_width, frame_height, ticks_per_second;
+ // TERM header
+ guint32 last_frame_delay, iteration_max;
+} YGdkMngPixbuf;
+
+typedef struct YGdkMngPixbufClass
+{
+ GdkPixbufAnimationClass parent_class;
+} YGdkMngPixbufClass;
+
+GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_file (const gchar *filename, GError **error);
+GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_data (const guint8 *data, long size, GError **error);
+gboolean ygdk_mng_pixbuf_is_file_mng (const gchar *filename);
+gboolean ygdk_mng_pixbuf_is_data_mng (const guint8 *data, long size);
+
+GType ygdk_mng_pixbuf_get_type (void) G_GNUC_CONST;
+
+#define YGDK_TYPE_MNG_PIXBUF_ITER (ygdk_mng_pixbuf_iter_get_type ())
+#define YGDK_MNG_PIXBUF_ITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGDK_TYPE_MNG_PIXBUF_ITER, YGdkMngPixbufIter))
+#define YGDK_MNG_PIXBUF_ITER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), YGDK_TYPE_MNG_PIXBUF_ITER, YGdkMngPixbufIterClass))
+#define YGDK_IS_MNG_PIXBUF_ITER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), YGDK_TYPE_MNG_PIXBUF_ITER))
+#define YGDK_MNG_PIXBUF_ITER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), YGDK_TYPE_MNG_PIXBUF_ITER, YGdkMngPixbufIterClass))
+
+typedef struct YGdkMngPixbufIter {
+ GdkPixbufAnimationIter parent;
+
+ // private:
+ YGdkMngPixbuf *mng_pixbuf;
+ int cur_frame, cur_iteration;
+} YGdkMngPixbufIter;
+
+typedef struct YGdkMngPixbufIterClass {
+ GdkPixbufAnimationIterClass parent_class;
+} YGdkMngPixbufIterClass;
+
+GType ygdk_mng_pixbuf_iter_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+#endif /*YGDK_MNG_PIXBUF_H*/
+
Added: trunk/gtk/src/ygtkbargraph.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkbargraph.c?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkbargraph.c (added)
+++ trunk/gtk/src/ygtkbargraph.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,196 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkBarGraph widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkbargraph.h"
+#include <gtk/gtklabel.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkeventbox.h>
+
+G_DEFINE_TYPE (YGtkBarGraph, ygtk_bar_graph, YGTK_TYPE_RATIO_HBOX)
+
+static void ygtk_bar_graph_init (YGtkBarGraph *bar)
+{
+// ygtk_ratio_box_set_homogeneous (YGTK_RATIO_BOX (bar), TRUE);
+
+ bar->m_tooltips = gtk_tooltips_new();
+ gtk_container_set_border_width (GTK_CONTAINER (bar), 12);
+}
+
+/* Just to avoid the size getting too big, when we have little bars. */
+static void ygtk_bar_graph_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ GTK_WIDGET_CLASS (ygtk_bar_graph_parent_class)->size_request (widget, requisition);
+ const int max_width = 250;
+ if (requisition->width > max_width)
+ requisition->width = max_width;
+ requisition->height += 6;
+}
+
+GtkWidget *ygtk_bar_graph_new (void)
+{
+ return g_object_new (YGTK_TYPE_BAR_GRAPH, NULL);
+}
+
+void ygtk_bar_graph_create_entries (YGtkBarGraph *bar, guint entries)
+{
+ // Remove the ones in excess
+ guint i;
+ for (i = entries; i < g_list_length (YGTK_RATIO_BOX (bar)->children); i++)
+ gtk_container_remove (GTK_CONTAINER (bar),
+ (GtkWidget*) g_list_nth_data (YGTK_RATIO_BOX (bar)->children, i));
+
+ // Add new ones, if missing
+ for (i = g_list_length (YGTK_RATIO_BOX (bar)->children); i < entries; i++) {
+ GtkWidget *label = ygtk_colored_label_new();
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+
+ YGtkColoredLabel *color_label = YGTK_COLORED_LABEL (label);
+ ygtk_colored_label_set_shadow_type (color_label, GTK_SHADOW_OUT);
+
+ // we need a GtkEventBox or something, so we may assign a tooltip to it
+ GtkWidget *box = gtk_event_box_new();
+ gtk_container_add (GTK_CONTAINER (box), label);
+ gtk_container_add (GTK_CONTAINER (bar), box);
+
+ gtk_widget_show_all (box);
+ }
+}
+
+void ygtk_bar_graph_setup_entry (YGtkBarGraph *bar, int index,
+ const gchar *label_entry, int value)
+{
+ YGtkRatioBoxChild *box_child = (YGtkRatioBoxChild *)
+ g_list_nth_data (YGTK_RATIO_BOX (bar)->children, index);
+
+ g_return_if_fail (box_child);
+ GtkWidget *box = box_child->widget;
+ GtkWidget *label = gtk_bin_get_child (GTK_BIN (box));
+
+ if (value < 0)
+ value = 0;
+
+ // Reading label text
+ if (label_entry) {
+ GString *label_text = g_string_new (label_entry);
+ { // Replace %1 by value(i)
+ guint i;
+ for (i = 0; i < label_text->len; i++)
+ if (label_text->str[i] == '%' && label_text->str[i+1] == '1') {
+ gchar *value_str = g_strdup_printf ("%d", value);
+ label_text = g_string_erase (label_text, i, 2);
+ label_text = g_string_insert (label_text, i, value_str);
+ g_free (value_str);
+ }
+ }
+ gtk_label_set_label (GTK_LABEL (label), label_text->str);
+
+ // Tooltip with the label -- useful if the bar entry gets too small
+ gtk_tooltips_set_tip (bar->m_tooltips, box, label_text->str, NULL);
+ }
+
+ // Set proportion
+ gtk_widget_set_size_request (box, 10, -1); // for homogeneous...
+ ygtk_ratio_box_set_child_packing (YGTK_RATIO_BOX (bar), box, MAX (value, 1),
+ TRUE, TRUE, 0);
+
+ // Set background color
+ // The Tango palette
+ const guint palette [][3] = {
+ { 138, 226, 52 }, // Chameleon 1
+ { 252, 175, 62 }, // Orange 1
+ { 114, 159, 207 }, // Sky Blue 1
+ { 233, 185, 110 }, // Chocolate 1
+ { 239, 41, 41 }, // Scarlet Red 1
+ { 252, 233, 79 }, // Butter 1
+ { 173, 127, 168 }, // Plum 1
+ { 115, 210, 22 }, // Chameleon 2
+ { 245, 121, 0 }, // Orange 2
+ { 52, 101, 164 }, // Sky Blue 2
+ { 193, 125, 17 }, // Chocolate 2
+ { 204, 0, 0 }, // Scarlet Red 2
+ { 237, 212, 0 }, // Butter 2
+ { 117, 80, 123 }, // Plum 2
+ { 78, 154, 6 }, // Chameleon 3
+ { 206, 92, 0 }, // Orange 3
+ { 32, 74, 135 }, // Sky Blue 3
+ { 143, 89, 2 }, // Chocolate 3
+ { 164, 0, 0 }, // Scarlet Red 3
+ { 196, 160, 0 }, // Butter 3
+ { 92, 53, 102 }, // Plum 3
+ { 238, 238, 236 }, // Aluminium 1
+ { 211, 215, 207 }, // Aluminium 2
+ { 186, 189, 182 }, // Aluminium 3
+ { 136, 138, 133 }, // Aluminium 4
+ { 85, 87, 83 }, // Aluminium 5
+ { 46, 52, 54 }, // Aluminium 6
+ };
+
+ const guint *color = palette [index % G_N_ELEMENTS (palette)];
+
+ YGtkColoredLabel *color_label = YGTK_COLORED_LABEL (label);
+ ygtk_colored_label_set_background (color_label, color[0], color[1], color[2]);
+}
+
+static void ygtk_bar_graph_class_init (YGtkBarGraphClass *klass)
+{
+ ygtk_bar_graph_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->size_request = ygtk_bar_graph_size_request;
+}
+
+//** YGtkColoredLabel
+
+G_DEFINE_TYPE (YGtkColoredLabel, ygtk_colored_label, GTK_TYPE_LABEL)
+
+static void ygtk_colored_label_init (YGtkColoredLabel *label)
+{
+ label->shadow = GTK_SHADOW_NONE;
+}
+
+static gboolean ygtk_colored_label_expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ GtkStyle *style = gtk_widget_get_style (widget);
+ GtkAllocation *alloc = &widget->allocation;
+ gtk_paint_box (style, widget->window, GTK_STATE_NORMAL,
+ YGTK_COLORED_LABEL (widget)->shadow, &event->area,
+ widget, NULL, alloc->x, alloc->y, alloc->width, alloc->height);
+
+ GTK_WIDGET_CLASS (ygtk_colored_label_parent_class)->expose_event (widget, event);
+ return FALSE;
+}
+
+GtkWidget *ygtk_colored_label_new (void)
+{ return g_object_new (YGTK_TYPE_COLORED_LABEL, NULL); }
+
+void ygtk_colored_label_set_foreground (YGtkColoredLabel *label, guint red,
+ guint green, guint blue)
+{
+ GdkColor color = { 0, red << 8, green << 8, blue << 8 };
+ gtk_widget_modify_fg (GTK_WIDGET (label), GTK_STATE_NORMAL, &color);
+}
+
+void ygtk_colored_label_set_background (YGtkColoredLabel *label, guint red,
+ guint green, guint blue)
+{
+ GdkColor color = { 0, red << 8, green << 8, blue << 8 };
+ gtk_widget_modify_bg (GTK_WIDGET (label), GTK_STATE_NORMAL, &color);
+}
+
+void ygtk_colored_label_set_shadow_type (YGtkColoredLabel *label, GtkShadowType type)
+{
+ label->shadow = type;
+}
+
+static void ygtk_colored_label_class_init (YGtkColoredLabelClass *klass)
+{
+ ygtk_colored_label_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->expose_event = ygtk_colored_label_expose_event;
+}
Added: trunk/gtk/src/ygtkbargraph.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkbargraph.h?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkbargraph.h (added)
+++ trunk/gtk/src/ygtkbargraph.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,101 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkBarGraph is just a simple graph of bars that may be
+ changed during run-time (see ygtk_bar_graph_setup_entry()).
+*/
+
+#ifndef YGTK_BAR_GRAPH_H
+#define YGTK_BAR_GRAPH_H
+
+#include "ygtkratiobox.h"
+#include <gtk/gtktooltips.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_BAR_GRAPH (ygtk_bar_graph_get_type ())
+#define YGTK_BAR_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_BAR_GRAPH, YGtkBarGraph))
+#define YGTK_BAR_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_BAR_GRAPH, YGtkBarGraphClass))
+#define YGTK_IS_BAR_GRAPH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_BAR_GRAPH))
+#define YGTK_IS_BAR_GRAPH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_BAR_GRAPH))
+#define YGTK_BAR_GRAPH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_BAR_GRAPH, YGtkBarGraphClass))
+
+typedef struct _YGtkBarGraph YGtkBarGraph;
+typedef struct _YGtkBarGraphClass YGtkBarGraphClass;
+
+struct _YGtkBarGraph
+{
+ YGtkRatioHBox parent;
+
+ // private
+ GtkTooltips *m_tooltips;
+};
+
+struct _YGtkBarGraphClass
+{
+ YGtkRatioBoxClass parent_class;
+};
+
+GtkWidget *ygtk_bar_graph_new (void);
+GType ygtk_bar_graph_get_type (void) G_GNUC_CONST;
+
+void ygtk_bar_graph_create_entries (YGtkBarGraph *bar, guint entries);
+void ygtk_bar_graph_setup_entry (YGtkBarGraph *bar, int index,
+ const gchar *label_entry, int value);
+
+G_END_DECLS
+#endif /*YGTK_BAR_GRAPH_H*/
+
+#ifndef YGTK_COLORED_LABEL_H
+#define YGTK_COLORED_LABEL_H
+
+#include <gtk/gtklabel.h>
+G_BEGIN_DECLS
+
+/* YGtkColoredLabel is a GtkLabel where gtk_modify_bg() can be used. It also
+ allows a frame around it. */
+
+#define YGTK_TYPE_COLORED_LABEL (ygtk_colored_label_get_type ())
+#define YGTK_COLORED_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_COLORED_LABEL, YGtkColoredLabel))
+#define YGTK_COLORED_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_COLORED_LABEL, YGtkColoredLabelClass))
+#define YGTK_IS_COLORED_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_COLORED_LABEL))
+#define YGTK_IS_COLORED_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_COLORED_LABEL))
+#define YGTK_COLORED_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_COLORED_LABEL, YGtkColoredLabelClass))
+
+typedef struct _YGtkColoredLabel
+{
+ GtkLabel parent;
+
+ // private
+ GtkShadowType shadow;
+} YGtkColoredLabel;
+
+typedef struct _YGtkColoredLabelClass
+{
+ GtkLabelClass parent_class;
+} YGtkColoredLabelClass;
+
+GtkWidget *ygtk_colored_label_new (void);
+GType ygtk_colored_label_get_type (void) G_GNUC_CONST;
+
+// A convenience function (you may use gtk_widget_modify_fg() and
+// gtk_widget_modify_bg() instead), where colors range is [0, 255]
+void ygtk_colored_label_set_foreground (YGtkColoredLabel *label, guint red,
+ guint green, guint blue);
+void ygtk_colored_label_set_background (YGtkColoredLabel *label, guint red,
+ guint green, guint blue);
+
+void ygtk_colored_label_set_shadow_type (YGtkColoredLabel *label, GtkShadowType type);
+
+G_END_DECLS
+#endif /*YGTK_COLORED_LABEL*/
Added: trunk/gtk/src/ygtkcellrendererarrow.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkcellrendererarrow.c?…
==============================================================================
--- trunk/gtk/src/ygtkcellrendererarrow.c (added)
+++ trunk/gtk/src/ygtkcellrendererarrow.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,260 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkCellRendererArrow widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkcellrendererarrow.h"
+
+#define ARROW_WIDTH 18
+#define ARROW_HEIGHT 14
+
+enum {
+ PROP_0,
+ PROP_CAN_GO_UP,
+ PROP_CAN_GO_DOWN
+};
+
+static guint pressed_signal;
+// VOID:UINT, STRING marshal
+static void ygtk_marshal_VOID__UINT_STRING (GClosure *closure, GValue *return_value,
+ guint n_param_values, const GValue *param_values, gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__UINT_STRING) (gpointer data1, guint arg_1,
+ gpointer arg_2, gpointer data2);
+ register GMarshalFunc_VOID__UINT_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__UINT_STRING) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, g_value_get_uint (param_values + 1),
+ (char*) g_value_get_string (param_values + 2), data2);
+}
+
+G_DEFINE_TYPE (YGtkCellRendererArrow, ygtk_cell_renderer_arrow, GTK_TYPE_CELL_RENDERER)
+
+static void ygtk_cell_renderer_arrow_init (YGtkCellRendererArrow *cell_arrow)
+{
+ GTK_CELL_RENDERER (cell_arrow)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
+ GTK_CELL_RENDERER (cell_arrow)->xalign = 0.0;
+ GTK_CELL_RENDERER (cell_arrow)->yalign = 0.5;
+ GTK_CELL_RENDERER (cell_arrow)->xpad = 0;
+ GTK_CELL_RENDERER (cell_arrow)->ypad = 0;
+
+ cell_arrow->can_go_up = cell_arrow->can_go_down = TRUE;
+}
+
+static void ygtk_cell_renderer_arrow_get_property (GObject *object,
+ guint param_id, GValue *value, GParamSpec *pspec)
+{
+ YGtkCellRendererArrow *cell_arrow = YGTK_CELL_RENDERER_ARROW (object);
+ switch (param_id) {
+ case PROP_CAN_GO_UP:
+ g_value_set_boolean (value, cell_arrow->can_go_up);
+ break;
+ case PROP_CAN_GO_DOWN:
+ g_value_set_boolean (value, cell_arrow->can_go_down);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void ygtk_cell_renderer_arrow_set_property (GObject *object,
+ guint param_id, const GValue *value, GParamSpec *pspec)
+{
+ YGtkCellRendererArrow *cell_arrow = YGTK_CELL_RENDERER_ARROW (object);
+ switch (param_id) {
+ case PROP_CAN_GO_UP:
+ cell_arrow->can_go_up = g_value_get_boolean (value);
+ break;
+ case PROP_CAN_GO_DOWN:
+ cell_arrow->can_go_down = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void ygtk_cell_renderer_arrow_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget, GdkRectangle *cell_area, gint *x_offset, gint *y_offset,
+ gint *width, gint *height)
+{
+ int w, h;
+ w = cell->xpad*2 + ARROW_WIDTH;
+ h = cell->ypad*2 + ARROW_HEIGHT*2 + 8;
+
+ if (width)
+ *width = w;
+ if (height)
+ *height = h;
+
+ if (x_offset)
+ *x_offset = MAX (cell->xalign * (cell_area->width - w), 0);
+ if (y_offset)
+ *y_offset = MAX (cell->yalign * (cell_area->height - h), 0);
+}
+
+static void draw_arrow (GdkWindow *window, GtkArrowType arrow, GdkColor *color,
+ GdkRectangle *area, gint x, gint y, gint width, gint height)
+{
+ /* Adapted from gtkstyle.c. We should avoid using gtk_style_paint_arrow(),
+ since some styles may draw weird arrows. It would also not be nice to
+ specify colors. And we may want to improve the arrow. */
+
+ cairo_t *cr = gdk_cairo_create (window);
+ gdk_cairo_set_source_color (cr, color);
+
+ if (area) {
+ gdk_cairo_rectangle (cr, area);
+ cairo_clip (cr);
+ }
+
+ if (arrow == GTK_ARROW_DOWN) {
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x + width, y);
+ cairo_line_to (cr, x + width / 2, y + height);
+ }
+ else /*if (arrow_type == GTK_ARROW_UP)*/ {
+ cairo_move_to (cr, x, y + height);
+ cairo_line_to (cr, x + width / 2, y);
+ cairo_line_to (cr, x + width, y + height);
+ }
+
+ cairo_close_path (cr);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+}
+
+static void ygtk_cell_renderer_arrow_render (GtkCellRenderer *cell,
+ GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area,
+ GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags)
+{
+ YGtkCellRendererArrow *cell_arrow = YGTK_CELL_RENDERER_ARROW (cell);
+ int x, y, w = ARROW_WIDTH, h = ARROW_HEIGHT;
+ ygtk_cell_renderer_arrow_get_size (cell, widget, cell_area, &x, &y, NULL, NULL);
+ x += cell_area->x;
+ y += cell_area->y;
+
+ static GdkColor grey = { 0, 225 << 8, 225 << 8, 225 << 8 };
+
+ // a bit ugly, but let's use a cycle here to avoid calling a function
+ int i;
+ GtkArrowType arrow = GTK_ARROW_UP;
+ // doesn't seem to be a way to see if the arrow is being pressed or hovered
+ gboolean cell_selected = flags & GTK_CELL_RENDERER_SELECTED;
+ gboolean sensitive;
+ for (i = 0; i < 2; i++) {
+ sensitive = cell->sensitive &&
+ (i == 0 ? cell_arrow->can_go_up : cell_arrow->can_go_down);
+
+ if (!sensitive) {
+ if (!cell_selected)
+ draw_arrow (window, arrow, &grey, expose_area, x, y, w, h);
+ }
+ else { // normal
+ if (cell_selected) {
+ GdkColor *color = &widget->style->fg [GTK_STATE_SELECTED];
+ draw_arrow (window, arrow, color, expose_area, x, y, w, h);
+ }
+ else {
+ GdkColor *color = &widget->style->bg [GTK_STATE_SELECTED];
+ draw_arrow (window, arrow, color, expose_area, x, y, w, h);
+ }
+ }
+
+ y += h + 4;
+ arrow = GTK_ARROW_DOWN;
+ }
+}
+
+static gboolean
+point_under_arrow (YGtkCellRendererArrow *cell_arrow,
+ GdkRectangle *cell_area, gint x, gint y,
+ GtkArrowType *arrow)
+{
+ x -= cell_area->x;
+ y -= cell_area->y;
+
+ int cx, cy, cw, ch;
+ ygtk_cell_renderer_arrow_get_size (GTK_CELL_RENDERER (cell_arrow), NULL,
+ cell_area, &cx, &cy, &cw, &ch);
+
+ if (x >= cx && x <= cx + cw && y >= cy && y <= cy + ch) {
+ if (cell_arrow->can_go_up && y <= ARROW_HEIGHT) {
+ *arrow = GTK_ARROW_UP;
+ return TRUE;
+ }
+ else if (cell_arrow->can_go_down && y >= ARROW_HEIGHT+8) {
+ *arrow = GTK_ARROW_DOWN;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean ygtk_cell_renderer_arrow_activate (GtkCellRenderer *cell,
+ GdkEvent *event, GtkWidget *widget, const gchar *path,
+ GdkRectangle *background_area, GdkRectangle *cell_area, GtkCellRendererState flags)
+{
+ YGtkCellRendererArrow *cell_arrow = YGTK_CELL_RENDERER_ARROW (cell);
+ if (event->type == GDK_BUTTON_PRESS) {
+ GtkArrowType arrow;
+ if (point_under_arrow (cell_arrow, cell_area,
+ event->button.x, event->button.y,
+ &arrow))
+ {
+ g_signal_emit (cell, pressed_signal, 0, arrow, path);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+GtkCellRenderer *ygtk_cell_renderer_arrow_new (void)
+{
+ return g_object_new (YGTK_TYPE_CELL_RENDERER_ARROW, NULL);
+}
+
+static void ygtk_cell_renderer_arrow_class_init (YGtkCellRendererArrowClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+
+ object_class->get_property = ygtk_cell_renderer_arrow_get_property;
+ object_class->set_property = ygtk_cell_renderer_arrow_set_property;
+
+ cell_class->get_size = ygtk_cell_renderer_arrow_get_size;
+ cell_class->render = ygtk_cell_renderer_arrow_render;
+ cell_class->activate = ygtk_cell_renderer_arrow_activate;
+
+ g_object_class_install_property (object_class, PROP_CAN_GO_UP,
+ g_param_spec_boolean ("can-go-up", "Can Go Up",
+ "Whether the up arrow can be pressed", TRUE,
+ G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (object_class, PROP_CAN_GO_DOWN,
+ g_param_spec_boolean ("can-go-down", "Can Go Down",
+ "Whether the down arrow can be pressed", TRUE,
+ G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+
+ /* signal sent when an arrow is pressed */
+ pressed_signal = g_signal_new ("pressed", G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (YGtkCellRendererArrowClass, pressed),
+ NULL, NULL, ygtk_marshal_VOID__UINT_STRING, G_TYPE_NONE, 2,
+ G_TYPE_UINT, G_TYPE_STRING);
+}
Added: trunk/gtk/src/ygtkcellrendererarrow.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkcellrendererarrow.h?…
==============================================================================
--- trunk/gtk/src/ygtkcellrendererarrow.h (added)
+++ trunk/gtk/src/ygtkcellrendererarrow.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,50 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkCellRendererArrow can be used as a light replacement for the
+ GtkCellRenderCombo or GtkCellRendererSpin. It renders two arrows
+ in the cell. If the user presses one of them, the program gets
+ the signal and does whatever it likes. One can hide one, or both,
+ of the arrows through the can-go-up and can-go-down proprieties.
+*/
+
+#ifndef YGTK_CELL_RENDERER_ARROW_H
+#define YGTK_CELL_RENDERER_ARROW_H
+
+#include <gtk/gtkcellrenderer.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_CELL_RENDERER_ARROW (ygtk_cell_renderer_arrow_get_type ())
+#define YGTK_CELL_RENDERER_ARROW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_CELL_RENDERER_ARROW, YGtkCellRendererArrow))
+#define YGTK_CELL_RENDERER_ARROW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_CELL_RENDERER_ARROW, YGtkCellRendererArrowClass))
+#define YGTK_IS_CELL_RENDERER_ARROW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_CELL_RENDERER_ARROW))
+#define YGTK_IS_CELL_RENDERER_ARROW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_CELL_RENDERER_ARROW))
+#define YGTK_CELL_RENDERER_ARROW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_CELL_RENDERER_ARROW, YGtkCellRendererArrowClass))
+
+typedef struct _YGtkCellRendererArrow
+{
+ GtkCellRenderer parent;
+
+ // private:
+ guint can_go_up : 1;
+ guint can_go_down : 1;
+} YGtkCellRendererArrow;
+
+typedef struct _YGtkCellRendererArrowClass
+{
+ GtkCellRendererClass parent_class;
+ // signals:
+ void (* pressed) (guint arrow_type, const gchar *path);
+} YGtkCellRendererArrowClass;
+
+GtkCellRenderer *ygtk_cell_renderer_arrow_new (void);
+GType ygtk_cell_renderer_arrow_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+#endif /*YGTK_CELL_RENDERER_ARROW_H*/
Added: trunk/gtk/src/ygtkfieldentry.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkfieldentry.c?rev=425…
==============================================================================
--- trunk/gtk/src/ygtkfieldentry.c (added)
+++ trunk/gtk/src/ygtkfieldentry.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,222 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkFieldEntry widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkfieldentry.h"
+#include <gtk/gtk.h>
+#include <string.h>
+
+//** YGtkFilterEntry
+
+static void ygtk_filter_entry_editable_init (GtkEditableClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (YGtkFilterEntry, ygtk_filter_entry, GTK_TYPE_ENTRY,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, ygtk_filter_entry_editable_init))
+
+static void ygtk_filter_entry_init (YGtkFilterEntry *entry)
+{
+}
+
+static void ygtk_filter_entry_insert_text (GtkEditable *editable, const gchar *new_text,
+ gint new_text_length, gint *pos)
+{
+ const gchar *valid_chars = YGTK_FILTER_ENTRY (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
+ gdk_beep();
+ return;
+ }
+ }
+ }
+
+ GtkEditableClass *parent_editable_iface = g_type_interface_peek
+ (ygtk_filter_entry_parent_class, GTK_TYPE_EDITABLE);
+ parent_editable_iface->insert_text (editable, new_text, new_text_length, pos);
+}
+
+static void ygtk_filter_entry_destroy (GtkObject *object)
+{
+ YGtkFilterEntry *entry = YGTK_FILTER_ENTRY (object);
+ if (entry->valid_chars)
+ g_free (entry->valid_chars);
+ entry->valid_chars = NULL;
+
+ GTK_OBJECT_CLASS (ygtk_filter_entry_parent_class)->destroy (object);
+}
+
+GtkWidget *ygtk_filter_entry_new (void)
+{
+ return g_object_new (YGTK_TYPE_FILTER_ENTRY, NULL);
+}
+
+void ygtk_filter_entry_set_valid_chars (YGtkFilterEntry *entry, const gchar *valid_chars)
+{
+ if (entry->valid_chars)
+ g_free (entry->valid_chars);
+ entry->valid_chars = g_strdup (valid_chars);
+}
+
+static void ygtk_filter_entry_class_init (YGtkFilterEntryClass *klass)
+{
+ ygtk_filter_entry_parent_class = g_type_class_peek_parent (klass);
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_filter_entry_destroy;
+}
+
+static void ygtk_filter_entry_editable_init (GtkEditableClass *iface)
+{
+ iface->insert_text = ygtk_filter_entry_insert_text;
+}
+
+//** YGtkFieldEntry
+
+static guint filter_entry_signal;
+G_DEFINE_TYPE (YGtkFieldEntry, ygtk_field_entry, GTK_TYPE_HBOX)
+
+static void ygtk_field_entry_init (YGtkFieldEntry *entry)
+{
+ gtk_box_set_spacing (GTK_BOX (entry), 4);
+}
+
+static YGtkFilterEntry *ygtk_field_entry_focus_next_entry (YGtkFieldEntry *fields,
+ YGtkFilterEntry *current_entry,
+ gint side)
+{
+ GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
+ gint pos = g_list_index (children, current_entry);
+
+ YGtkFilterEntry *next_entry = g_list_nth_data (children, pos + (2 * side));
+ g_list_free (children);
+
+ if (next_entry)
+ gtk_widget_grab_focus (GTK_WIDGET (next_entry));
+ return next_entry;
+}
+
+// If max characters reached, jump to next field
+static void ygtk_field_entry_insert_text (GtkEditable *editable, const gchar *new_text,
+ gint new_text_length, gint *position, YGtkFieldEntry *fields)
+{
+ if (*position == gtk_entry_get_max_length (GTK_ENTRY (editable))) {
+ YGtkFilterEntry *next_entry = ygtk_field_entry_focus_next_entry (fields,
+ YGTK_FILTER_ENTRY (editable), 1);
+ if (next_entry) {
+ gint pos = 0;
+ gtk_editable_insert_text (GTK_EDITABLE (next_entry), new_text,
+ new_text_length, &pos);
+ gtk_editable_set_position (GTK_EDITABLE (next_entry), pos);
+
+ // it would not insert the text anyway, but to avoid the beep
+ g_signal_stop_emission_by_name (editable, "insert_text");
+ }
+ }
+}
+
+static void ygtk_field_entry_move_cursor (GtkEntry *entry, GtkMovementStep move,
+ gint count, gboolean selection, YGtkFieldEntry *fields)
+{
+ if (move == GTK_MOVEMENT_VISUAL_POSITIONS) {
+ if (count > 0)
+ ygtk_field_entry_focus_next_entry (fields, YGTK_FILTER_ENTRY (entry), 1);
+ else
+ ygtk_field_entry_focus_next_entry (fields, YGTK_FILTER_ENTRY (entry), -1);
+ }
+}
+
+static void ygtk_field_entry_entry_changed (GtkEditable *editable, YGtkFieldEntry *fields)
+{
+ GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
+ gint nb = g_list_index (children, YGTK_FILTER_ENTRY (editable)) / 2;
+ g_list_free (children);
+
+ g_signal_emit (fields, filter_entry_signal, 0, nb);
+}
+
+GtkWidget *ygtk_field_entry_new (void)
+{
+ return g_object_new (YGTK_TYPE_FIELD_ENTRY, NULL);
+}
+
+void ygtk_field_entry_add_field (YGtkFieldEntry *fields, gchar separator,
+ guint max_length, const gchar *valid_chars)
+{
+ GtkWidget *label = 0, *entry;
+ if (fields->use_separator) {
+ const gchar str[2] = { separator, '\0' };
+ label = gtk_label_new (str);
+ }
+ entry = ygtk_filter_entry_new();
+ gtk_entry_set_max_length (GTK_ENTRY (entry), max_length);
+ gtk_entry_set_width_chars (GTK_ENTRY (entry), (max_length == 0) ? -1 : max_length);
+ ygtk_filter_entry_set_valid_chars (YGTK_FILTER_ENTRY (entry), valid_chars);
+
+ g_signal_connect (G_OBJECT (entry), "insert-text",
+ G_CALLBACK (ygtk_field_entry_insert_text), fields);
+ g_signal_connect (G_OBJECT (entry), "move-cursor",
+ G_CALLBACK (ygtk_field_entry_move_cursor), fields);
+
+ g_signal_connect (G_OBJECT (entry), "changed",
+ G_CALLBACK (ygtk_field_entry_entry_changed), fields);
+
+ GtkBox *box = GTK_BOX (fields);
+ if (label)
+ gtk_box_pack_start (box, label, FALSE, FALSE, 0);
+ gtk_box_pack_start (box, entry, TRUE, TRUE, 0);
+
+ fields->use_separator = TRUE;
+}
+
+static YGtkFilterEntry *ygtk_field_entry_get_field (YGtkFieldEntry *fields, guint nb)
+{
+ YGtkFilterEntry *entry;
+
+ GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
+ entry = g_list_nth_data (children, nb * 2);
+ g_list_free (children);
+
+ return entry;
+}
+
+void ygtk_field_entry_set_field_text (YGtkFieldEntry *fields, guint nb, const gchar *text)
+{
+ YGtkFilterEntry *entry = ygtk_field_entry_get_field (fields, nb);
+ g_signal_handlers_block_by_func (entry,
+ (gpointer) ygtk_field_entry_entry_changed, fields);
+ g_signal_handlers_block_by_func (entry,
+ (gpointer) ygtk_field_entry_insert_text, fields);
+
+ gtk_entry_set_text (GTK_ENTRY (entry), text);
+
+ g_signal_handlers_unblock_by_func (entry,
+ (gpointer) ygtk_field_entry_entry_changed, fields);
+ g_signal_handlers_unblock_by_func (entry,
+ (gpointer) ygtk_field_entry_insert_text, fields);
+}
+
+const gchar *ygtk_field_entry_get_field_text (YGtkFieldEntry *fields, guint nb)
+{
+ YGtkFilterEntry *entry = ygtk_field_entry_get_field (fields, nb);
+ return gtk_entry_get_text (GTK_ENTRY (entry));
+}
+
+static void ygtk_field_entry_class_init (YGtkFieldEntryClass *klass)
+{
+ ygtk_field_entry_parent_class = g_type_class_peek_parent (klass);
+
+ filter_entry_signal = g_signal_new ("field_entry_changed",
+ G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (YGtkFieldEntryClass, filter_entry_changed),
+ NULL, NULL, gtk_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+}
Added: trunk/gtk/src/ygtkfieldentry.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkfieldentry.h?rev=425…
==============================================================================
--- trunk/gtk/src/ygtkfieldentry.h (added)
+++ trunk/gtk/src/ygtkfieldentry.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,102 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkFieldEntry is an extension of GtkEntry with the added
+ functionality of being able to define fields (useful for when
+ you need the user to set a IP address or time/date). The number
+ of fields, their individual range and separation character
+ is all customizable.
+
+ YGtkFilterEntry is an extension to GtkEntry that only accepts
+ input that is specified in an array of valid characters
+*/
+
+#ifndef YGTK_FILTER_ENTRY_H
+#define YGTK_FILTER_ENTRY_H
+
+#include <gtk/gtkentry.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_FILTER_ENTRY (ygtk_filter_entry_get_type ())
+#define YGTK_FILTER_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_FILTER_ENTRY, YGtkFilterEntry))
+#define YGTK_FILTER_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_FILTER_ENTRY, YGtkFilterEntryClass))
+#define YGTK_IS_FILTER_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_FILTER_ENTRY))
+#define YGTK_IS_FILTER_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_FILTER_ENTRY))
+#define YGTK_FILTER_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_FILTER_ENTRY, YGtkFilterEntryClass))
+
+typedef struct _YGtkFilterEntry
+{
+ GtkEntry parent;
+
+ // private:
+ gchar *valid_chars;
+} YGtkFilterEntry;
+
+typedef struct _YGtkFilterEntryClass
+{
+ GtkEntryClass parent_class;
+} YGtkFilterEntryClass;
+
+GtkWidget* ygtk_filter_entry_new (void);
+GType ygtk_filter_entry_get_type (void) G_GNUC_CONST;
+
+void ygtk_filter_entry_set_valid_chars (YGtkFilterEntry *entry,
+ const gchar *valid_chars);
+
+G_END_DECLS
+#endif /*YGTK_FILTER_ENTRY_H*/
+
+#ifndef YGTK_FIELD_ENTRY_H
+#define YGTK_FIELD_ENTRY_H
+
+#include <gtk/gtkhbox.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_FIELD_ENTRY (ygtk_field_entry_get_type ())
+#define YGTK_FIELD_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_FIELD_ENTRY, YGtkFieldEntry))
+#define YGTK_FIELD_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_FIELD_ENTRY, YGtkFieldEntryClass))
+#define IS_YGTK_FIELD_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_FIELD_ENTRY))
+#define IS_YGTK_FIELD_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_FIELD_ENTRY))
+#define YGTK_FIELD_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_FIELD_ENTRY, YGtkFieldEntryClass))
+
+typedef struct _YGtkFieldEntry
+{
+ GtkHBox parent;
+
+ // private:
+ // used to disable separator for the first field
+ gboolean use_separator;
+} YGtkFieldEntry;
+
+typedef struct _YGtkFieldEntryClass
+{
+ GtkHBoxClass parent_class;
+
+ void (* filter_entry_changed) (YGtkFieldEntry *entry, gint field_nb);
+} YGtkFieldEntryClass;
+
+GtkWidget* ygtk_field_entry_new (void);
+GType ygtk_field_entry_get_type (void) G_GNUC_CONST;
+
+// if this is the first field, separator will be ignored. max_length can be 0 to
+// disable it. valids_chars can be NULL to disable it.
+void ygtk_field_entry_add_field (YGtkFieldEntry *entry, gchar separator,
+ guint max_length, const gchar *valid_chars);
+
+// convinience
+void ygtk_field_entry_set_field_text (YGtkFieldEntry *entry, guint nb, const gchar *text);
+const gchar *ygtk_field_entry_get_field_text (YGtkFieldEntry *entry, guint nb);
+
+G_END_DECLS
+#endif /*YGTK_FIELD_ENTRY_H*/
Added: trunk/gtk/src/ygtkfindentry.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkfindentry.c?rev=4251…
==============================================================================
--- trunk/gtk/src/ygtkfindentry.c (added)
+++ trunk/gtk/src/ygtkfindentry.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,517 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkExtEntry widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkfindentry.h"
+#include <gtk/gtk.h>
+
+G_DEFINE_TYPE (YGtkExtEntry, ygtk_ext_entry, GTK_TYPE_ENTRY)
+
+static void ygtk_ext_entry_init (YGtkExtEntry *entry)
+{
+}
+
+static void ygtk_ext_entry_destroy (GtkObject *object)
+{
+ GTK_OBJECT_CLASS (ygtk_ext_entry_parent_class)->destroy (object);
+
+ YGtkExtEntry *entry = YGTK_EXT_ENTRY (object);
+ ygtk_ext_entry_set_border_window_size (entry, YGTK_EXT_ENTRY_LEFT_WIN, 0);
+ ygtk_ext_entry_set_border_window_size (entry, YGTK_EXT_ENTRY_RIGHT_WIN, 0);
+}
+
+static void ygtk_ext_entry_map (GtkWidget *widget)
+{
+ if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget)) {
+ GTK_WIDGET_CLASS (ygtk_ext_entry_parent_class)->map (widget);
+
+ YGtkExtEntry *entry = YGTK_EXT_ENTRY (widget);
+ if (entry->left_window)
+ gdk_window_show (entry->left_window);
+ if (entry->right_window)
+ gdk_window_show (entry->right_window);
+ }
+}
+
+static void ygtk_ext_entry_unmap (GtkWidget *widget)
+{
+ if (GTK_WIDGET_MAPPED (widget)) {
+ YGtkExtEntry *entry = YGTK_EXT_ENTRY (widget);
+ if (entry->left_window)
+ gdk_window_hide (entry->left_window);
+ if (entry->right_window)
+ gdk_window_hide (entry->right_window);
+
+ GTK_WIDGET_CLASS (ygtk_ext_entry_parent_class)->unmap (widget);
+ }
+}
+
+static void ygtk_ext_entry_sync_color (YGtkExtEntry *entry)
+{
+ /* We don't use gtk_style_set_background() since we want to reflect
+ gtk_widget_modify_base() color, if changed. */
+
+ GtkWidget *widget = GTK_WIDGET (entry);
+ GdkColor color = widget->style->base [GTK_STATE_NORMAL];
+ gdk_rgb_find_color (gtk_widget_get_colormap (widget), &color);
+
+ if (entry->left_window)
+ gdk_window_set_background (entry->left_window, &color);
+ if (entry->right_window)
+ gdk_window_set_background (entry->right_window, &color);
+}
+
+static void ygtk_ext_entry_style_set (GtkWidget *widget, GtkStyle *prev_style)
+{
+ GTK_WIDGET_CLASS (ygtk_ext_entry_parent_class)->style_set (widget, prev_style);
+ ygtk_ext_entry_sync_color (YGTK_EXT_ENTRY (widget));
+}
+
+GdkWindow *ygtk_ext_entry_get_window (YGtkExtEntry *entry,
+ YGtkExtEntryWindowType type)
+{
+ switch (type) {
+ case YGTK_EXT_ENTRY_WIDGET_WIN:
+ return gtk_widget_get_parent_window (GTK_WIDGET (entry));
+ case YGTK_EXT_ENTRY_TEXT_WIN:
+ return GTK_ENTRY (entry)->text_area;
+ case YGTK_EXT_ENTRY_LEFT_WIN:
+ return entry->left_window;
+ case YGTK_EXT_ENTRY_RIGHT_WIN:
+ return entry->right_window;
+ }
+ return NULL;
+}
+
+void ygtk_ext_entry_set_border_window_size (YGtkExtEntry *entry,
+ YGtkExtEntryWindowType type, gint size)
+{
+ GtkWidget *widget = GTK_WIDGET (entry);
+ g_return_if_fail (type == YGTK_EXT_ENTRY_LEFT_WIN || type == YGTK_EXT_ENTRY_RIGHT_WIN);
+
+ GdkWindow **window;
+ if (type == YGTK_EXT_ENTRY_LEFT_WIN)
+ window = &entry->left_window;
+ else
+ window = &entry->right_window;
+
+ if (size) {
+ if (!*window) {
+ // must be realized to create a window
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK
+ | GDK_ENTER_NOTIFY_MASK | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ // this will be tuned on size_allocate
+ if (type == YGTK_EXT_ENTRY_LEFT_WIN)
+ attributes.x = 0;
+ else
+ attributes.x = widget->allocation.width - size;
+ attributes.y = widget->allocation.y;
+ attributes.width = size;
+ attributes.height = widget->allocation.height;
+
+ *window = gdk_window_new (widget->window,
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (*window, widget);
+ // set background style
+ ygtk_ext_entry_sync_color (entry);
+
+ if (GTK_WIDGET_MAPPED (widget))
+ gdk_window_show (*window);
+ gtk_widget_queue_resize (widget);
+ }
+ else {
+ gint width, height;
+ gdk_drawable_get_size (GDK_DRAWABLE (*window), &width, &height);
+ if (width != size) {
+ gdk_window_resize (*window, size, height);
+ gtk_widget_queue_resize (widget);
+ }
+ }
+ }
+ else { // remove the window
+ if (*window) {
+ gdk_window_set_user_data (*window, NULL);
+ gdk_window_destroy (*window);
+ *window = NULL;
+ gtk_widget_queue_resize (widget);
+ }
+ }
+}
+
+gint ygtk_ext_entry_get_border_window_size (YGtkExtEntry *entry,
+ YGtkExtEntryWindowType type)
+{
+ g_return_val_if_fail (type == YGTK_EXT_ENTRY_LEFT_WIN || type == YGTK_EXT_ENTRY_RIGHT_WIN, 0);
+ GdkWindow *window = ygtk_ext_entry_get_window (entry, type);
+ gint size = 0;
+ if (window && gdk_window_is_visible (window))
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &size, NULL);
+ return size;
+}
+
+static void ygtk_ext_entry_size_request (GtkWidget *widget, GtkRequisition *req)
+{
+ GTK_WIDGET_CLASS (ygtk_ext_entry_parent_class)->size_request (widget, req);
+
+ YGtkExtEntry *entry = YGTK_EXT_ENTRY (widget);
+ req->width += ygtk_ext_entry_get_border_window_size (entry,
+ YGTK_EXT_ENTRY_LEFT_WIN);
+ req->width += ygtk_ext_entry_get_border_window_size (entry,
+ YGTK_EXT_ENTRY_RIGHT_WIN);
+}
+
+static void ygtk_ext_entry_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GTK_WIDGET_CLASS (ygtk_ext_entry_parent_class)->size_allocate
+ (widget, allocation);
+ if (!GTK_WIDGET_REALIZED (widget))
+ return;
+
+ YGtkExtEntry *entry = YGTK_EXT_ENTRY (widget);
+ gint left_border, right_border;
+ left_border = ygtk_ext_entry_get_border_window_size (entry,
+ YGTK_EXT_ENTRY_LEFT_WIN);
+ right_border = ygtk_ext_entry_get_border_window_size (entry,
+ YGTK_EXT_ENTRY_RIGHT_WIN);
+
+ GdkWindow *window;
+ gint _x, _y, _w, _h, x, w;
+
+ // text window
+ window = ygtk_ext_entry_get_window (entry, YGTK_EXT_ENTRY_TEXT_WIN);
+ gdk_window_get_geometry (window, &_x, &_y, &_w, &_h, NULL);
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+ x = _x + left_border;
+ else
+ x = _x + right_border;
+ w = _w - (left_border + right_border);
+ gdk_window_move_resize (window, x, _y, w, _h);
+
+ // left window
+ window = ygtk_ext_entry_get_window (entry, YGTK_EXT_ENTRY_LEFT_WIN);
+ if (window && gdk_window_is_visible (window)) {
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+ x = _x;
+ else
+ x = _x + _w - left_border;
+ w = left_border;
+ gdk_window_move_resize (window, x, _y, w, _h);
+ }
+
+ // right window
+ window = ygtk_ext_entry_get_window (entry, YGTK_EXT_ENTRY_RIGHT_WIN);
+ if (window && gdk_window_is_visible (window)) {
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+ x = _x + _w - right_border;
+ else
+ x = _x;
+ w = right_border;
+ gdk_window_move_resize (window, x, _y, w, _h);
+ }
+}
+
+GtkWidget *ygtk_ext_entry_new (void)
+{
+ return g_object_new (YGTK_TYPE_EXT_ENTRY, NULL);
+}
+
+static void ygtk_ext_entry_class_init (YGtkExtEntryClass *klass)
+{
+ GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->map = ygtk_ext_entry_map;
+ gtkwidget_class->unmap = ygtk_ext_entry_unmap;
+ gtkwidget_class->style_set = ygtk_ext_entry_style_set;
+ gtkwidget_class->size_request = ygtk_ext_entry_size_request;
+ gtkwidget_class->size_allocate = ygtk_ext_entry_size_allocate;
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_ext_entry_destroy;
+}
+
+/* YGtkFindEntry widget */
+// check the header file for information about this widget
+
+#include <string.h>
+#define ARROW_SIZE 7
+
+static void ygtk_find_entry_editable_init (GtkEditableClass *iface);
+
+G_DEFINE_TYPE_WITH_CODE (YGtkFindEntry, ygtk_find_entry, YGTK_TYPE_EXT_ENTRY,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, ygtk_find_entry_editable_init))
+
+static void ygtk_find_entry_init (YGtkFindEntry *entry)
+{
+}
+
+static void ygtk_find_entry_destroy (GtkObject *object)
+{
+ GTK_OBJECT_CLASS (ygtk_find_entry_parent_class)->destroy (object);
+
+ YGtkFindEntry *entry = YGTK_FIND_ENTRY (object);
+
+#define DESTROY_ICON(icon) \
+ if (icon) { g_object_unref (G_OBJECT (icon)); icon = NULL; }
+
+ DESTROY_ICON (entry->find_icon)
+ DESTROY_ICON (entry->find_hover_icon)
+ DESTROY_ICON (entry->clear_icon)
+ DESTROY_ICON (entry->clear_hover_icon)
+#undef DESTROY_ICON
+}
+
+// Code from Banshee: shades a pixbuf a bit, used to provide the hover effect
+static inline guchar pixel_clamp (int val)
+{ return MAX (0, MIN (255, val)); }
+static GdkPixbuf *pixbuf_color_shift (const GdkPixbuf *src, int shift)
+{
+ if (!src)
+ return NULL;
+
+ 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++) + shift);
+ *(dest_pixels++) = pixel_clamp (*(src_pixels++) + shift);
+ *(dest_pixels++) = pixel_clamp (*(src_pixels++) + shift);
+ if (has_alpha)
+ *(dest_pixels++) = *(src_pixels++);
+ }
+ }
+ return dest;
+}
+
+static void ygtk_find_entry_set_borders (YGtkFindEntry *entry)
+{
+ YGtkExtEntry *eentry = YGTK_EXT_ENTRY (entry);
+ int left_border = 0, right_border = 0;
+ if (entry->find_icon) {
+ left_border = gdk_pixbuf_get_width (entry->find_icon) + 2;
+ if (entry->context_menu)
+ left_border += ARROW_SIZE - 1;
+ }
+ if (entry->clear_icon)
+ right_border = gdk_pixbuf_get_width (entry->clear_icon) + 2;
+
+ ygtk_ext_entry_set_border_window_size (eentry,
+ YGTK_EXT_ENTRY_LEFT_WIN, left_border);
+ ygtk_ext_entry_set_border_window_size (eentry,
+ YGTK_EXT_ENTRY_RIGHT_WIN, right_border);
+ gtk_widget_queue_resize (GTK_WIDGET (entry));
+}
+
+static void ygtk_find_entry_realize (GtkWidget *widget)
+{
+ GTK_WIDGET_CLASS (ygtk_find_entry_parent_class)->realize (widget);
+
+ YGtkExtEntry *eentry = YGTK_EXT_ENTRY (widget);
+ YGtkFindEntry *fentry = YGTK_FIND_ENTRY (widget);
+ fentry->find_icon = gtk_widget_render_icon (widget, GTK_STOCK_FIND,
+ GTK_ICON_SIZE_MENU, NULL);
+ fentry->clear_icon = gtk_widget_render_icon (widget, GTK_STOCK_CLEAR,
+ GTK_ICON_SIZE_MENU, NULL);
+
+ fentry->find_hover_icon = pixbuf_color_shift (fentry->find_icon, 30);
+ fentry->clear_hover_icon = pixbuf_color_shift (fentry->clear_icon, 30);
+
+ ygtk_find_entry_set_borders (fentry);
+
+ GdkDisplay *display = gtk_widget_get_display (widget);
+ GdkCursor *cursor = gdk_cursor_new_for_display (display, GDK_HAND1);
+
+ gdk_window_set_cursor (eentry->left_window, cursor);
+ gdk_window_set_cursor (eentry->right_window, cursor);
+ gdk_cursor_unref (cursor);
+}
+
+static void ygtk_find_entry_map (GtkWidget *widget)
+{
+ if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget)) {
+ GTK_WIDGET_CLASS (ygtk_find_entry_parent_class)->map (widget);
+ // only show clear icon when the entry has text
+ GdkWindow *clear_win = YGTK_EXT_ENTRY (widget)->right_window;
+ if (clear_win)
+ gdk_window_hide (clear_win);
+ }
+}
+
+static gboolean ygtk_find_entry_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+ YGtkExtEntry *eentry = YGTK_EXT_ENTRY (widget);
+ YGtkFindEntry *fentry = YGTK_FIND_ENTRY (widget);
+
+ GdkWindow *hover_window = gdk_display_get_window_at_pointer (
+ gtk_widget_get_display (widget), NULL, NULL);
+
+ if (event->window == eentry->left_window ||
+ event->window == eentry->right_window) {
+ gboolean hover = hover_window == event->window;
+ GdkPixbuf *pixbuf;
+ if (event->window == eentry->left_window)
+ pixbuf = hover ? fentry->find_hover_icon : fentry->find_icon;
+ else
+ pixbuf = hover ? fentry->clear_hover_icon : fentry->clear_icon;
+
+ int pix_height = gdk_pixbuf_get_height (pixbuf), win_width, win_height, y;
+ gdk_drawable_get_size (event->window, &win_width, &win_height);
+ y = (win_height - pix_height) / 2;
+
+ gdk_draw_pixbuf (event->window, widget->style->fg_gc[0], pixbuf,
+ 0, 0, 1, y, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
+
+ if (fentry->context_menu && event->window == eentry->left_window)
+ gtk_paint_arrow (widget->style, event->window, GTK_STATE_NORMAL,
+ GTK_SHADOW_NONE, &event->area, widget, NULL,
+ GTK_ARROW_DOWN, FALSE,
+ win_width - ARROW_SIZE - 1, win_height - ARROW_SIZE,
+ ARROW_SIZE, ARROW_SIZE);
+ }
+ else
+ GTK_WIDGET_CLASS (ygtk_find_entry_parent_class)->expose_event (widget, event);
+ return TRUE;
+}
+
+/* Re-draw find/clear windows on mouse hover. */
+static gboolean ygtk_find_entry_enter_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ if (widget == gtk_get_event_widget ((GdkEvent*) event)) {
+ YGtkExtEntry *eentry = YGTK_EXT_ENTRY (widget);
+ if (event->window == eentry->left_window ||
+ event->window == eentry->right_window)
+ gdk_window_invalidate_rect (event->window, NULL, FALSE);
+ }
+ return FALSE;
+}
+
+static void ygtk_find_entry_actual_popup_menu (GtkWidget *widget, guint button,
+ guint32 time)
+{
+ GtkMenu *menu = YGTK_FIND_ENTRY (widget)->context_menu;
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, time);
+}
+
+static gboolean ygtk_find_entry_popup_menu (GtkWidget *widget)
+{
+ if (YGTK_FIND_ENTRY (widget)->context_menu) {
+ ygtk_find_entry_actual_popup_menu (widget, 0, gtk_get_current_event_time());
+ return TRUE;
+ }
+ return GTK_WIDGET_CLASS (ygtk_find_entry_parent_class)->popup_menu (widget);
+}
+
+static gboolean ygtk_find_entry_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ YGtkFindEntry *fentry = YGTK_FIND_ENTRY (widget);
+ YGtkExtEntry *eentry = YGTK_EXT_ENTRY (widget);
+ if (event->window == eentry->left_window) {
+ // If the entry has an associated context menu, use it.
+ // Otherwise, find icon selects entry's text.
+ gtk_widget_grab_focus (widget);
+ if (fentry->context_menu)
+ ygtk_find_entry_actual_popup_menu (widget, event->button, event->time);
+ else
+ gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
+ }
+ else if (event->window == eentry->right_window) {
+ gtk_editable_delete_text (GTK_EDITABLE (widget), 0, -1);
+ gtk_widget_grab_focus (widget);
+ }
+ else
+ return GTK_WIDGET_CLASS (ygtk_find_entry_parent_class)->button_press_event
+ (widget, event);
+ return TRUE;
+}
+
+static void ygtk_find_entry_insert_text (GtkEditable *editable,
+ const gchar *new_text, gint new_text_len, gint *pos)
+{
+ GtkEditableClass *parent_editable_iface = g_type_interface_peek
+ (ygtk_find_entry_parent_class, GTK_TYPE_EDITABLE);
+ parent_editable_iface->insert_text (editable, new_text, new_text_len, pos);
+
+ GdkWindow *clear_win = YGTK_EXT_ENTRY (editable)->right_window;
+ if (clear_win)
+ gdk_window_show (clear_win);
+}
+
+static void ygtk_find_entry_delete_text (GtkEditable *editable, gint start_pos,
+ gint end_pos)
+{
+ GtkEditableClass *parent_editable_iface = g_type_interface_peek
+ (ygtk_find_entry_parent_class, GTK_TYPE_EDITABLE);
+ parent_editable_iface->delete_text (editable, start_pos, end_pos);
+
+ int has_text = strlen (gtk_entry_get_text (GTK_ENTRY (editable)));
+ if (!has_text) {
+ /* Set or delete text may be called while the widget has not yet been
+ realized. */
+ GdkWindow *clear_win = YGTK_EXT_ENTRY (editable)->right_window;
+ if (clear_win)
+ gdk_window_hide (clear_win);
+ }
+}
+
+void ygtk_find_entry_attach_menu (YGtkFindEntry *entry, GtkMenu *menu)
+{
+ if (entry->context_menu)
+ gtk_menu_detach (entry->context_menu);
+ entry->context_menu = menu;
+ if (menu)
+ gtk_menu_attach_to_widget (menu, GTK_WIDGET (entry), NULL);
+ ygtk_find_entry_set_borders (entry);
+}
+
+GtkWidget *ygtk_find_entry_new (void /*gboolean will_use_find_icon */)
+{
+ return g_object_new (YGTK_TYPE_FIND_ENTRY, NULL);
+}
+
+static void ygtk_find_entry_class_init (YGtkFindEntryClass *klass)
+{
+ GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->realize = ygtk_find_entry_realize;
+ gtkwidget_class->map = ygtk_find_entry_map;
+ gtkwidget_class->expose_event = ygtk_find_entry_expose;
+ gtkwidget_class->enter_notify_event = ygtk_find_entry_enter_leave_notify_event;
+ gtkwidget_class->leave_notify_event = ygtk_find_entry_enter_leave_notify_event;
+ gtkwidget_class->button_press_event = ygtk_find_entry_button_press_event;
+ gtkwidget_class->popup_menu = ygtk_find_entry_popup_menu;
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_find_entry_destroy;
+}
+
+static void ygtk_find_entry_editable_init (GtkEditableClass *iface)
+{
+ iface->insert_text = ygtk_find_entry_insert_text;
+ iface->delete_text = ygtk_find_entry_delete_text;
+}
Added: trunk/gtk/src/ygtkfindentry.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkfindentry.h?rev=4251…
==============================================================================
--- trunk/gtk/src/ygtkfindentry.h (added)
+++ trunk/gtk/src/ygtkfindentry.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,99 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkExtEntry extends GtkEntry adding two optional GdkWindows, at each
+ horizontal corner, which are created at demand. Very useful to create
+ a panel, an icon or something inside of it.
+ GtkTextView provides something similar and would be nice to have this
+ right on GtkEntry; in fact, GtkSpinButton could be simplified if it
+ were for this.
+ Right-to-left is supported at this level (borders are mirrored, if it
+ is set). If you don't want that, use gtk_widget_set_direction().
+
+ YGtkFindEntry is a convinience widget that has a find icon, with an
+ optional menu, at the left, and an erase icon at the right.
+*/
+
+#ifndef YGTK_FIND_ENTRY_H
+#define YGTK_FIND_ENTRY_H
+
+#include <gtk/gtkentry.h>
+G_BEGIN_DECLS
+
+//** YGtkExtEntry
+
+#define YGTK_TYPE_EXT_ENTRY (ygtk_ext_entry_get_type ())
+#define YGTK_EXT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_EXT_ENTRY, YGtkExtEntry))
+#define YGTK_EXT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_EXT_ENTRY, YGtkExtEntryClass))
+#define YGTK_IS_EXT_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_EXT_ENTRY))
+#define YGTK_IS_EXT_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_EXT_ENTRY))
+#define YGTK_EXT_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_EXT_ENTRY, YGtkExtEntryClass))
+
+typedef struct _YGtkExtEntry
+{
+ GtkEntry parent;
+ // members:
+ GdkWindow *left_window, *right_window;
+} YGtkExtEntry;
+
+typedef struct _YGtkExtEntryClass
+{
+ GtkEntryClass parent_class;
+} YGtkExtEntryClass;
+
+GtkWidget* ygtk_ext_entry_new (void);
+GType ygtk_ext_entry_get_type (void) G_GNUC_CONST;
+
+// API based on that of GtkTextView -- limited to our needs
+typedef enum
+{ YGTK_EXT_ENTRY_WIDGET_WIN, YGTK_EXT_ENTRY_TEXT_WIN,
+ YGTK_EXT_ENTRY_LEFT_WIN, YGTK_EXT_ENTRY_RIGHT_WIN
+} YGtkExtEntryWindowType;
+
+GdkWindow *ygtk_ext_entry_get_window (YGtkExtEntry *entry,
+ YGtkExtEntryWindowType type);
+void ygtk_ext_entry_set_border_window_size (YGtkExtEntry *entry,
+ YGtkExtEntryWindowType type, gint size);
+gint ygtk_ext_entry_get_border_window_size (YGtkExtEntry *entry,
+ YGtkExtEntryWindowType type);
+
+//** YGtkFindEntry
+
+#define YGTK_TYPE_FIND_ENTRY (ygtk_find_entry_get_type ())
+#define YGTK_FIND_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_FIND_ENTRY, YGtkFindEntry))
+#define YGTK_FIND_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_FIND_ENTRY, YGtkFindEntryClass))
+#define YGTK_IS_FIND_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_FIND_ENTRY))
+#define YGTK_IS_FIND_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_FIND_ENTRY))
+#define YGTK_FIND_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_FIND_ENTRY, YGtkFindEntryClass))
+
+typedef struct _YGtkFindEntry
+{
+ YGtkExtEntry parent;
+ // members
+ GdkPixbuf *find_icon, *clear_icon, *find_hover_icon, *clear_hover_icon;
+ GtkMenu *context_menu;
+} YGtkFindEntry;
+
+typedef struct _YGtkFindEntryClass
+{
+ YGtkExtEntryClass parent_class;
+} YGtkFindEntryClass;
+
+GtkWidget* ygtk_find_entry_new (void);
+GType ygtk_find_entry_get_type (void) G_GNUC_CONST;
+
+void ygtk_find_entry_attach_menu (YGtkFindEntry *entry, GtkMenu *popup_menu);
+
+G_END_DECLS
+#endif /*YGTK_FIND_ENTRY_H*/
Added: trunk/gtk/src/ygtkhtmlwrap.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkhtmlwrap.c?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkhtmlwrap.c (added)
+++ trunk/gtk/src/ygtkhtmlwrap.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,170 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkHtmlWrap widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include <gtk/gtkversion.h>
+#include <string.h>
+#include "ygtkhtmlwrap.h"
+
+GtkWidget *ygtk_html_wrap_new (void)
+{
+ return g_object_new (ygtk_html_wrap_get_type(), NULL);
+}
+
+
+// Utilities
+static inline void adjust_scroll (GtkAdjustment *vadj, gboolean top)
+{
+ g_assert (vadj != 0);
+ if (top)
+ gtk_adjustment_set_value (vadj, vadj->lower);
+ else /* bottom */
+ gtk_adjustment_set_value (vadj, vadj->upper - vadj->page_size);
+}
+
+static void gdkwindow_set_background (GdkWindow *window, const char *image)
+{
+ if (image) {
+ GError *error = 0;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (image, &error);
+ if (!pixbuf) {
+ g_warning ("ygtkrichtext: could not open background image: '%s'"
+ " - %s", image, error->message);
+ return;
+ }
+
+ GdkPixmap *pixmap;
+ gdk_pixbuf_render_pixmap_and_mask_for_colormap (pixbuf,
+ gdk_drawable_get_colormap (GDK_DRAWABLE (window)), &pixmap, NULL, 0);
+ g_object_unref (G_OBJECT (pixbuf));
+
+ gdk_window_set_back_pixmap (window, pixmap, FALSE);
+ }
+ else
+ gdk_window_clear (window);
+}
+
+// GtkHTML
+#ifdef USE_GTKHTML
+#include <libgtkhtml-3.14/gtkhtml/gtkhtml.h>
+#include <libgtkhtml-3.14/gtkhtml/gtkhtml-stream.h>
+#include <libgtkhtml-3.14/gtkhtml/gtkhtml-search.h>
+
+GType ygtk_html_wrap_get_type (void)
+{
+ return GTK_TYPE_HTML;
+}
+
+static void gtkhtml_url_requested_cb (GtkHTML *html, const gchar *url, GtkHTMLStream *stream)
+{ // to load images (and possibly other external embed files)
+ FILE *file = fopen (url, "rb");
+
+ fseek (file, 0, SEEK_END);
+ size_t file_size = ftell (file);
+ rewind (file);
+
+ gboolean error;
+ gchar *data = g_new (gchar, file_size);
+ error = fread (data, 1, file_size, file) < file_size;
+ fclose (file);
+
+ if (!error)
+ gtk_html_stream_write (stream, data, file_size);
+ g_free (data);
+}
+
+void ygtk_html_wrap_init (GtkWidget *widget)
+{
+ gtk_html_set_editable (GTK_HTML (widget), FALSE);
+ g_signal_connect (G_OBJECT (widget), "url-requested",
+ G_CALLBACK (gtkhtml_url_requested_cb), NULL);
+}
+
+void ygtk_html_wrap_set_text (GtkWidget *widget, const gchar* text)
+{
+ GtkHTMLStream *stream = gtk_html_begin (GTK_HTML (widget));
+ gtk_html_write (GTK_HTML (widget), stream, text, strlen (text));
+ gtk_html_end (GTK_HTML (widget), stream, GTK_HTML_STREAM_OK);
+}
+
+void ygtk_html_wrap_scroll (GtkWidget *widget, gboolean top)
+{
+ adjust_scroll (GTK_LAYOUT (widget)->vadjustment, top);
+}
+
+gboolean ygtk_html_wrap_search (GtkWidget *widget, const gchar *text)
+{
+/* if (*text == '\0')
+ return TRUE;*/
+ return gtk_html_engine_search (GTK_HTML (widget), text, FALSE, TRUE, FALSE);
+}
+
+gboolean ygtk_html_wrap_search_next (GtkWidget *widget, const gchar *text)
+{
+ return gtk_html_engine_search_next (GTK_HTML (widget));
+}
+
+void ygtk_html_wrap_connect_link_clicked (GtkWidget *widget, GCallback callback, gpointer data)
+{
+ g_signal_connect (G_OBJECT (widget), "link-clicked", callback, data);
+}
+
+void ygtk_html_wrap_set_background (GtkWidget *widget, const char *image)
+{
+ // TODO
+}
+
+// YGtkRichText
+#else
+#include "ygtkrichtext.h"
+
+GType ygtk_html_wrap_get_type()
+{
+ return YGTK_TYPE_RICH_TEXT;
+}
+
+void ygtk_html_wrap_init (GtkWidget *widget)
+{
+}
+
+void ygtk_html_wrap_set_text (GtkWidget *widget, const gchar* text)
+{
+ ygtk_rich_text_set_text (YGTK_RICH_TEXT (widget), text, TRUE);
+}
+
+void ygtk_html_wrap_scroll (GtkWidget *widget, gboolean top)
+{
+ adjust_scroll (GTK_TEXT_VIEW (widget)->vadjustment, top);
+}
+
+gboolean ygtk_html_wrap_search (GtkWidget *widget, const gchar *text)
+{
+ gboolean ret = ygtk_rich_text_mark_text (YGTK_RICH_TEXT (widget), text);
+ ygtk_rich_text_forward_mark (YGTK_RICH_TEXT (widget), text);
+ return ret;
+}
+
+gboolean ygtk_html_wrap_search_next (GtkWidget *widget, const gchar *text)
+{
+ return ygtk_rich_text_forward_mark (YGTK_RICH_TEXT (widget), text);
+}
+
+void ygtk_html_wrap_connect_link_clicked (GtkWidget *widget, GCallback callback, gpointer data)
+{
+ g_signal_connect (G_OBJECT (widget), "link-clicked", callback, data);
+}
+
+void ygtk_html_wrap_set_background (GtkWidget *widget, const char *image)
+{
+ g_return_if_fail (GTK_WIDGET_REALIZED (widget));
+ GdkWindow *window = gtk_text_view_get_window
+ (GTK_TEXT_VIEW (widget), GTK_TEXT_WINDOW_TEXT);
+ gdkwindow_set_background (window, image);
+}
+
+#endif
+
Added: trunk/gtk/src/ygtkhtmlwrap.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkhtmlwrap.h?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkhtmlwrap.h (added)
+++ trunk/gtk/src/ygtkhtmlwrap.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,37 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkHtmlWrap is a wrapper around either GtkHtml and YGtkRichText, as
+ set at compilation time. GtkHtml is superior, but to avoid dependencies,
+ we use our customized in case it isn't installed.
+ If you flag it as plain_text, it will simply wrap GtkTextView.
+*/
+
+#ifndef YGTK_HTML_WRAP_H
+#define YGTK_HTML_WRAP_H
+
+#include <gtk/gtkwidget.h>
+G_BEGIN_DECLS
+
+GtkWidget *ygtk_html_wrap_new (void);
+
+GType ygtk_html_wrap_get_type (void);
+void ygtk_html_wrap_init (GtkWidget *widget); // if you use g_object_new(), call this
+
+void ygtk_html_wrap_set_text (GtkWidget *widget, const gchar* text);
+void ygtk_html_wrap_scroll (GtkWidget *widget, gboolean top /* or bottom */);
+
+// callback of type: void (GtkWidget *htmlwrap, const gchar *url, gpointer data)
+void ygtk_html_wrap_connect_link_clicked (GtkWidget *widget, GCallback callback, gpointer data);
+
+// not supported on plain text
+gboolean ygtk_html_wrap_search (GtkWidget *widget, const gchar *text);
+gboolean ygtk_html_wrap_search_next (GtkWidget *widget, const gchar *text); // F3
+
+// set a background image -- to be done on (or after) realize
+void ygtk_html_wrap_set_background (GtkWidget *widget, const char *image);
+
+G_END_DECLS
+#endif /* YGTK_HTML_WRAP_H */
+
Added: trunk/gtk/src/ygtkmenubutton.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkmenubutton.c?rev=425…
==============================================================================
--- trunk/gtk/src/ygtkmenubutton.c (added)
+++ trunk/gtk/src/ygtkmenubutton.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,247 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkMenuButton widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkmenubutton.h"
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+//** YGtkPopupWindow
+
+G_DEFINE_TYPE (YGtkPopupWindow, ygtk_popup_window, GTK_TYPE_WINDOW)
+
+static void ygtk_popup_window_init (YGtkPopupWindow *popup)
+{
+ GtkWindow *window = GTK_WINDOW (popup);
+ gtk_window_set_resizable (window, FALSE);
+
+ GtkWidget *frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+ gtk_widget_show (frame);
+ gtk_container_add (GTK_CONTAINER (window), frame);
+}
+
+static void ygtk_popup_window_hide (GtkWidget *widget)
+{
+ gtk_grab_remove (widget);
+ GTK_WIDGET_CLASS (ygtk_popup_window_parent_class)->hide (widget);
+}
+
+static gboolean ygtk_popup_window_key_press_event (GtkWidget *widget, GdkEventKey *event)
+{
+ if (event->keyval == GDK_Escape) {
+ gtk_widget_hide (widget);
+ return TRUE;
+ }
+ return GTK_WIDGET_CLASS (ygtk_popup_window_parent_class)->key_press_event
+ (widget, event);
+}
+
+static gboolean ygtk_popup_window_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ // NOTE: You can't rely on events x and y since the event may take place
+ // outside of the window.
+ // So, we'll check if this widget (or any of its kids) got the event
+ // If that's not the case, close the menu
+
+ GtkWidget *child = gtk_get_event_widget ((GdkEvent *) event);
+ if (child != widget)
+ while (child) {
+ if (child == widget)
+ return FALSE;
+ child = child->parent;
+ }
+ gtk_widget_hide (widget);
+ return TRUE;
+}
+
+GtkWidget *ygtk_popup_window_new (GtkWidget *child)
+{
+ GtkWidget *widget = g_object_new (YGTK_TYPE_POPUP_WINDOW,
+ "type", GTK_WINDOW_POPUP, NULL);
+ GtkWidget *frame = gtk_bin_get_child (GTK_BIN (widget));
+ gtk_container_add (GTK_CONTAINER (frame), child);
+ return widget;
+}
+
+void ygtk_popup_window_popup (GtkWidget *widget, gint x, gint y, guint activate_time)
+{
+ gtk_grab_add (widget);
+ gtk_window_move (GTK_WINDOW (widget), x, y);
+ gtk_widget_grab_focus (widget);
+ gtk_widget_show (widget);
+
+ // grab this with your teeth
+ if (gdk_pointer_grab (widget->window, TRUE,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
+ NULL, NULL, activate_time) == 0)
+ if (gdk_keyboard_grab (widget->window, TRUE, activate_time) != 0)
+ gdk_pointer_ungrab(activate_time);
+}
+
+static void ygtk_popup_window_class_init (YGtkPopupWindowClass *klass)
+{
+ ygtk_popup_window_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->key_press_event = ygtk_popup_window_key_press_event;
+ widget_class->button_press_event = ygtk_popup_window_button_press_event;
+ widget_class->hide = ygtk_popup_window_hide;
+}
+
+//** YGtkMenuButton
+
+G_DEFINE_TYPE (YGtkMenuButton, ygtk_menu_button, GTK_TYPE_TOGGLE_BUTTON)
+
+static void ygtk_menu_button_init (YGtkMenuButton *button)
+{
+ button->popup = NULL;
+ button->label = gtk_label_new ("");
+
+ GtkWidget *hbox, *arrow;
+ hbox = gtk_hbox_new (FALSE, 0);
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
+
+ if (gtk_widget_get_direction (arrow) == GTK_TEXT_DIR_LTR) {
+ gtk_container_add (GTK_CONTAINER (hbox), button->label);
+ gtk_container_add (GTK_CONTAINER (hbox), arrow);
+ }
+ else {
+ gtk_container_add (GTK_CONTAINER (hbox), arrow);
+ gtk_container_add (GTK_CONTAINER (hbox), button->label);
+ }
+
+ gtk_box_set_child_packing (GTK_BOX (hbox), arrow, FALSE, FALSE,
+ 5, GTK_PACK_START);
+
+ gtk_widget_show_all (hbox);
+ gtk_container_add (GTK_CONTAINER (button), hbox);
+}
+
+static void ygtk_menu_button_free_popup (YGtkMenuButton *button)
+{
+ if (button->popup) {
+ gtk_widget_destroy (GTK_WIDGET (button->popup));
+ g_object_unref (G_OBJECT (button->popup));
+ button->popup = NULL;
+ }
+}
+
+static void ygtk_menu_button_finalize (GObject *object)
+{
+ ygtk_menu_button_free_popup (YGTK_MENU_BUTTON (object));
+ G_OBJECT_CLASS (ygtk_menu_button_parent_class)->finalize (object);
+}
+
+static void ygtk_menu_button_get_menu_pos (GtkMenu *menu, gint *x, gint *y,
+ gboolean *push_in, gpointer pointer)
+{
+ GtkWidget *widget = (GtkWidget*) pointer;
+ gdk_window_get_origin (widget->window, x, y);
+ *x += widget->allocation.x;
+ *y += widget->allocation.y + widget->allocation.height;
+ *push_in = TRUE;
+}
+
+static void ygtk_menu_button_show_popup (YGtkMenuButton *button)
+{
+ GtkWidget *widget = GTK_WIDGET (button);
+ GtkWidget *popup = button->popup;
+ if (!popup)
+ return;
+
+ guint activate_time = gtk_get_current_event_time();
+
+ if (GTK_IS_MENU (popup))
+ gtk_menu_popup (GTK_MENU (popup), NULL, NULL, ygtk_menu_button_get_menu_pos,
+ widget, 0, activate_time);
+ else { // GTK_IS_WINDOW
+ gint x, y;
+ gdk_window_get_origin (GDK_WINDOW (widget->window), &x, &y);
+ x += widget->allocation.x;
+ y += widget->allocation.y + widget->allocation.height;
+
+ ygtk_popup_window_popup (popup, x, y, activate_time);
+ }
+
+ if (widget->allocation.width > popup->allocation.width)
+ gtk_widget_set_size_request (popup, widget->allocation.width, -1);
+}
+
+static void ygtk_menu_button_hide_popup (YGtkMenuButton *button)
+{
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
+}
+
+static void ygtk_menu_button_button_toggle (GtkToggleButton *button)
+{
+ if (gtk_toggle_button_get_active (button))
+ ygtk_menu_button_show_popup (YGTK_MENU_BUTTON (button));
+ else
+ ygtk_menu_button_hide_popup (YGTK_MENU_BUTTON (button));
+}
+
+static gint ygtk_menu_button_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+ if (event->type == GDK_BUTTON_PRESS && event->button == 1) {
+ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+ ygtk_menu_button_show_popup (YGTK_MENU_BUTTON (widget));
+ }
+ else
+ ygtk_menu_button_hide_popup (YGTK_MENU_BUTTON (widget));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+GtkWidget *ygtk_menu_button_new (void)
+{
+ return g_object_new (YGTK_TYPE_MENU_BUTTON, NULL);
+}
+
+void ygtk_menu_button_set_label (YGtkMenuButton *button, const gchar *label)
+{
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (button->label), label);
+ gtk_widget_show (button->label);
+}
+
+static void menu_button_hide_popup (GtkWidget *widget, YGtkMenuButton *button)
+{ ygtk_menu_button_hide_popup (button); }
+
+void ygtk_menu_button_set_popup (YGtkMenuButton *button, GtkWidget *popup)
+{
+ ygtk_menu_button_free_popup (button);
+
+ if (!GTK_IS_MENU (popup) && !IS_YGTK_POPUP_WINDOW (popup)) {
+ // install widget on a YGtkPopupMenu
+ button->popup = ygtk_popup_window_new (popup);
+ }
+ else
+ button->popup = popup;
+
+ g_object_ref (G_OBJECT (button->popup));
+ gtk_object_sink (GTK_OBJECT (button->popup));
+
+ g_signal_connect (G_OBJECT (popup), "hide",
+ G_CALLBACK (menu_button_hide_popup), button);
+}
+
+static void ygtk_menu_button_class_init (YGtkMenuButtonClass *klass)
+{
+ ygtk_menu_button_parent_class = g_type_class_peek_parent (klass);
+
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = ygtk_menu_button_finalize;
+
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->button_press_event = ygtk_menu_button_button_press;
+
+ GtkToggleButtonClass *toggle_button_class = GTK_TOGGLE_BUTTON_CLASS (klass);
+ toggle_button_class->toggled = ygtk_menu_button_button_toggle;
+}
Added: trunk/gtk/src/ygtkmenubutton.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkmenubutton.h?rev=425…
==============================================================================
--- trunk/gtk/src/ygtkmenubutton.h (added)
+++ trunk/gtk/src/ygtkmenubutton.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,90 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkMenuButton is a button that displays a widget when pressed.
+ This widget can either be of type GtkMenu or another, like a
+ GtkCalendar and we'll do the proper "emulation" (the work of
+ the YGtkPopupWindow widget).
+*/
+
+#ifndef YGTK_POPUP_WINDOW_H
+#define YGTK_POPUP_WINDOW_H
+
+#include <gtk/gtkwindow.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_POPUP_WINDOW (ygtk_popup_window_get_type ())
+#define YGTK_POPUP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_POPUP_WINDOW, YGtkPopupWindow))
+#define YGTK_POPUP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_POPUP_WINDOW, YGtkPopupWindowClass))
+#define IS_YGTK_POPUP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_POPUP_WINDOW))
+#define IS_YGTK_POPUP_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_POPUP_WINDOW))
+#define YGTK_POPUP_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_POPUP_WINDOW, YGtkPopupWindowClass))
+
+typedef struct _YGtkPopupWindow
+{
+ GtkWindow parent;
+} YGtkPopupWindow;
+
+typedef struct _YGtkPopupWindowClass
+{
+ GtkWindowClass parent_class;
+} YGtkPopupWindowClass;
+
+// don't forget to use gtk_widget_show() on the child!
+GtkWidget* ygtk_popup_window_new (GtkWidget *child);
+GType ygtk_popup_window_get_type (void) G_GNUC_CONST;
+
+void ygtk_popup_window_popup (GtkWidget *widget, gint x, gint y, guint activate_time);
+
+G_END_DECLS
+#endif /*YGTK_POPUP_WINDOW_H*/
+
+#ifndef YGTK_MENU_BUTTON_H
+#define YGTK_MENU_BUTTON_H
+
+#include <gtk/gtktogglebutton.h>
+#include <gtk/gtkmenu.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_MENU_BUTTON (ygtk_menu_button_get_type ())
+#define YGTK_MENU_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_MENU_BUTTON, YGtkMenuButton))
+#define YGTK_MENU_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_MENU_BUTTON, YGtkMenuButtonClass))
+#define IS_YGTK_MENU_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_MENU_BUTTON))
+#define IS_YGTK_MENU_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_MENU_BUTTON))
+#define YGTK_MENU_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_MENU_BUTTON, YGtkMenuButtonClass))
+
+typedef struct _YGtkMenuButton
+{
+ GtkToggleButton parent;
+
+ // private:
+ GtkWidget *label, *popup;
+} YGtkMenuButton;
+
+typedef struct _YGtkMenuButtonClass
+{
+ GtkToggleButtonClass parent_class;
+} YGtkMenuButtonClass;
+
+GtkWidget* ygtk_menu_button_new (void);
+GType ygtk_menu_button_get_type (void) G_GNUC_CONST;
+
+void ygtk_menu_button_set_label (YGtkMenuButton *button, const gchar *label);
+
+/* Popup must be either a GtkMenu or a YGtkPopupWindow. */
+// You may hide your popup "manually" issueing a gtk_widget_hide() on it
+void ygtk_menu_button_set_popup (YGtkMenuButton *button, GtkWidget *popup);
+
+G_END_DECLS
+#endif /*YGTK_MENU_BUTTON_H*/
Added: trunk/gtk/src/ygtkratiobox.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkratiobox.c?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkratiobox.c (added)
+++ trunk/gtk/src/ygtkratiobox.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,585 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkRatioBox widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkratiobox.h"
+
+G_DEFINE_ABSTRACT_TYPE (YGtkRatioBox, ygtk_ratio_box, GTK_TYPE_CONTAINER)
+
+static void ygtk_ratio_box_init (YGtkRatioBox *box)
+{
+ GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW);
+ gtk_widget_set_redraw_on_allocate (GTK_WIDGET (box), FALSE);
+}
+
+static GType ygtk_ratio_box_child_type (GtkContainer* container)
+{ return GTK_TYPE_WIDGET; }
+
+void ygtk_ratio_box_pack (YGtkRatioBox *box, GtkWidget *child,
+ gfloat ratio, gboolean xfill, gboolean yfill,
+ guint padding)
+{
+ YGtkRatioBoxChild* child_info;
+ child_info = g_new (YGtkRatioBoxChild, 1);
+ child_info->widget = child;
+ child_info->ratio = ratio;
+ child_info->padding = padding;
+ child_info->xfill = xfill;
+ child_info->yfill = yfill;
+ child_info->expand = 0;
+
+ box->children = g_list_append (box->children, child_info);
+
+ gtk_widget_freeze_child_notify (child);
+ gtk_widget_set_parent (child, GTK_WIDGET (box));
+ gtk_widget_thaw_child_notify (child);
+}
+
+static YGtkRatioBoxChild *ygtk_ratio_get_child_info (YGtkRatioBox *box, GtkWidget *child)
+{
+ YGtkRatioBoxChild *i = NULL;
+ GList *list;
+ for (list = box->children; list; list = list->next) {
+ i = (YGtkRatioBoxChild*) list->data;
+ if (i->widget == child)
+ break;
+ }
+ if (!list)
+ return NULL;
+ return i;
+}
+
+static void ygtk_ratio_box_add (GtkContainer *container, GtkWidget *child)
+{
+ ygtk_ratio_box_pack (YGTK_RATIO_BOX (container), child, 1.0, TRUE, TRUE, 0);
+}
+
+static void ygtk_ratio_box_remove (GtkContainer *container, GtkWidget *widget)
+{
+ YGtkRatioBox* box = YGTK_RATIO_BOX (container);
+
+ GList* child = box->children;
+ for (child = box->children; child; child = child->next) {
+ YGtkRatioBoxChild *box_child = (YGtkRatioBoxChild*) child->data;
+ if (box_child->widget == widget) {
+ gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
+ gtk_widget_unparent (widget);
+
+ box->children = g_list_remove_link (box->children, child);
+ g_list_free (child);
+ g_free (box_child);
+
+ if (was_visible)
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ break;
+ }
+ }
+}
+
+static void ygtk_ratio_box_forall (GtkContainer *container, gboolean include_internals,
+ GtkCallback callback, gpointer callback_data)
+{
+ g_return_if_fail (callback != NULL);
+
+ YGtkRatioBox* box = YGTK_RATIO_BOX (container);
+
+ GList* children = box->children;
+ while (children) {
+ YGtkRatioBoxChild* child = (YGtkRatioBoxChild*) children->data;
+ children = children->next;
+ (* callback) (child->widget, callback_data);
+ }
+}
+
+/* We put size_request and _allocate in the same functions for both
+ orientations because it's just easier to maintain having the
+ logic in the same place. */
+
+static void ygtk_ratio_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition,
+ GtkOrientation orientation)
+{
+ YGtkRatioBox* box = YGTK_RATIO_BOX (widget);
+ gfloat ratios_sum = 0;
+ box->has_must_expand = FALSE;
+ GList* child;
+ for (child = box->children; child; child = child->next) {
+ YGtkRatioBoxChild* box_child = (YGtkRatioBoxChild*) child->data;
+ if (!GTK_WIDGET_VISIBLE (box_child->widget))
+ continue;
+ if (box_child->ratio)
+ ratios_sum += box_child->ratio;
+ if (box_child->must_expand)
+ box->has_must_expand = TRUE;
+ }
+
+ // If we want to calculate horizontal size, primary_req would be horizontal
+ // length, while secondary the height. Idem for the inverse.
+ guint primary_req = 0, secondary_req = 0;
+ box->weight_length = 0; // biggest ratio of widget-size / widget-ratio
+
+ for (child = box->children; child; child = child->next) {
+ YGtkRatioBoxChild* box_child = (YGtkRatioBoxChild*) child->data;
+ if (!GTK_WIDGET_VISIBLE (box_child->widget))
+ continue;
+
+ GtkRequisition child_req;
+ gtk_widget_size_request (box_child->widget, &child_req);
+
+ guint prim_length, sec_length;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ prim_length = child_req.width;
+ sec_length = child_req.height;
+ }
+ else {
+ prim_length = child_req.height;
+ sec_length = child_req.width;
+ }
+
+ if (box_child->ratio)
+ {
+ int length = (prim_length * ratios_sum) / box_child->ratio;
+ box->weight_length = MAX (box->weight_length, length);
+ }
+ else
+ primary_req += prim_length;
+ primary_req += box_child->padding + box->spacing;
+ secondary_req = MAX (secondary_req, sec_length);
+ }
+
+ primary_req += box->weight_length;
+
+ guint border = GTK_CONTAINER (widget)->border_width * 2;
+ primary_req += border*2; secondary_req += border*2;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ requisition->width = primary_req;
+ requisition->height = secondary_req;
+ }
+ else {
+ requisition->width = secondary_req;
+ requisition->height = primary_req;
+ }
+}
+
+static void ygtk_ratio_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation,
+ GtkOrientation orientation)
+{
+ YGtkRatioBox* box = YGTK_RATIO_BOX (widget);
+ guint border = GTK_CONTAINER (widget)->border_width;
+
+ // a first loop to get some data for expansibles (ie. childs with weight)
+ gfloat ratios_sum = 0;
+ gint expand_num = 0, max_ratio = 0;
+ gint expansable_length;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ expansable_length = allocation->width - border*2;
+ else
+ expansable_length = allocation->height - border*2;
+
+ GList* child;
+ for (child = box->children; child; child = child->next) {
+ YGtkRatioBoxChild* box_child = (YGtkRatioBoxChild*) child->data;
+ if (!GTK_WIDGET_VISIBLE (box_child->widget))
+ continue;
+
+ if (box_child->expand)
+ expand_num++;
+ if (box_child->ratio)
+ {
+ ratios_sum += box_child->ratio;
+ max_ratio = MAX (max_ratio, box_child->ratio);
+ }
+
+ if (!box_child->ratio)
+ {
+ GtkRequisition child_req;
+ gtk_widget_get_child_requisition (box_child->widget, &child_req);
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ expansable_length -= child_req.width;
+ else
+ expansable_length -= child_req.height;
+ }
+ expansable_length -= box->spacing - box_child->padding;
+ }
+ expansable_length -= box->weight_length;
+
+ gint child_pos = 0;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ child_pos = allocation->x + border;
+ else
+ child_pos = allocation->y + border;
+
+ gboolean right_to_left = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+ for (child = box->children; child; child = child->next) {
+ YGtkRatioBoxChild* box_child = (YGtkRatioBoxChild*) child->data;
+ if (!GTK_WIDGET_VISIBLE (box_child->widget))
+ continue;
+
+ GtkAllocation child_alloc;
+ gint length;
+
+ GtkRequisition child_req;
+ gtk_widget_get_child_requisition (box_child->widget, &child_req);
+
+ if (!box_child->ratio)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ length = child_req.width;
+ else
+ length = child_req.height;
+ }
+
+ // give extra size (honor stretch order)
+ if (box_child->ratio)
+ {
+ int available_length = box->weight_length;
+ if (!box->has_must_expand)
+ available_length += expansable_length;
+ length = (box_child->ratio * available_length) / ratios_sum;
+ }
+ else if (box_child->expand && (ratios_sum == 0 || box_child->must_expand))
+ {
+ // FIXME: something is wrong for expansable_length being < 0 at times
+ // we aren't asking for enough size!
+ if (expansable_length > 0)
+ length += expansable_length / expand_num;
+ }
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL) {
+ child_alloc.x = child_pos;
+ child_alloc.y = allocation->y + border;
+ child_alloc.width = length;
+ child_alloc.height = allocation->height - border*2;
+ }
+ else { // GTK_ORIENTATION_VERTICAL
+ child_alloc.x = allocation->x + border;
+ child_alloc.y = child_pos;
+ child_alloc.width = allocation->width - border*2;
+ child_alloc.height = length;
+ }
+
+ if (!box_child->xfill) {
+ // we also need to center the widget
+ gint width = MIN (child_alloc.width, child_req.width);
+ child_alloc.x += MAX ((child_alloc.width - width) / 2, 0);
+ child_alloc.width = width;
+ }
+ if (!box_child->yfill) {
+ gint height = MIN (child_alloc.height, child_req.height);
+ child_alloc.y += MAX ((child_alloc.height - height) / 2, 0);
+ child_alloc.height = height;
+ }
+
+ if (right_to_left)
+ child_alloc.x = allocation->width - child_alloc.x - child_alloc.width;
+
+ gtk_widget_size_allocate (box_child->widget, &child_alloc);
+ child_pos += length + box->spacing + box_child->padding;
+ }
+}
+
+void ygtk_ratio_box_set_child_packing (YGtkRatioBox *box, GtkWidget *child,
+ gfloat ratio, gboolean xfill, gboolean yfill,
+ guint padding)
+{
+ YGtkRatioBoxChild *child_info;
+ child_info = ygtk_ratio_get_child_info (box, child);
+
+ if (child_info) {
+ gtk_widget_freeze_child_notify (child);
+
+ child_info->ratio = ratio;
+ child_info->xfill = xfill;
+ child_info->yfill = yfill;
+ child_info->padding = padding;
+ child_info->expand = 0;
+ child_info->must_expand = 0;
+
+ if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
+ gtk_widget_queue_resize (child);
+
+ gtk_widget_thaw_child_notify (child);
+ }
+}
+
+void ygtk_ratio_box_get_child_packing (YGtkRatioBox *box, GtkWidget *child,
+ gfloat *ratio, gboolean *xfill,
+ gboolean *yfill, guint *padding,
+ gboolean *expand)
+{
+ YGtkRatioBoxChild *child_info;
+ child_info = ygtk_ratio_get_child_info (box, child);
+
+ if (child_info) {
+ gtk_widget_freeze_child_notify (child);
+
+ if (ratio) *ratio = child_info->ratio;
+ if (xfill) *xfill = child_info->xfill;
+ if (yfill) *yfill = child_info->yfill;
+ if (padding) *padding = child_info->padding;
+ if (expand) *expand = child_info->expand;
+ }
+}
+
+void ygtk_ratio_box_set_child_expand (YGtkRatioBox *box, GtkWidget *child,
+ gboolean expand, gboolean must_expand)
+{
+ YGtkRatioBoxChild *child_info;
+ child_info = ygtk_ratio_get_child_info (box, child);
+ if (child_info)
+ {
+ child_info->expand = expand;
+ if (expand)
+ child_info->must_expand = must_expand;
+ }
+}
+
+void ygtk_ratio_box_set_child_ratio (YGtkRatioBox *box, GtkWidget *child,
+ gfloat ratio)
+{
+ YGtkRatioBoxChild *child_info;
+ child_info = ygtk_ratio_get_child_info (box, child);
+ if (child_info)
+ child_info->ratio = ratio;
+}
+
+void ygtk_ratio_box_set_spacing (YGtkRatioBox *box, gint spacing)
+{
+ box->spacing = spacing;
+}
+
+static void ygtk_ratio_box_class_init (YGtkRatioBoxClass *klass)
+{
+ ygtk_ratio_box_parent_class = (GtkContainerClass*) g_type_class_peek_parent (klass);
+
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ container_class->add = ygtk_ratio_box_add;
+ container_class->remove = ygtk_ratio_box_remove;
+ container_class->forall = ygtk_ratio_box_forall;
+ container_class->child_type = ygtk_ratio_box_child_type;
+}
+
+//** RatioHBox
+
+G_DEFINE_TYPE (YGtkRatioHBox, ygtk_ratio_hbox, YGTK_TYPE_RATIO_BOX)
+
+static void ygtk_ratio_hbox_init (YGtkRatioHBox *box)
+{
+}
+
+static void ygtk_ratio_hbox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ ygtk_ratio_box_size_request (widget, requisition, GTK_ORIENTATION_HORIZONTAL);
+}
+
+static void ygtk_ratio_hbox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ ygtk_ratio_box_size_allocate (widget, allocation, GTK_ORIENTATION_HORIZONTAL);
+}
+
+GtkWidget* ygtk_ratio_hbox_new (gint spacing)
+{
+ YGtkRatioBox* box = (YGtkRatioBox*) g_object_new (YGTK_TYPE_RATIO_HBOX, NULL);
+ box->spacing = spacing;
+ return GTK_WIDGET (box);
+}
+
+static void ygtk_ratio_hbox_class_init (YGtkRatioHBoxClass *klass)
+{
+ ygtk_ratio_hbox_parent_class = (YGtkRatioBoxClass*) g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->size_request = ygtk_ratio_hbox_size_request;
+ widget_class->size_allocate = ygtk_ratio_hbox_size_allocate;
+}
+
+//** RatioVBox
+
+G_DEFINE_TYPE (YGtkRatioVBox, ygtk_ratio_vbox, YGTK_TYPE_RATIO_BOX)
+
+static void ygtk_ratio_vbox_init (YGtkRatioVBox *box)
+{
+}
+
+static void ygtk_ratio_vbox_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ ygtk_ratio_box_size_request (widget, requisition, GTK_ORIENTATION_VERTICAL);
+}
+
+static void ygtk_ratio_vbox_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ ygtk_ratio_box_size_allocate (widget, allocation, GTK_ORIENTATION_VERTICAL);
+}
+
+GtkWidget* ygtk_ratio_vbox_new (gint spacing)
+{
+ YGtkRatioBox* box = (YGtkRatioBox*) g_object_new (YGTK_TYPE_RATIO_VBOX, NULL);
+ box->spacing = spacing;
+ return GTK_WIDGET (box);
+}
+
+static void ygtk_ratio_vbox_class_init (YGtkRatioVBoxClass *klass)
+{
+ ygtk_ratio_vbox_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->size_request = ygtk_ratio_vbox_size_request;
+ widget_class->size_allocate = ygtk_ratio_vbox_size_allocate;
+}
+
+//** YGtkAdjSize
+
+G_DEFINE_TYPE (YGtkAdjSize, ygtk_adj_size, GTK_TYPE_BIN)
+
+static void ygtk_adj_size_init (YGtkAdjSize *adj_size)
+{
+ GTK_WIDGET_SET_FLAGS (adj_size, GTK_NO_WINDOW);
+ gtk_widget_set_redraw_on_allocate (GTK_WIDGET (adj_size), FALSE);
+}
+
+static void ygtk_adj_size_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkWidget *child = GTK_BIN (widget)->child;
+ requisition->width = requisition->height = 0;
+ if (child && GTK_WIDGET_VISIBLE (child)) {
+ gtk_widget_size_request (child, requisition);
+ guint border = GTK_CONTAINER (widget)->border_width;
+ requisition->width += border * 2;
+ requisition->height += border * 2;
+
+ YGtkAdjSize *adj_size = YGTK_ADJ_SIZE (widget);
+ requisition->width = MAX (requisition->width, adj_size->min_width);
+ requisition->height = MAX (requisition->height, adj_size->min_height);
+
+ if (adj_size->max_width)
+ requisition->width = MIN (requisition->width, adj_size->max_width);
+ if (adj_size->max_height)
+ requisition->height = MIN (requisition->height, adj_size->max_height);
+
+ if (adj_size->only_expand) {
+ adj_size->min_width = requisition->width;
+ adj_size->min_height = requisition->height;
+ }
+ }
+}
+
+static void ygtk_adj_size_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWidget *child = GTK_BIN (widget)->child;
+ if (child && GTK_WIDGET_VISIBLE (child)) {
+ GtkAllocation child_alloc = *allocation;
+ guint border = GTK_CONTAINER (widget)->border_width;
+ child_alloc.x += border;
+ child_alloc.y += border;
+ child_alloc.width -= border * 2;
+ child_alloc.height -= border * 2;
+ gtk_widget_size_allocate (child, &child_alloc);
+ }
+ GTK_WIDGET_CLASS (ygtk_adj_size_parent_class)->size_allocate (widget, allocation);
+}
+
+GtkWidget* ygtk_adj_size_new (void)
+{
+ return GTK_WIDGET (g_object_new (YGTK_TYPE_ADJ_SIZE, NULL));
+}
+
+void ygtk_adj_size_set_min (YGtkAdjSize *adj_size, guint min_width, guint min_height)
+{
+ adj_size->min_width = min_width;
+ adj_size->min_height = min_height;
+}
+
+void ygtk_adj_size_set_max (YGtkAdjSize *adj_size, guint max_width, guint max_height)
+{
+ adj_size->max_width = max_width;
+ adj_size->max_height = max_height;
+}
+
+void ygtk_adj_size_set_only_expand (YGtkAdjSize *adj_size, gboolean only_expand)
+{
+ adj_size->only_expand = only_expand;
+}
+
+static void ygtk_adj_size_class_init (YGtkAdjSizeClass *klass)
+{
+ ygtk_adj_size_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->size_request = ygtk_adj_size_size_request;
+ widget_class->size_allocate = ygtk_adj_size_size_allocate;
+}
+
+//** YGtkScrolledWindow
+
+G_DEFINE_TYPE (YGtkScrolledWindow, ygtk_scrolled_window, GTK_TYPE_SCROLLED_WINDOW)
+
+static void ygtk_scrolled_window_init (YGtkScrolledWindow *scroll)
+{
+}
+
+static void ygtk_scrolled_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ YGtkScrolledWindow *scroll = YGTK_SCROLLED_WINDOW (widget);
+
+ GtkRequisition child_req;
+ GtkWidget *child = GTK_BIN (widget)->child;
+ gtk_widget_size_request (child, &child_req);
+
+ GtkScrolledWindow *gscroll = GTK_SCROLLED_WINDOW (widget);
+ GtkPolicyType hpolicy, vpolicy;
+ gtk_scrolled_window_get_policy (gscroll, &hpolicy, &vpolicy);
+
+ if (scroll->max_width) {
+ if (child_req.width < scroll->max_width)
+ gscroll->hscrollbar_policy = GTK_POLICY_NEVER;
+ else
+ gscroll->hscrollbar_policy = GTK_POLICY_AUTOMATIC;
+ }
+ if (scroll->max_height) {
+ if (child_req.height < scroll->max_height)
+ gscroll->vscrollbar_policy = GTK_POLICY_NEVER;
+ else
+ gscroll->vscrollbar_policy = GTK_POLICY_AUTOMATIC;
+ }
+
+ GTK_WIDGET_CLASS (ygtk_scrolled_window_parent_class)->size_request (widget, requisition);
+ // to avoid disruptions:
+ requisition->width = MIN (requisition->width, scroll->max_width);
+ requisition->height = MIN (requisition->height, scroll->max_height);
+}
+
+GtkWidget* ygtk_scrolled_window_new (GtkWidget *child)
+{
+ YGtkScrolledWindow *scroll = g_object_new (YGTK_TYPE_SCROLLED_WINDOW, NULL);
+ if (child)
+ gtk_container_add (GTK_CONTAINER (scroll), child);
+ return GTK_WIDGET (scroll);
+}
+
+void ygtk_scrolled_window_set_auto_policy (YGtkScrolledWindow *scroll,
+ guint max_width, guint max_height)
+{
+ scroll->max_width = max_width;
+ scroll->max_height = max_height;
+}
+
+static void ygtk_scrolled_window_class_init (YGtkScrolledWindowClass *klass)
+{
+ ygtk_scrolled_window_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->size_request = ygtk_scrolled_window_size_request;
+}
Added: trunk/gtk/src/ygtkratiobox.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkratiobox.h?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkratiobox.h (added)
+++ trunk/gtk/src/ygtkratiobox.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,241 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkRatioBox is an improvement over the GtkBox container that
+ allows the programmer to set stretch weights to containees.
+
+ It is similar to GtkBox in usage but instead of feeding an
+ expand boolean, a weight is given instead. In fact, it should
+ behave just the same as a GtkBox if you give 0 for not expand
+ and 1 to.
+*/
+/*
+ Quirks (cause of yast-core):
+ if one of the children has certain special properties, then only widgets with
+ the same properties will be expanded. These are, by order:
+ both stretch and rubber-band
+ both stretch and weight
+ weight
+ stretch
+
+ We use different naming:
+ stretch = expand
+ rubber-band or layout-stretch = must expand
+ weight = ratio
+*/
+
+#ifndef YGTK_RATIO_BOX_H
+#define YGTK_RATIO_BOX_H
+
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_RATIO_BOX (ygtk_ratio_box_get_type ())
+#define YGTK_RATIO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_RATIO_BOX, YGtkRatioBox))
+#define YGTK_RATIO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_RATIO_BOX, YGtkRatioBoxClass))
+#define YGTK_IS_RATIO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_RATIO_BOX))
+#define YGTK_IS_RATIO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_RATIO_BOX))
+#define YGTK_RATIO_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_RATIO_BOX, YGtkRatioBoxClass))
+
+typedef struct _YGtkRatioBox
+{
+ GtkContainer parent;
+
+ // private (read-only):
+ GList *children;
+ gint16 spacing;
+ guint weight_length; // min-length for weight widgets
+ guint has_must_expand : 1; // cache
+} YGtkRatioBox;
+
+typedef struct _YGtkRatioBoxClass
+{
+ GtkContainerClass parent_class;
+} YGtkRatioBoxClass;
+
+typedef struct _YGtkRatioBoxChild
+{
+ GtkWidget *widget;
+ // members
+ guint16 padding;
+ gfloat ratio;
+ guint xfill : 1;
+ guint yfill : 1;
+ guint expand : 1; // twilight zone flag; use ratio
+ guint must_expand : 1; // higher order expand
+} YGtkRatioBoxChild;
+
+GType ygtk_ratio_box_get_type (void) G_GNUC_CONST;
+
+void ygtk_ratio_box_set_spacing (YGtkRatioBox *box, gint spacing);
+
+void ygtk_ratio_box_pack (YGtkRatioBox *box, GtkWidget *child, gfloat ratio,
+ gboolean xfill, gboolean yfill, guint padding);
+
+// If you don't want to use ratios, you can use the ordinary expand flag. NOTE:
+// If some other child has ratio > 0, this one won't expand.
+// All this mess is so we can conform with yast-core.
+void ygtk_ratio_box_set_child_expand (YGtkRatioBox *box, GtkWidget *child,
+ gboolean expand, gboolean must_expand);
+void ygtk_ratio_box_set_child_ratio (YGtkRatioBox *box, GtkWidget *child,
+ gfloat ratio);
+
+void ygtk_ratio_box_set_child_packing (YGtkRatioBox *box, GtkWidget *child,
+ gfloat ratio, gboolean xfill,
+ gboolean yfill, guint padding);
+
+void ygtk_ratio_box_get_child_packing (YGtkRatioBox *box, GtkWidget *child,
+ gfloat *ratio, gboolean *xfill,
+ gboolean *yfill, guint *padding,
+ gboolean *expandable);
+
+void ygtk_ratio_box_set_force_min_weight (YGtkRatioBox *box, gboolean force);
+
+/* RatioHBox */
+
+#define YGTK_TYPE_RATIO_HBOX (ygtk_ratio_hbox_get_type ())
+#define YGTK_RATIO_HBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_RATIO_HBOX, YGtkRatioHBox))
+#define YGTK_RATIO_HBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_RATIO_HBOX, YGtkRatioHBoxClass))
+#define YGTK_IS_RATIO_HBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_RATIO_HBOX))
+#define YGTK_IS_RATIO_HBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_RATIO_HBOX))
+#define YGTK_RATIO_HBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_RATIO_HBOX, YGtkRatioHBoxClass))
+
+typedef struct _YGtkRatioHBox
+{
+ YGtkRatioBox parent;
+} YGtkRatioHBox;
+
+typedef struct _YGtkRatioHBoxClass
+{
+ YGtkRatioBoxClass parent_class;
+} YGtkRatioHBoxClass;
+
+GtkWidget* ygtk_ratio_hbox_new (gint spacing);
+GType ygtk_ratio_hbox_get_type (void) G_GNUC_CONST;
+
+/* RatioVBox */
+
+#define YGTK_TYPE_RATIO_VBOX (ygtk_ratio_vbox_get_type ())
+#define YGTK_RATIO_VBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_RATIO_VBOX, YGtkRatioVBox))
+#define YGTK_RATIO_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_RATIO_VBOX, YGtkRatioVBoxClass))
+#define YGTK_IS_RATIO_VBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_RATIO_VBOX))
+#define YGTK_IS_RATIO_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_RATIO_VBOX))
+#define YGTK_RATIO_VBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_RATIO_VBOX, YGtkRatioVBoxClass))
+
+typedef struct _YGtkRatioVBox
+{
+ YGtkRatioBox parent;
+} YGtkRatioVBox;
+
+typedef struct _YGtkRatioVBoxClass
+{
+ YGtkRatioBoxClass parent_class;
+} YGtkRatioVBoxClass;
+
+GtkWidget* ygtk_ratio_vbox_new (gint spacing);
+GType ygtk_ratio_vbox_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+#endif /* YGTK_RATIO_BOX_H */
+
+/* YGtkAdjSize container allows for better fine grained size constrains. */
+#ifndef YGTK_ADJ_SIZE_H
+#define YGTK_ADJ_SIZE_H
+
+#include <gtk/gtkbin.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_ADJ_SIZE (ygtk_adj_size_get_type ())
+#define YGTK_ADJ_SIZE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_ADJ_SIZE, YGtkAdjSize))
+#define YGTK_ADJ_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_ADJ_SIZE, YGtkAdjSizeClass))
+#define YGTK_IS_ADJ_SIZE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_ADJ_SIZE))
+#define YGTK_IS_ADJ_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_ADJ_SIZE))
+#define YGTK_ADJ_SIZE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_ADJ_SIZE, YGtkAdjSizeClass))
+
+typedef struct _YGtkAdjSize
+{
+ GtkBin parent;
+ // members
+ guint min_width, min_height, max_width, max_height;
+ gboolean only_expand;
+} YGtkAdjSize;
+
+typedef struct _YGtkAdjSizeClass
+{
+ GtkBinClass parent_class;
+} YGtkAdjSizeClass;
+
+GType ygtk_adj_size_get_type (void) G_GNUC_CONST;
+GtkWidget* ygtk_adj_size_new (void);
+
+void ygtk_adj_size_set_min (YGtkAdjSize *adj_size, guint min_width, guint min_height);
+void ygtk_adj_size_set_max (YGtkAdjSize *adj_size, guint max_width, guint max_height);
+
+/* Only allow the child to grow (ie. to ask for bigger sizes). */
+void ygtk_adj_size_set_only_expand (YGtkAdjSize *adj_size, gboolean only_expand);
+
+G_END_DECLS
+#endif /*YGTK_ADJ_SIZE_H*/
+
+/* YGtkScrolledWindow gives some a more fine-grained automatic scroll policy.
+ It allows the user to specify from which size scrolling should be applied. */
+#ifndef YGTK_SCROLLED_WIDOW_H
+#define YGTK_SCROLLED_WIDOW_H
+
+#include <gtk/gtkscrolledwindow.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_SCROLLED_WINDOW (ygtk_scrolled_window_get_type ())
+#define YGTK_SCROLLED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_SCROLLED_WINDOW, YGtkScrolledWindow))
+#define YGTK_SCROLLED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_SCROLLED_WINDOW, YGtkScrolledWindowClass))
+#define YGTK_IS_SCROLLED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_SCROLLED_WINDOW))
+#define YGTK_IS_SCROLLED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_SCROLLED_WINDOW))
+#define YGTK_SCROLLED_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_SCROLLED_WINDOW, YGtkScrolledWindowClass))
+
+typedef struct _YGtkScrolledWindow
+{
+ GtkScrolledWindow parent;
+ // members
+ guint max_width, max_height;
+} YGtkScrolledWindow;
+
+typedef struct _YGtkScrolledWindowClass
+{
+ GtkScrolledWindowClass parent_class;
+} YGtkScrolledWindowClass;
+
+GType ygtk_scrolled_window_get_type (void) G_GNUC_CONST;
+GtkWidget* ygtk_scrolled_window_new (GtkWidget *child /*or NULL*/);
+
+void ygtk_scrolled_window_set_auto_policy (YGtkScrolledWindow *scroll,
+ guint max_width, guint max_height);
+
+G_END_DECLS
+#endif /*YGTK_SCROLLED_WIDOW_H*/
Added: trunk/gtk/src/ygtkrichtext.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkrichtext.c?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkrichtext.c (added)
+++ trunk/gtk/src/ygtkrichtext.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,716 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkRichText widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkrichtext.h"
+#include <gtk/gtkversion.h>
+#include <string.h>
+
+#define IDENT_MARGIN 20
+#define PARAGRAPH_SPACING 12
+
+//#define PRINT_WARNINGS
+
+// Sucky - but we mix C & C++ so ...
+/* Convert html to xhtml (or at least try) */
+gchar *ygutils_convert_to_xhmlt_and_subst (const char *instr, const char *product);
+
+G_DEFINE_TYPE (YGtkRichText, ygtk_rich_text, GTK_TYPE_TEXT_VIEW)
+
+static GdkCursor *hand_cursor, *regular_cursor;
+static guint ref_cursor = 0;
+static guint link_clicked_signal;
+static GdkColor link_color = { 0, 0, 0, 0xeeee };
+
+// utilities
+// Looks at all tags covering the position of iter in the text view,
+// and returns the link the text points to, in case that text is a link.
+static const char* get_link (GtkTextView *text_view, gint x, gint y)
+{
+ GtkTextIter iter;
+ gtk_text_view_get_iter_at_location (text_view, &iter, x, y);
+
+ char *link = NULL;
+ GSList *tags = gtk_text_iter_get_tags (&iter), *tagp;
+ for (tagp = tags; tagp != NULL; tagp = tagp->next) {
+ GtkTextTag *tag = (GtkTextTag*) tagp->data;
+ link = (char*) g_object_get_data (G_OBJECT (tag), "link");
+ if (link)
+ break;
+ }
+
+ if (tags)
+ g_slist_free (tags);
+ return link;
+}
+
+// callbacks
+// Links can also be activated by clicking.
+static gboolean event_after (GtkWidget *text_view, GdkEvent *ev)
+{
+ GtkTextIter start, end;
+ GtkTextBuffer *buffer;
+ GdkEventButton *event;
+ gint x, y;
+
+ if (ev->type != GDK_BUTTON_RELEASE)
+ return FALSE;
+
+ event = (GdkEventButton *)ev;
+ if (event->button != 1)
+ return FALSE;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+ // We shouldn't follow a link if the user is selecting something.
+ gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+ if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
+ return FALSE;
+
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+ GTK_TEXT_WINDOW_WIDGET, (gint) event->x, (gint) event->y, &x, &y);
+
+ const char *link = get_link (GTK_TEXT_VIEW (text_view), x, y);
+ if (link) // report link
+ g_signal_emit (YGTK_RICH_TEXT (text_view), link_clicked_signal, 0, link);
+ return FALSE;
+}
+
+#include <stdlib.h>
+static int mystrcmp(void *a, void *b)
+{ return g_ascii_strcasecmp (*(char **)a, *(char **)b); }
+
+static gboolean isBlockTag (const char *tag)
+{
+ static const char *Tags[] =
+ { "blockquote", "h1", "h2", "h3", "h4", "h5", "li", "p", "pre" };
+ void *ret;
+ ret = bsearch (&tag, Tags, sizeof (Tags)/sizeof(char*), sizeof(char *), (void*)mystrcmp);
+ return ret != 0;
+}
+static gboolean isIdentTag (const char *tag)
+{
+ static const char *Tags[] =
+ { "blockquote", "ol", "ul" };
+ void *ret;
+ ret = bsearch (&tag, Tags, sizeof (Tags)/sizeof(char*), sizeof(char *), (void*)mystrcmp);
+ return ret != 0;
+}
+
+void ygtk_rich_text_init (YGtkRichText *rtext)
+{
+ rtext->prodname = NULL;
+
+ GtkTextView *tview = GTK_TEXT_VIEW (rtext);
+ gtk_text_view_set_wrap_mode (tview, GTK_WRAP_WORD_CHAR);
+ gtk_text_view_set_editable (tview, FALSE);
+ gtk_text_view_set_cursor_visible (tview, FALSE);
+ gtk_text_view_set_pixels_below_lines (tview, 4);
+
+ // Init link support
+ if (!ref_cursor) {
+ GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (rtext));
+ hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+ regular_cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+ }
+ ref_cursor++;
+
+#if GTK_CHECK_VERSION(2,10,0)
+ gtk_widget_style_get (GTK_WIDGET (rtext), "link_color", &link_color, NULL);
+#endif
+
+ g_signal_connect (tview, "event-after",
+ G_CALLBACK (event_after), NULL);
+
+ // Create a few tags like 'h3', 'b', 'i'. others need to be created as we parse
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (tview);
+ PangoFontDescription *font_desc = GTK_WIDGET (rtext)->style->font_desc;
+ int size = pango_font_description_get_size (font_desc);
+ if (pango_font_description_get_size_is_absolute (font_desc))
+ size /= PANGO_SCALE;
+
+ gtk_text_buffer_create_tag (buffer, "h1", "weight", PANGO_WEIGHT_HEAVY,
+ "size", (int)(size * PANGO_SCALE_XX_LARGE), "pixels-below-lines", 16, NULL);
+ gtk_text_buffer_create_tag (buffer, "h2", "weight", PANGO_WEIGHT_ULTRABOLD,
+ "size", (int)(size * PANGO_SCALE_X_LARGE), "pixels-below-lines", 15, NULL);
+ gtk_text_buffer_create_tag (buffer, "h3", "weight", PANGO_WEIGHT_BOLD,
+ "size", (int)(size * PANGO_SCALE_LARGE), "pixels-below-lines", 14, NULL);
+ gtk_text_buffer_create_tag (buffer, "h4", "weight", PANGO_WEIGHT_SEMIBOLD,
+ "size", (int)(size * PANGO_SCALE_LARGE), "pixels-below-lines", 13, NULL);
+ gtk_text_buffer_create_tag (buffer, "h5",
+ "size", (int)(size * PANGO_SCALE_LARGE), NULL);
+ gtk_text_buffer_create_tag (buffer, "p", "pixels-below-lines", 12, NULL);
+ gtk_text_buffer_create_tag (buffer, "big",
+ "size", (int)(size * PANGO_SCALE_LARGE), NULL);
+ gtk_text_buffer_create_tag (buffer, "small",
+ "size", (int)(size * PANGO_SCALE_SMALL), NULL);
+ gtk_text_buffer_create_tag (buffer, "tt", "family", "monospace", NULL);
+ gtk_text_buffer_create_tag (buffer, "pre", "family", "monospace", NULL);
+ gtk_text_buffer_create_tag (buffer, "b", "weight", PANGO_WEIGHT_BOLD, NULL);
+ gtk_text_buffer_create_tag (buffer, "i", "style", PANGO_STYLE_ITALIC, NULL);
+ gtk_text_buffer_create_tag (buffer, "u", "underline", PANGO_UNDERLINE_SINGLE, NULL);
+ gtk_text_buffer_create_tag (buffer, "center", "justification", GTK_JUSTIFY_CENTER,
+ NULL);
+ // helpers
+ gtk_text_buffer_create_tag (buffer, "keyword", "background", "yellow", NULL);
+}
+
+static void ygtk_rich_text_destroy (GtkObject *object)
+{
+ YGtkRichText *rtext = YGTK_RICH_TEXT (object);
+
+ if (rtext->prodname)
+ // destroy can be called multiple times, and we must ref only once
+ if (ref_cursor > 0 && (--ref_cursor == 0)) {
+ gdk_cursor_unref (hand_cursor);
+ gdk_cursor_unref (regular_cursor);
+ }
+
+ if (rtext->prodname)
+ g_free (rtext->prodname);
+ rtext->prodname = NULL;
+
+ GTK_OBJECT_CLASS (ygtk_rich_text_parent_class)->destroy (object);
+}
+
+// Change the cursor to the "hands" cursor typically used by web browsers,
+// if there is a link in the given position.
+static void set_cursor_if_appropriate (GtkTextView *text_view, gint x, gint y)
+ {
+ static gboolean hovering_over_link = FALSE;
+ gboolean hovering = get_link (text_view, x, y) != NULL;
+
+ if (hovering != hovering_over_link) {
+ hovering_over_link = hovering;
+
+ if (hovering_over_link)
+ gdk_window_set_cursor (gtk_text_view_get_window
+ (text_view, GTK_TEXT_WINDOW_TEXT), hand_cursor);
+ else
+ gdk_window_set_cursor (gtk_text_view_get_window
+ (text_view, GTK_TEXT_WINDOW_TEXT), regular_cursor);
+ }
+}
+
+// Update the cursor image if the pointer moved.
+static gboolean ygtk_rich_text_motion_notify_event (GtkWidget *text_view,
+ GdkEventMotion *event)
+{
+ gint x, y;
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+ GTK_TEXT_WINDOW_WIDGET,
+ (gint) event->x, (gint) event->y,
+ &x, &y);
+ set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);
+
+ gdk_window_get_pointer (text_view->window, NULL, NULL, NULL);
+ return TRUE;
+}
+
+// Also update the cursor image if the window becomes visible
+// (e.g. when a window covering it got iconified).
+static gboolean ygtk_rich_text_visibility_notify_event (GtkWidget *text_view,
+ GdkEventVisibility *event)
+{
+ gint wx, wy, bx, by;
+
+ gdk_window_get_pointer (text_view->window, &wx, &wy, NULL);
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
+ GTK_TEXT_WINDOW_WIDGET,
+ wx, wy, &bx, &by);
+ set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), bx, by);
+ return TRUE;
+}
+
+/* Rich Text parsing methods. */
+
+typedef struct _HTMLList
+{
+ gboolean ordered;
+ char enumeration;
+} HTMLList;
+
+static void HTMLList_init (HTMLList *list, gboolean ordered)
+{
+ list->ordered = ordered;
+ list->enumeration = 1;
+}
+
+typedef struct GRTPTag {
+ GtkTextMark *mark;
+ GtkTextTag *tag;
+} GRTPTag;
+typedef struct GRTParseState {
+ GtkTextBuffer *buffer;
+ GtkTextTagTable *tags;
+ GList *htags; // of GRTPTag
+
+ // Attributes for tags that affect their children
+ gboolean pre_mode;
+ gboolean default_color;
+ int left_margin;
+ GList *html_list; // of HTMLList
+} GRTParseState;
+
+static void GRTParseState_init (GRTParseState *state, GtkTextBuffer *buffer)
+{
+ state->buffer = buffer;
+ state->pre_mode = FALSE;
+ state->default_color = TRUE;
+ state->left_margin = 0;
+ state->tags = gtk_text_buffer_get_tag_table (buffer);
+ state->html_list = NULL;
+ state->htags = NULL;
+}
+
+static void free_list (GList *list)
+{
+ GList *i;
+ for (i = g_list_first (list); i; i = i->next)
+ g_free (i->data);
+ g_list_free (list);
+}
+
+static void GRTParseState_free (GRTParseState *state)
+{
+ // NOTE: some elements might not have been freed because of bad html
+ free_list (state->html_list);
+ free_list (state->htags);
+}
+
+static char *elide_whitespace (const char *instr, int len);
+
+// Tags to support: <p> and not </p>:
+// either 'elide' \ns (turn off with <pre> I guess
+static void
+rt_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{ // Called for open tags <foo bar="baz">
+ if (!g_ascii_strcasecmp (element_name, "body"))
+ return;
+
+ GRTParseState *state = (GRTParseState*) user_data;
+ GRTPTag *tag = g_malloc (sizeof (GRTPTag));
+ GtkTextIter iter;
+ gtk_text_buffer_get_end_iter (state->buffer, &iter);
+ tag->mark = gtk_text_buffer_create_mark (state->buffer, NULL, &iter, TRUE);
+
+ if (!g_ascii_strcasecmp (element_name, "pre"))
+ state->pre_mode = TRUE;
+
+ // Check if this is a block tag
+ if (isBlockTag (element_name)) {
+ // make sure this opens a new paragraph
+ if (!gtk_text_iter_starts_line (&iter))
+ {
+ gtk_text_buffer_insert (state->buffer, &iter, "\n", -1);
+ gtk_text_buffer_get_end_iter (state->buffer, &iter);
+ }
+ }
+
+ char *lower = g_ascii_strdown (element_name, -1);
+ tag->tag = gtk_text_tag_table_lookup (state->tags, lower);
+
+ // Special tags that must be inserted manually
+ if (!tag->tag) {
+ if (!g_ascii_strcasecmp (element_name, "font")) {
+ if (attribute_names[0] &&
+ !g_ascii_strcasecmp (attribute_names[0], "color")) {
+ tag->tag = gtk_text_buffer_create_tag (state->buffer, NULL,
+ "foreground", attribute_values[0],
+ NULL);
+ state->default_color = FALSE;
+ }
+#ifdef PRINT_WARNINGS
+ else
+ g_warning ("Unknown font attribute: '%s'", attribute_names[0]);
+#endif
+ }
+ else if (!g_ascii_strcasecmp (element_name, "a")) {
+ if (attribute_names[0] &&
+ !g_ascii_strcasecmp (attribute_names[0], "href")) {
+ tag->tag = gtk_text_buffer_create_tag (state->buffer, NULL,
+ "underline", PANGO_UNDERLINE_SINGLE,
+ NULL);
+ if (state->default_color)
+ g_object_set (tag->tag, "foreground-gdk", &link_color, NULL);
+ g_object_set_data (G_OBJECT (tag->tag), "link", g_strdup (attribute_values[0]));
+ }
+#ifdef PRINT_WARNINGS
+ else
+ g_warning ("Unknown a attribute: '%s'", attribute_names[0]);
+#endif
+ }
+ else if (!g_ascii_strcasecmp (element_name, "li")) {
+ HTMLList *front_list;
+
+ if (state->html_list &&
+ (front_list = g_list_first (state->html_list)->data) &&
+ (front_list->ordered)) {;
+ gchar *str = g_strdup_printf ("%d. ", front_list->enumeration++);
+ gtk_text_buffer_insert (state->buffer, &iter, str, -1);
+ g_free (str);
+ }
+ else { // \\u25cf for bigger bullets
+ gtk_text_buffer_insert (state->buffer, &iter, "\u2022 ", -1);
+ }
+ }
+ // Tags that affect the margin
+ else if (!g_ascii_strcasecmp (element_name, "ul") ||
+ !g_ascii_strcasecmp (element_name, "ol")) {
+ HTMLList *list = g_malloc (sizeof (HTMLList));
+ HTMLList_init (list, !g_ascii_strcasecmp (element_name, "ol"));
+ state->html_list = g_list_append (state->html_list, list);
+ }
+
+ else if (!g_ascii_strcasecmp (element_name, "img")) {
+ if (attribute_names[0] &&
+ !g_ascii_strcasecmp (attribute_names[0], "src")) {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (attribute_values[0], NULL);
+ if (pixbuf) {
+ gtk_text_buffer_insert_pixbuf (state->buffer, &iter, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ }
+ }
+#ifdef PRINT_WARNINGS
+ else
+ g_warning ("Unknown img attribute: '%s'", attribute_names[0]);
+#endif
+ }
+
+ // for tags like <br/>, GMarkup will pass them through the end
+ // tag callback too, so we'll deal with them there
+ else if (!g_ascii_strcasecmp (element_name, "br"))
+ ;
+
+ else
+ {
+#ifdef PRINT_WARNINGS
+ if (isBlockTag (element_name))
+ ;
+ else
+ g_warning ("Unknown tag '%s'", element_name);
+#endif
+ }
+ }
+
+ if (!tag->tag && isIdentTag (element_name)) {
+ state->left_margin += IDENT_MARGIN;
+ tag->tag = gtk_text_buffer_create_tag (state->buffer, NULL,
+ "left-margin", state->left_margin, NULL);
+ }
+
+ g_free (lower);
+ state->htags = g_list_append (state->htags, tag);
+}
+
+static void
+rt_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{ // Called for close tags </foo>
+ if (!g_ascii_strcasecmp (element_name, "body"))
+ return;
+
+ GRTParseState *state = (GRTParseState*) user_data;
+
+ if (g_list_length (state->htags) == 0) {
+ g_warning ("Urgh - empty tag queue closing '%s'", element_name);
+ return;
+ }
+
+ g_return_if_fail (state->htags != NULL);
+ GRTPTag *tag = g_list_last (state->htags)->data;
+ state->htags = g_list_remove (state->htags, tag);
+
+ GtkTextIter start, end;
+ gtk_text_buffer_get_iter_at_mark (state->buffer, &start, tag->mark);
+ gtk_text_buffer_get_end_iter (state->buffer, &end);
+
+ gint appendLines = 0;
+
+ if (isIdentTag (element_name))
+ state->left_margin -= IDENT_MARGIN;
+
+ if (!g_ascii_strcasecmp (element_name, "ul") ||
+ !g_ascii_strcasecmp (element_name, "ol")) {
+ HTMLList *last_list = g_list_last (state->html_list)->data;
+ state->html_list = g_list_remove (state->html_list, last_list);
+ g_free (last_list);
+ }
+ else if (!g_ascii_strcasecmp (element_name, "font"))
+ state->default_color = TRUE;
+
+ else if (!g_ascii_strcasecmp (element_name, "pre")) {
+ state->pre_mode = FALSE;
+/*
+ // \n must be inserted as <br>
+ char *txt = gtk_text_buffer_get_text (state->buffer,
+ &start, &end, TRUE);
+ char endc = txt ? txt[strlen(txt) - 1] : '\0';
+ appendLines = (endc != '\r' && endc != '\n') ? 1 : 0;
+ g_free (txt);*/
+ }
+
+ else if (!g_ascii_strcasecmp (element_name, "br"))
+ appendLines = 1;
+
+ if (isBlockTag (element_name))
+ {
+// appendLines = 2;
+// if (!g_ascii_strcasecmp (element_name, "li"))
+ appendLines = 1;
+ }
+
+
+ if (appendLines) {
+ gtk_text_buffer_insert (state->buffer, &end,
+ appendLines == 1 ? "\n" : "\n\n", -1);
+ gtk_text_buffer_get_iter_at_mark (state->buffer, &start, tag->mark);
+ gtk_text_buffer_get_end_iter (state->buffer, &end);
+ }
+
+ if (tag->tag)
+ gtk_text_buffer_apply_tag (state->buffer, tag->tag, &start, &end);
+
+ gtk_text_buffer_delete_mark (state->buffer, tag->mark);
+ g_free (tag);
+}
+
+static void
+rt_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{ // Called for character data, NB. text NOT nul-terminated
+ GRTParseState *state = (GRTParseState*) user_data;
+ GtkTextIter start, end;
+ gtk_text_buffer_get_end_iter (state->buffer, &start);
+ if (state->pre_mode)
+ gtk_text_buffer_insert_with_tags (state->buffer, &start,
+ text, text_len, NULL, NULL);
+ else {
+ char *real = elide_whitespace (text, text_len);
+ gtk_text_buffer_insert_with_tags (state->buffer, &start,
+ real, -1, NULL, NULL);
+ g_free (real);
+ }
+ gtk_text_buffer_get_end_iter (state->buffer, &end);
+}
+
+static void
+rt_passthrough (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ // ignore comments etc.
+}
+
+static void
+rt_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+}
+
+static GMarkupParser rt_parser = {
+ rt_start_element,
+ rt_end_element,
+ rt_text,
+ rt_passthrough,
+ rt_error
+};
+
+GtkWidget *ygtk_rich_text_new (void)
+{
+ return g_object_new (YGTK_TYPE_RICH_TEXT, NULL);
+}
+
+/* String preparation methods. */
+
+#define IS_WHITE(c) (g_ascii_isspace (c) || (c) == '\t')
+
+static char *elide_whitespace (const char *instr, int len)
+{
+ GString *dest = g_string_new ("");
+ if (len < 0)
+ len = strlen (instr);
+ gboolean last_white = FALSE;
+ int i;
+// FIXME: whitespace elision needs to happen across tags [urk]
+// FIXME: perhaps post-process non-pre sections when they are complete ?
+ for (i = 0; i < len; i++)
+ {
+ char ch = instr[i];
+ if (ch == '\r' || ch == '\n')
+ continue;
+ if (ch == '\t')
+ ch = ' ';
+ gboolean cur_white = IS_WHITE (ch);
+ if (!cur_white || !last_white)
+ g_string_append_c (dest, ch);
+ last_white = cur_white;
+ }
+
+ return g_string_free (dest, FALSE);
+}
+
+void ygtk_richttext_set_prodname (YGtkRichText *rtext, const char *prodname)
+{
+ rtext->prodname = g_strdup (prodname);
+}
+
+void ygtk_rich_text_set_text (YGtkRichText* rtext, const gchar* text,
+ gboolean rich_text)
+{
+ GtkTextBuffer *buffer;
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (rtext));
+
+ if (!rich_text) {
+ gtk_text_buffer_set_text (buffer, text, -1);
+ return;
+ }
+
+ // remove any possible existing text
+ gtk_text_buffer_set_text (buffer, "", 0);
+
+ GRTParseState state;
+ GRTParseState_init (&state, buffer);
+
+ GMarkupParseContext *ctx;
+ ctx = g_markup_parse_context_new (&rt_parser, (GMarkupParseFlags)0, &state, NULL);
+
+ char *xml = ygutils_convert_to_xhmlt_and_subst (text, rtext->prodname);
+ GError *error = NULL;
+ if (!g_markup_parse_context_parse (ctx, xml, -1, &error)) {
+#ifdef PRINT_WARNINGS
+ g_warning ("Markup parse error '%s'", error ? error->message : "Unknown");
+#endif
+ }
+ g_free (xml);
+
+ g_markup_parse_context_free (ctx);
+ GRTParseState_free (&state);
+
+ // remove last empty line, if any
+ GtkTextIter end_it, before_end_it;
+ gtk_text_buffer_get_end_iter (buffer, &end_it);
+ before_end_it = end_it;
+ if (gtk_text_iter_backward_char (&before_end_it) &&
+ gtk_text_iter_get_char (&before_end_it) == '\n')
+ gtk_text_buffer_delete (buffer, &before_end_it, &end_it);
+}
+
+/* gtk_text_iter_forward_search() is case-sensitive so we roll our own.
+ The idea is to keep use get_text and strstr there, but to be more
+ efficient we check per line. */
+static gboolean ygtk_rich_text_forward_search (const GtkTextIter *begin,
+ const GtkTextIter *end, const gchar *_key, GtkTextIter *match_start,
+ GtkTextIter *match_end)
+{
+ if (*_key == 0)
+ return FALSE;
+
+ /* gtk_text_iter_get_char() returns a gunichar (ucs4 coding), so we
+ convert the given string (which is utf-8, like anyhting in gtk+) */
+ gunichar *key = g_utf8_to_ucs4 (_key, -1, NULL, NULL, NULL);
+ if (!key) // conversion error -- should not happen
+ return FALSE;
+
+ // convert key to lower case, to avoid work later
+ gunichar *k;
+ for (k = key; *k; k++)
+ *k = g_unichar_tolower (*k);
+
+ GtkTextIter iter = *begin, iiter;
+ while (!gtk_text_iter_is_end (&iter) && gtk_text_iter_compare (&iter, end) <= 0) {
+ iiter = iter;
+ for (k = key; *k == g_unichar_tolower (gtk_text_iter_get_char (&iiter)) && (*k);
+ k++, gtk_text_iter_forward_char (&iiter))
+ ;
+ if (!*k) {
+ *match_start = iter;
+ *match_end = iiter;
+ return TRUE;
+ }
+ gtk_text_iter_forward_char (&iter);
+ }
+ return FALSE;
+}
+
+gboolean ygtk_rich_text_mark_text (YGtkRichText *rtext, const gchar *text)
+{
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (rtext));
+ GtkTextIter iter, end, match_start, match_end;
+
+ gtk_text_buffer_get_bounds (buffer, &iter, &end);
+ gtk_text_buffer_remove_tag_by_name (buffer, "keyword", &iter, &end);
+
+ gtk_text_buffer_select_range (buffer, &iter, &iter); // unselect text
+ if (!text || *text == '\0')
+ return TRUE;
+
+ gboolean found = FALSE;
+ while (ygtk_rich_text_forward_search (&iter, &end, text,
+ &match_start, &match_end)) {
+ found = TRUE;
+ gtk_text_buffer_apply_tag_by_name (buffer, "keyword", &match_start, &match_end);
+ iter = match_end;
+ gtk_text_iter_forward_char (&iter);
+ }
+ return found;
+}
+
+gboolean ygtk_rich_text_forward_mark (YGtkRichText *rtext, const gchar *text)
+{
+ GtkTextIter start_iter, end_iter;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (rtext));
+ gtk_text_buffer_get_iter_at_mark (buffer, &start_iter,
+ gtk_text_buffer_get_selection_bound (buffer));
+ gtk_text_buffer_get_end_iter (buffer, &end_iter);
+
+ gboolean found;
+ found = ygtk_rich_text_forward_search (&start_iter, &end_iter, text,
+ &start_iter, &end_iter);
+ if (!found) {
+ gtk_text_buffer_get_start_iter (buffer, &start_iter);
+ found = ygtk_rich_text_forward_search (&start_iter, &end_iter, text,
+ &start_iter, &end_iter);
+ }
+
+ if (found) {
+ gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (rtext), &start_iter, 0.10,
+ FALSE, 0, 0);
+ gtk_text_buffer_select_range (buffer, &start_iter, &end_iter);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void ygtk_rich_text_class_init (YGtkRichTextClass *klass)
+{
+ GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
+ gtkwidget_class->motion_notify_event = ygtk_rich_text_motion_notify_event;
+ gtkwidget_class->visibility_notify_event = ygtk_rich_text_visibility_notify_event;
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_rich_text_destroy;
+
+ link_clicked_signal = g_signal_new ("link-clicked",
+ G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (YGtkRichTextClass, link_clicked), NULL, NULL,
+ g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+}
+
Added: trunk/gtk/src/ygtkrichtext.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkrichtext.h?rev=42515…
==============================================================================
--- trunk/gtk/src/ygtkrichtext.h (added)
+++ trunk/gtk/src/ygtkrichtext.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,59 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkRichText is a very simple widget that displays HTML code.
+ It was done, since GTK+ doesn't offer one out of box, and to
+ avoid dependencies.
+*/
+
+#ifndef YGTK_RICH_TEXT_H
+#define YGTK_RICH_TEXT_H
+
+#include <gtk/gtktextview.h>
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_RICH_TEXT (ygtk_rich_text_get_type ())
+#define YGTK_RICH_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_RICH_TEXT, YGtkRichText))
+#define YGTK_RICH_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_RICH_TEXT, YGtkRichTextClass))
+#define YGTK_IS_RICH_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_RICH_TEXT))
+#define YGTK_IS_RICH_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_RICH_TEXT))
+#define YGTK_RICH_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_RICH_TEXT, YGtkRichTextClass))
+
+typedef struct _YGtkRichText
+{
+ GtkTextView parent;
+ // private:
+ char *prodname;
+} YGtkRichText;
+
+typedef struct _YGtkRichTextClass
+{
+ GtkTextViewClass parent_class;
+
+ // signals:
+ void (*link_clicked) (YGtkRichText *rich_text, const gchar *link);
+} YGtkRichTextClass;
+
+GtkWidget* ygtk_rich_text_new (void);
+GType ygtk_rich_text_get_type (void) G_GNUC_CONST;
+
+/* Sets some text to YGtkRichText, may be HTML or plain text, as indicated by
+ rich_text. */
+void ygtk_rich_text_set_text (YGtkRichText* rtext, const gchar* text,
+ gboolean rich_text);
+
+void ygtk_richttext_set_prodname (YGtkRichText *rtext, const char *prodname);
+
+// To be used together with an entry box to search for text
+gboolean ygtk_rich_text_mark_text (YGtkRichText *rtext, const gchar *text);
+gboolean ygtk_rich_text_forward_mark (YGtkRichText *rtext, const gchar *text); // F3
+
+G_END_DECLS
+#endif /* YGTK_RICH_TEXT_H */
+
Added: trunk/gtk/src/ygtksteps.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtksteps.c?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/ygtksteps.c (added)
+++ trunk/gtk/src/ygtksteps.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,324 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkSteps widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtksteps.h"
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkalignment.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkimage.h>
+#include <string.h>
+
+#define BORDER 6
+#define STEPS_HEADER_SPACING 8
+#define STEPS_SPACING 2
+#define STEPS_IDENTATION 30
+#define CURRENT_MARK_ANIMATION_TIME 250
+#define CURRENT_MARK_ANIMATION_OFFSET 3
+#define CURRENT_MARK_FRAMES_NB (CURRENT_MARK_ANIMATION_OFFSET*2)
+
+G_DEFINE_TYPE (YGtkSteps, ygtk_steps, GTK_TYPE_WIDGET)
+
+static void ygtk_steps_init (YGtkSteps *steps)
+{
+ GTK_WIDGET_SET_FLAGS (steps, GTK_NO_WINDOW);
+
+ PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET (steps));
+ steps->check_mark_layout = pango_layout_new (context);
+ steps->current_mark_layout = pango_layout_new (context);
+ pango_layout_set_markup (steps->check_mark_layout, "\u2714", -1);
+ pango_layout_set_markup (steps->current_mark_layout, "<b>\u2192</b>", -1);
+ steps->current_mark_timeout_id = steps->current_mark_frame = 0;
+}
+
+static void ygtk_steps_destroy (GtkObject *object)
+{
+ YGtkSteps *steps = YGTK_STEPS (object);
+
+ if (steps->current_mark_timeout_id) {
+ g_source_remove (steps->current_mark_timeout_id);
+ steps->current_mark_timeout_id = 0;
+ }
+
+ g_object_unref (steps->check_mark_layout);
+ steps->check_mark_layout = NULL;
+
+ g_object_unref (steps->current_mark_layout);
+ steps->current_mark_layout = NULL;
+
+ ygtk_steps_clear (steps);
+ GTK_OBJECT_CLASS (ygtk_steps_parent_class)->destroy (object);
+}
+
+
+static inline YGtkSingleStep *ygtk_steps_get_step (YGtkSteps *steps, guint step_nb)
+{
+ return g_list_nth_data (steps->steps, step_nb);
+}
+
+static void ygtk_step_invalidate_layout (YGtkSingleStep *step)
+{
+ if (step->layout) {
+ g_object_unref (G_OBJECT (step->layout));
+ step->layout = NULL;
+ }
+ if (step->layout_bold) {
+ g_object_unref (G_OBJECT (step->layout_bold));
+ step->layout_bold = NULL;
+ }
+}
+
+// should be called rather than accessing step->layout
+static PangoLayout *ygtk_steps_get_step_layout (YGtkSteps *steps, guint step_nb)
+{
+ YGtkSingleStep *step = ygtk_steps_get_step (steps, step_nb);
+
+ if (!step->layout) {
+ step->layout = gtk_widget_create_pango_layout (GTK_WIDGET (steps), NULL);
+
+ gchar *text, *text_bold = 0;
+ if (step->is_heading) {
+ text = g_strdup_printf ("<span size=\"x-large\" weight=\"heavy\">%s</span>",
+ step->text);
+ pango_layout_set_spacing (step->layout, STEPS_HEADER_SPACING * PANGO_SCALE);
+ }
+ else {
+ if (!step->layout_bold)
+ step->layout_bold = gtk_widget_create_pango_layout (GTK_WIDGET (steps), NULL);
+ g_assert (step->layout_bold);
+ text = g_strdup (step->text);
+ text_bold = g_strdup_printf ("<b>%s</b>", step->text);
+ pango_layout_set_indent (step->layout, STEPS_IDENTATION * PANGO_SCALE);
+ pango_layout_set_indent (step->layout_bold, STEPS_IDENTATION * PANGO_SCALE);
+ pango_layout_set_spacing (step->layout, STEPS_SPACING * PANGO_SCALE);
+ pango_layout_set_spacing (step->layout_bold, STEPS_SPACING * PANGO_SCALE);
+ }
+
+ pango_layout_set_markup (step->layout, text, -1);
+ g_free (text);
+ if (step->layout_bold)
+ {
+ pango_layout_set_markup (step->layout_bold, text_bold, -1);
+ g_free (text_bold);
+ }
+ }
+
+ if (steps->current_step == step_nb)
+ return step->layout_bold;
+ return step->layout;
+}
+
+// If PangoContext got invalidated (eg. system language change), re-compute it!
+static void ygtk_steps_recompute_layout (YGtkSteps *steps)
+{
+ GList *it;
+ for (it = steps->steps; it; it = it->next) {
+ YGtkSingleStep *step = it->data;
+ if (step->layout)
+ pango_layout_context_changed (step->layout);
+ if (step->layout_bold)
+ pango_layout_context_changed (step->layout_bold);
+ }
+}
+
+static void ygtk_steps_direction_changed (GtkWidget *widget, GtkTextDirection dir)
+{
+ ygtk_steps_recompute_layout (YGTK_STEPS (widget));
+ GTK_WIDGET_CLASS (ygtk_steps_parent_class)->direction_changed (widget, dir);
+}
+
+static void ygtk_steps_style_set (GtkWidget *widget, GtkStyle *style)
+{
+ ygtk_steps_recompute_layout (YGTK_STEPS (widget));
+ GTK_WIDGET_CLASS (ygtk_steps_parent_class)->style_set (widget, style);
+}
+
+static void ygtk_steps_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ requisition->width = requisition->height = 0;
+
+ YGtkSteps *steps = YGTK_STEPS (widget);
+ int i;
+ for (i = 0; i < ygtk_steps_total (steps); i++) {
+ PangoLayout *layout = ygtk_steps_get_step_layout (steps, i);
+ YGtkSingleStep *step = ygtk_steps_get_step (steps, i);
+ if (!step->is_heading)
+ layout = step->layout_bold;
+
+ int w, h;
+ pango_layout_get_pixel_size (layout, &w, &h);
+ w += PANGO_PIXELS (pango_layout_get_indent (layout));
+ h += PANGO_PIXELS (pango_layout_get_spacing (layout)) * 2;
+
+ requisition->width = MAX (w, requisition->width);
+ requisition->height += h;
+ }
+
+ requisition->width += BORDER * 2;
+ requisition->height += BORDER * 2;
+}
+
+static gboolean ygtk_steps_expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ int x = widget->allocation.x + BORDER, y = widget->allocation.y + BORDER;
+ GtkStyle *style = gtk_widget_get_style (widget);
+
+ YGtkSteps *steps = YGTK_STEPS (widget);
+ int i;
+ for (i = 0; i < ygtk_steps_total (steps); i++) {
+ PangoLayout *layout = ygtk_steps_get_step_layout (steps, i);
+
+ // as opposite to identation, we need to apply spacing ourselves, since we aren't
+ // really using paragraphs
+ y += PANGO_PIXELS (pango_layout_get_spacing (layout));
+
+ gtk_paint_layout (style, widget->window, GTK_STATE_NORMAL, TRUE,
+ NULL, /*event->area,*/ widget, NULL, x, y, layout);
+
+ if (i <= steps->current_step && !ygtk_steps_get_step (steps, i)->is_heading) {
+ PangoLayout *mark = (i == steps->current_step) ? steps->current_mark_layout
+ : steps->check_mark_layout;
+ int x_;
+ pango_layout_get_pixel_size (mark, &x_, NULL);
+ x_ = x + STEPS_IDENTATION - x_ - 6;
+ if (i == steps->current_step) {
+ if (steps->current_mark_frame < CURRENT_MARK_FRAMES_NB/2)
+ x_ -= steps->current_mark_frame * CURRENT_MARK_ANIMATION_OFFSET;
+ else
+ x_ -= (CURRENT_MARK_FRAMES_NB - steps->current_mark_frame) *
+ CURRENT_MARK_ANIMATION_OFFSET;
+ }
+
+ gtk_paint_layout (style, widget->window, GTK_STATE_NORMAL, TRUE,
+ NULL, /*event->area,*/ widget, NULL, x_, y, mark);
+ }
+
+ int h;
+ pango_layout_get_pixel_size (layout, NULL, &h);
+ // we need spacing for both sides
+ y += h + PANGO_PIXELS (pango_layout_get_spacing (layout));
+ }
+ return FALSE;
+}
+
+GtkWidget* ygtk_steps_new (void)
+{
+ return g_object_new (YGTK_TYPE_STEPS, NULL);
+}
+
+guint ygtk_steps_append (YGtkSteps *steps, const gchar *step_text)
+{
+ gint steps_nb;
+
+ g_return_val_if_fail (YGTK_IS_STEPS (steps), 0);
+
+ steps_nb = ygtk_steps_total (steps);
+
+ // check if the text is the same as the previous...
+ if (steps_nb) {
+ YGtkSingleStep *last_step = g_list_last (steps->steps)->data;
+ if (!g_strcasecmp (last_step->text, step_text)) {
+ last_step->strength++;
+ return steps_nb-1;
+ }
+ }
+
+ // New step
+ YGtkSingleStep *step = g_new0 (YGtkSingleStep, 1);
+ step->is_heading = FALSE;
+ step->text = g_strdup (step_text);
+ step->strength = 1;
+ step->layout = step->layout_bold = NULL;
+
+ steps->steps = g_list_append (steps->steps, step);
+ gtk_widget_queue_resize (GTK_WIDGET (steps));
+ return steps_nb;
+}
+
+void ygtk_steps_append_heading (YGtkSteps *steps, const gchar *heading)
+{
+ YGtkSingleStep *step;
+
+ g_return_if_fail (YGTK_IS_STEPS (steps));
+
+ step = g_new0 (YGtkSingleStep, 1);
+ step->is_heading = TRUE;
+ step->text = g_strdup (heading);
+ step->strength = 1; // not important anyway
+ step->layout = step->layout_bold = NULL;
+
+ steps->steps = g_list_append (steps->steps, step);
+ gtk_widget_queue_resize (GTK_WIDGET (steps));
+}
+
+void ygtk_steps_advance (YGtkSteps *steps)
+{
+ if (steps->current_step + 1 < ygtk_steps_total (steps))
+ ygtk_steps_set_current (steps, steps->current_step + 1);
+}
+
+static gboolean current_mark_animation_cb (void *steps_ptr)
+{
+ YGtkSteps *steps = steps_ptr;
+
+ // ugly -- should use gtk_widget_queue_draw_area (widget, x, y, w, h)
+ // but we need to iterate through all steps to get current location and
+ // all, so...
+ gtk_widget_queue_draw (GTK_WIDGET (steps));
+
+ if (++steps->current_mark_frame == CURRENT_MARK_FRAMES_NB) {
+ steps->current_mark_frame = 0;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void ygtk_steps_set_current (YGtkSteps *steps, guint step)
+{
+ guint old_step = steps->current_step;
+ steps->current_step = step;
+
+ // update step icons
+ ygtk_step_invalidate_layout (ygtk_steps_get_step (steps, old_step));
+ ygtk_step_invalidate_layout (ygtk_steps_get_step (steps, step));
+
+ steps->current_mark_frame = 0;
+ steps->current_mark_timeout_id = g_timeout_add
+ (CURRENT_MARK_ANIMATION_TIME / CURRENT_MARK_FRAMES_NB,
+ current_mark_animation_cb, steps);
+}
+
+guint ygtk_steps_total (YGtkSteps *steps)
+{
+ return g_list_length (steps->steps);
+}
+
+void ygtk_steps_clear (YGtkSteps *steps)
+{
+ GList *it;
+ for (it = steps->steps; it; it = it->next) {
+ YGtkSingleStep *step = it->data;
+ ygtk_step_invalidate_layout (step);
+ g_free (step->text);
+ g_free (step);
+ }
+ g_list_free (steps->steps);
+ steps->steps = NULL;
+}
+
+static void ygtk_steps_class_init (YGtkStepsClass *klass)
+{
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->expose_event = ygtk_steps_expose_event;
+ widget_class->size_request = ygtk_steps_size_request;
+ widget_class->direction_changed = ygtk_steps_direction_changed;
+ widget_class->style_set = ygtk_steps_style_set;
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_steps_destroy;
+}
+
Added: trunk/gtk/src/ygtksteps.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtksteps.h?rev=42515&vi…
==============================================================================
--- trunk/gtk/src/ygtksteps.h (added)
+++ trunk/gtk/src/ygtksteps.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,82 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkSteps is a widget that displays a list of steps, useful
+ to show the progress of some configuration tool as it does
+ the work of updating files or services or whatever.
+
+ You use the append functions to initializate the steps. If,
+ for some reason, you want one step to count as more than one
+ (ie. so that a ygtk_steps_advance() needs to be called more than
+ once to actually advance for a given step), you may append a
+ step with the same name of the previous, that they'll be collapsed.
+ (Internally, we call that the 'strength' of the step.)
+
+ TODO: the PangoLayout usage is getting a bit hacky. We may want to
+ replace it with Cairo methods.
+*/
+
+#ifndef YGTK_STEPS_H
+#define YGTK_STEPS_H
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define YGTK_TYPE_STEPS (ygtk_steps_get_type ())
+#define YGTK_STEPS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_STEPS, YGtkSteps))
+#define YGTK_STEPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_STEPS, YGtkStepsClass))
+#define YGTK_IS_STEPS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_STEPS))
+#define YGTK_IS_STEPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_STEPS))
+#define YGTK_STEPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_STEPS, YGtkStepsClass))
+
+typedef struct _YGtkSteps
+{
+ GtkWidget parent;
+
+ // private:
+ GList *steps; // of YGtkSingleStep
+ guint current_step;
+ PangoLayout *check_mark_layout, *current_mark_layout;
+ // for current_mark little animation
+ guint current_mark_timeout_id, current_mark_frame;
+
+} YGtkSteps;
+
+typedef struct _YGtkStepsClass
+{
+ GtkWidgetClass parent_class;
+} YGtkStepsClass;
+
+typedef struct _YGtkSingleStep
+{
+ gboolean is_heading;
+ gchar *text;
+ guint strength; // check the text at top
+
+ // private -- don't access it, call ygtk_step_get_layout() instead
+ PangoLayout *layout, *layout_bold; // cache
+} YGtkSingleStep;
+
+GtkWidget* ygtk_steps_new (void);
+GType ygtk_steps_get_type (void) G_GNUC_CONST;
+
+guint ygtk_steps_append (YGtkSteps *steps, const gchar *label);
+void ygtk_steps_append_heading (YGtkSteps *steps, const gchar *heading);
+
+void ygtk_steps_advance (YGtkSteps *steps);
+void ygtk_steps_set_current (YGtkSteps *steps, guint step);
+guint ygtk_steps_total (YGtkSteps *steps);
+
+void ygtk_steps_clear (YGtkSteps *steps);
+
+G_END_DECLS
+
+#endif /* YGTK_STEPS_H */
Added: trunk/gtk/src/ygtkwizard.c
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkwizard.c?rev=42515&v…
==============================================================================
--- trunk/gtk/src/ygtkwizard.c (added)
+++ trunk/gtk/src/ygtkwizard.c Thu Nov 29 18:25:41 2007
@@ -0,0 +1,1249 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkWizard widget */
+// check the header file for information about this widget
+
+#include <config.h>
+#include "ygtkwizard.h"
+#include <atk/atk.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <string.h>
+#include "ygtkhtmlwrap.h"
+#include "ygtksteps.h"
+#include "ygtkfindentry.h"
+
+#define BUTTONS_SPACING 12
+#define BORDER 4
+#define CHILD_BORDER 6
+
+// YGUtils bridge
+extern void ygutils_setWidgetFont (GtkWidget *widget, PangoWeight weight,
+ double scale);
+extern void ygutils_setStockIcon (GtkWidget *button, const char *ycp_str);
+
+//** YGtkHelpDialog
+
+G_DEFINE_TYPE (YGtkHelpDialog, ygtk_help_dialog, GTK_TYPE_WINDOW)
+
+// callbacks
+static void ygtk_help_dialog_find_next (YGtkHelpDialog *dialog)
+{
+ const gchar *text = gtk_entry_get_text (GTK_ENTRY (dialog->search_entry));
+ ygtk_html_wrap_search_next (dialog->help_text, text);
+}
+
+static void search_entry_modified_cb (GtkEditable *editable, YGtkHelpDialog *dialog)
+{
+ gchar *key = gtk_editable_get_chars (editable, 0, -1);
+ if (!ygtk_html_wrap_search (dialog->help_text, key)) {
+ GdkColor red = { 0, 255 << 8, 102 << 8, 102 << 8 },
+ white = { 0, 255 << 8, 255 << 8, 255 << 8 };
+ gtk_widget_modify_base (dialog->search_entry, GTK_STATE_NORMAL, &red);
+ gtk_widget_modify_text (dialog->search_entry, GTK_STATE_NORMAL, &white);
+ gdk_beep();
+ }
+ else {
+ gtk_widget_modify_base (dialog->search_entry, GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_text (dialog->search_entry, GTK_STATE_NORMAL, NULL);
+ }
+ g_free (key);
+}
+static void search_entry_activated_cb (GtkEntry *entry, YGtkHelpDialog *dialog)
+{ ygtk_help_dialog_find_next (dialog); }
+static void close_button_clicked_cb (GtkButton *button, YGtkHelpDialog *dialog)
+{ gtk_widget_hide (GTK_WIDGET (dialog)); }
+
+static void ygtk_help_dialog_init (YGtkHelpDialog *dialog)
+{
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+ gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+
+ gtk_window_set_title (GTK_WINDOW (dialog), "Help");
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 350);
+
+ // title
+ GtkStockItem help_item;
+ gtk_stock_lookup (GTK_STOCK_HELP, &help_item);
+
+ dialog->title_box = gtk_hbox_new (FALSE, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (dialog->title_box), 6);
+ dialog->title_image = gtk_image_new_from_stock (GTK_STOCK_HELP,
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ dialog->title_label = gtk_label_new ("Help");
+ gtk_widget_modify_fg (dialog->title_label, GTK_STATE_NORMAL,
+ &dialog->title_label->style->fg [GTK_STATE_SELECTED]);
+ ygutils_setWidgetFont (dialog->title_label, PANGO_WEIGHT_ULTRABOLD,
+ PANGO_SCALE_LARGE);
+ gtk_box_pack_start (GTK_BOX (dialog->title_box), dialog->title_image,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (dialog->title_box), dialog->title_label,
+ FALSE, FALSE, 0);
+
+ // help text
+ dialog->help_box = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->help_box),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (dialog->help_box),
+ GTK_SHADOW_IN);
+ dialog->help_text = ygtk_html_wrap_new();
+ gtk_container_add (GTK_CONTAINER (dialog->help_box), dialog->help_text);
+
+ // bottom part (search entry + close button)
+ GtkWidget *bottom_box;
+ bottom_box = gtk_hbox_new (FALSE, 0);
+ dialog->search_entry = ygtk_find_entry_new();
+ gtk_widget_set_size_request (dialog->search_entry, 140, -1);
+ dialog->close_button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ GTK_WIDGET_SET_FLAGS (dialog->close_button, GTK_CAN_DEFAULT);
+
+ gtk_box_pack_start (GTK_BOX (bottom_box), dialog->search_entry, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (bottom_box), dialog->close_button, FALSE, FALSE, 0);
+
+ g_signal_connect (G_OBJECT (dialog->search_entry), "changed",
+ G_CALLBACK (search_entry_modified_cb), dialog);
+ g_signal_connect (G_OBJECT (dialog->search_entry), "activate",
+ G_CALLBACK (search_entry_activated_cb), dialog);
+
+ // glue it
+ dialog->vbox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (dialog->vbox), dialog->title_box, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (dialog->vbox), dialog->help_box, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (dialog->vbox), bottom_box, FALSE, FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
+ gtk_widget_show_all (dialog->vbox);
+
+ g_signal_connect (G_OBJECT (dialog->close_button), "clicked",
+ G_CALLBACK (close_button_clicked_cb), dialog);
+ g_signal_connect (G_OBJECT (dialog), "delete-event",
+ G_CALLBACK (gtk_widget_hide_on_delete), NULL);
+}
+
+static void ygtk_help_dialog_realize (GtkWidget *widget)
+{
+ GTK_WIDGET_CLASS (ygtk_help_dialog_parent_class)->realize (widget);
+ YGtkHelpDialog *dialog = YGTK_HELP_DIALOG (widget);
+
+ // set help text background
+ gtk_widget_realize (dialog->help_text);
+ ygtk_html_wrap_set_background (dialog->help_text, THEMEDIR "/wizard/help-background.png");
+
+ // set close as default widget
+ gtk_widget_grab_default (dialog->close_button);
+ gtk_widget_grab_focus (dialog->close_button);
+}
+
+static gboolean ygtk_help_dialog_expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ YGtkHelpDialog *dialog = YGTK_HELP_DIALOG (widget);
+
+ // draw rect on title
+ int x, y, w, h;
+ x = dialog->title_box->allocation.x;
+ y = dialog->title_box->allocation.y;
+ w = dialog->title_box->allocation.width;
+ h = dialog->title_box->allocation.height;
+ if (x + w >= event->area.x && x <= event->area.x + event->area.width &&
+ y + h >= event->area.y && x <= event->area.y + event->area.height) {
+ cairo_t *cr = gdk_cairo_create (widget->window);
+ gdk_cairo_set_source_color (cr, &widget->style->bg [GTK_STATE_SELECTED]);
+ cairo_rectangle (cr, x, y, w, h);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+ }
+
+ gtk_container_propagate_expose (GTK_CONTAINER (dialog), dialog->vbox, event);
+ return FALSE;
+}
+
+static void ygtk_help_dialog_close (YGtkHelpDialog *dialog)
+{ gtk_widget_hide (GTK_WIDGET (dialog)); }
+
+GtkWidget *ygtk_help_dialog_new (GtkWindow *parent)
+{
+ GtkWidget *dialog = g_object_new (YGTK_TYPE_HELP_DIALOG, NULL);
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+ return dialog;
+}
+
+void ygtk_help_dialog_set_text (YGtkHelpDialog *dialog, const gchar *text)
+{
+ gtk_editable_delete_text (GTK_EDITABLE (dialog->search_entry), 0, -1);
+ ygtk_html_wrap_set_text (dialog->help_text, text);
+}
+
+static void ygtk_help_dialog_class_init (YGtkHelpDialogClass *klass)
+{
+ klass->find_next = ygtk_help_dialog_find_next;
+ klass->close = ygtk_help_dialog_close;
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->expose_event = ygtk_help_dialog_expose_event;
+ widget_class->realize = ygtk_help_dialog_realize;
+
+ // key bindings (F3 for next word, Esc to close the window)
+ g_signal_new ("find_next", G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (YGtkHelpDialogClass, find_next),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("close", G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (YGtkHelpDialogClass, close),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ GtkBindingSet *binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_F3, 0, "find_next", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "close", 0);
+}
+
+//** YGtkWizard
+
+static gint get_header_padding (GtkWidget *widget)
+{
+#if 0
+// TODO: read GtkAssistance style_rc attributes
+ gint padding;
+ gtk_widget_style_get (widget, "header-padding", &padding, NULL);
+ return padding;
+#else
+ return 6;
+#endif
+}
+
+static gint get_content_padding (GtkWidget *widget)
+{
+#if 0
+ gint padding;
+ gtk_widget_style_get (widget, "content-padding", &padding, NULL);
+ return padding;
+#else
+ return 1;
+#endif
+}
+
+// callbacks
+static void destroy_tree_path (gpointer data)
+{
+ GtkTreePath *path = data;
+ gtk_tree_path_free (path);
+}
+
+// signals
+static guint action_triggered_signal;
+
+static void ygtk_marshal_VOID__POINTER_INT (GClosure *closure,
+ GValue *return_value, guint n_param_values, const GValue *param_values,
+ gpointer invocation_hint, gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__POINTER_INT) (gpointer data1, gpointer arg_1,
+ gint arg_2, gpointer data2);
+ register GMarshalFunc_VOID__POINTER_INT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__POINTER_INT)
+ (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1, g_value_get_pointer (param_values + 1),
+ g_value_get_int (param_values + 2), data2);
+}
+
+static void button_clicked_cb (GtkButton *button, YGtkWizard *wizard)
+{
+ gpointer id = g_object_get_data (G_OBJECT (button), "id");
+ g_signal_emit (wizard, action_triggered_signal, 0, id, G_TYPE_POINTER);
+}
+
+static GtkWidget *button_new (YGtkWizard *wizard)
+{
+ GtkWidget *button = gtk_button_new_with_mnemonic ("");
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (button_clicked_cb), wizard);
+ return button;
+}
+
+static void ygtk_wizard_popup_help (YGtkWizard *wizard)
+{
+ if (!wizard->m_help_dialog) {
+ GtkWindow *window = (GtkWindow *) gtk_widget_get_ancestor (
+ GTK_WIDGET (wizard), GTK_TYPE_WINDOW);
+ wizard->m_help_dialog = ygtk_help_dialog_new (window);
+ ygtk_help_dialog_set_text (YGTK_HELP_DIALOG (wizard->m_help_dialog),
+ wizard->m_help);
+ }
+ gtk_widget_show (wizard->m_help_dialog);
+}
+
+static void help_button_clicked_cb (GtkWidget *button, YGtkWizard *wizard)
+{ ygtk_wizard_popup_help (wizard); }
+
+G_DEFINE_TYPE (YGtkWizard, ygtk_wizard, GTK_TYPE_BIN)
+
+static void ygtk_wizard_init (YGtkWizard *wizard)
+{
+ wizard->menu_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+ wizard->tree_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, destroy_tree_path);
+ wizard->steps_ids = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (wizard), BORDER);
+
+ //** Title
+ wizard->m_title = gtk_hbox_new (FALSE, 0);
+
+ wizard->m_title_image = gtk_image_new();
+ wizard->m_title_label = gtk_label_new("");
+ gtk_label_set_ellipsize (GTK_LABEL (wizard->m_title_label), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (wizard->m_title_label), 0, 0);
+
+ // setup label look
+ gtk_widget_modify_fg (wizard->m_title_label, GTK_STATE_NORMAL,
+ &wizard->m_title_label->style->fg [GTK_STATE_SELECTED]);
+ // set a strong font to the heading label
+ ygutils_setWidgetFont (wizard->m_title_label, PANGO_WEIGHT_ULTRABOLD,
+ PANGO_SCALE_XX_LARGE);
+
+ gtk_box_pack_start (GTK_BOX (wizard->m_title), wizard->m_title_label,
+ TRUE, TRUE, 0);
+ gtk_box_pack_end (GTK_BOX (wizard->m_title), wizard->m_title_image,
+ FALSE, FALSE, 0);
+
+ gtk_widget_set_parent (wizard->m_title, GTK_WIDGET (wizard));
+ gtk_widget_show_all (wizard->m_title);
+
+ //** Adding the bottom buttons
+ wizard->m_next_button = button_new (wizard);
+ wizard->m_back_button = button_new (wizard);
+ wizard->m_abort_button = button_new (wizard);
+ wizard->m_release_notes_button = button_new (wizard);
+
+ wizard->m_help_button = gtk_button_new_from_stock (GTK_STOCK_HELP);
+ GTK_WIDGET_SET_FLAGS (wizard->m_help_button, GTK_CAN_DEFAULT);
+ g_signal_connect (G_OBJECT (wizard->m_help_button), "clicked",
+ G_CALLBACK (help_button_clicked_cb), wizard);
+
+ // we need to protect this button against insensitive in some cases
+ // this is a flag to enable that
+ ygtk_wizard_protect_next_button (wizard, FALSE);
+
+ wizard->m_buttons = gtk_hbox_new (FALSE, 12);
+
+ gtk_box_pack_start (GTK_BOX (wizard->m_buttons), wizard->m_help_button, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (wizard->m_buttons), wizard->m_release_notes_button,
+ FALSE, TRUE, 0);
+
+ gtk_box_pack_end (GTK_BOX (wizard->m_buttons), wizard->m_next_button, FALSE, TRUE, 0);
+ gtk_box_pack_end (GTK_BOX (wizard->m_buttons), wizard->m_back_button, FALSE, TRUE, 0);
+ gtk_box_pack_end (GTK_BOX (wizard->m_buttons), wizard->m_abort_button, FALSE, TRUE, 0);
+
+ gtk_widget_set_parent (wizard->m_buttons, GTK_WIDGET (wizard));
+ gtk_widget_show (wizard->m_buttons);
+
+ // make buttons all having the same size
+ GtkSizeGroup *buttons_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+ gtk_size_group_add_widget (buttons_group, wizard->m_help_button);
+ gtk_size_group_add_widget (buttons_group, wizard->m_release_notes_button);
+ gtk_size_group_add_widget (buttons_group, wizard->m_next_button);
+ gtk_size_group_add_widget (buttons_group, wizard->m_back_button);
+ gtk_size_group_add_widget (buttons_group, wizard->m_abort_button);
+ g_object_unref (G_OBJECT (buttons_group));
+
+ //** The menu and the navigation widget will be created when requested.
+ //** Help dialog will be build on realize so we can give it a parent window.
+}
+
+static void ygtk_wizard_realize (GtkWidget *widget)
+{
+ YGtkWizard *wizard = YGTK_WIZARD (widget);
+
+ GTK_WIDGET_CLASS (ygtk_wizard_parent_class)->realize (widget);
+
+ gtk_widget_grab_default (wizard->m_next_button);
+ gtk_widget_grab_focus (wizard->m_next_button);
+}
+
+static void destroy_hash (GHashTable **hash)
+{
+ if (*hash)
+ g_hash_table_destroy (*hash);
+ *hash = NULL;
+}
+
+static void ygtk_wizard_destroy (GtkObject *object)
+{
+ YGtkWizard *wizard = YGTK_WIZARD (object);
+
+ destroy_hash (&wizard->menu_ids);
+ destroy_hash (&wizard->tree_ids);
+ destroy_hash (&wizard->steps_ids);
+
+ if (wizard->m_help) {
+ g_free (wizard->m_help);
+ wizard->m_help = NULL;
+ }
+
+/* We must unparent these widgets from the wizard as they would try
+ to use gtk_container_remove() on it. We ref them since we still
+ want to call destroy on them so they children die. */
+#define DESTROY_WIDGET(widget) \
+ if (widget) { \
+ g_object_ref (G_OBJECT (widget)); \
+ gtk_widget_unparent (widget); \
+ gtk_widget_destroy (widget); \
+ widget = NULL; \
+ }
+ DESTROY_WIDGET (wizard->m_title)
+ DESTROY_WIDGET (wizard->m_buttons)
+ DESTROY_WIDGET (wizard->m_menu)
+ DESTROY_WIDGET (wizard->m_navigation)
+ DESTROY_WIDGET (wizard->m_title)
+#undef DESTROY_WIDGET
+
+ if (wizard->m_help_dialog) {
+ gtk_widget_destroy (wizard->m_help_dialog);
+ wizard->m_help_dialog = NULL;
+ }
+
+ GTK_OBJECT_CLASS (ygtk_wizard_parent_class)->destroy (object);
+}
+
+GtkWidget *ygtk_wizard_new (void)
+{
+ return g_object_new (YGTK_TYPE_WIZARD, NULL);
+}
+
+static void selected_menu_item_cb (GtkMenuItem *item, const char *id)
+{
+ YGtkWizard *wizard = g_object_get_data (G_OBJECT (item), "wizard");
+ g_signal_emit (wizard, action_triggered_signal, 0, id, G_TYPE_STRING);
+}
+
+static void tree_item_selected_cb (GtkTreeView *tree_view, YGtkWizard *wizard)
+{
+ const gchar *id = ygtk_wizard_get_tree_selection (wizard);
+ if (id)
+ g_signal_emit (wizard, action_triggered_signal, 0, id, G_TYPE_STRING);
+}
+
+void ygtk_wizard_enable_steps (YGtkWizard *wizard)
+{
+ if (wizard->m_navigation) {
+ g_error ("YGtkWizard: a tree or steps widgets have already been enabled.");
+ return;
+ }
+ wizard->m_navigation_widget = ygtk_steps_new();
+ wizard->m_navigation = wizard->m_navigation_widget;
+ gtk_widget_modify_text (wizard->m_navigation_widget, GTK_STATE_NORMAL,
+ &wizard->m_navigation_widget->style->fg [GTK_STATE_SELECTED]);
+
+ gtk_widget_set_parent (wizard->m_navigation, GTK_WIDGET (wizard));
+ gtk_widget_show_all (wizard->m_navigation);
+}
+
+void ygtk_wizard_enable_tree (YGtkWizard *wizard)
+{
+ if (wizard->m_navigation) {
+ g_error ("YGtkWizard: a tree or steps widgets have already been enabled.");
+ return;
+ }
+
+ wizard->m_navigation_widget = gtk_tree_view_new_with_model
+ (GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_STRING)));
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (wizard->m_navigation_widget),
+ 0, "(no title)", gtk_cell_renderer_text_new(), "text", 0, NULL);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (wizard->m_navigation_widget), FALSE);
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (wizard->m_navigation_widget)), GTK_SELECTION_BROWSE);
+
+ g_signal_connect (G_OBJECT (wizard->m_navigation_widget), "cursor-changed",
+ G_CALLBACK (tree_item_selected_cb), wizard);
+
+ wizard->m_navigation = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wizard->m_navigation),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (wizard->m_navigation),
+ GTK_SHADOW_IN);
+
+ gtk_container_add (GTK_CONTAINER (wizard->m_navigation), wizard->m_navigation_widget);
+ gtk_widget_set_size_request (wizard->m_navigation, 180, -1);
+
+ gtk_widget_set_parent (wizard->m_navigation, GTK_WIDGET (wizard));
+ gtk_widget_show_all (wizard->m_navigation);
+ gtk_widget_queue_draw (GTK_WIDGET (wizard));
+}
+
+void ygtk_wizard_set_child (YGtkWizard *wizard, GtkWidget *new_child)
+{
+ GtkWidget *child = GTK_BIN (wizard)->child;
+ if (child)
+ gtk_container_remove (GTK_CONTAINER (wizard), child);
+ if (new_child)
+ gtk_container_add (GTK_CONTAINER (wizard), new_child);
+}
+
+#define ENABLE_WIDGET(enable, widget) \
+ (enable ? gtk_widget_show (widget) : gtk_widget_hide (widget))
+#define ENABLE_WIDGET_STR(str, widget) \
+ (str && str[0] ? gtk_widget_show (widget) : gtk_widget_hide (widget))
+
+/* Commands */
+
+void ygtk_wizard_set_help_text (YGtkWizard *wizard, const gchar *text)
+{
+ if (wizard->m_help)
+ g_free (wizard->m_help);
+ wizard->m_help = g_strdup (text);
+ if (wizard->m_help_dialog)
+ ygtk_help_dialog_set_text (YGTK_HELP_DIALOG (wizard->m_help_dialog), text);
+ ENABLE_WIDGET_STR (text, wizard->m_help_button);
+}
+
+gboolean ygtk_wizard_add_tree_item (YGtkWizard *wizard, const char *parent_id,
+ const char *text, const char *id)
+{
+ GtkTreeModel *model = gtk_tree_view_get_model
+ (GTK_TREE_VIEW (wizard->m_navigation_widget));
+ GtkTreeIter iter;
+
+ if (!parent_id || !*parent_id)
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
+ else {
+ GtkTreePath *path = g_hash_table_lookup (wizard->tree_ids, parent_id);
+ if (path == NULL)
+ return FALSE;
+ GtkTreeIter parent_iter;
+ gtk_tree_model_get_iter (model, &parent_iter, path);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent_iter);
+ }
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 0, text, -1);
+ g_hash_table_insert (wizard->tree_ids, g_strdup (id),
+ gtk_tree_model_get_path (model, &iter));
+ return TRUE;
+}
+
+/* this is g_hash_table_remove_all in new glib */
+static gboolean hash_table_clear_cb (gpointer key, gpointer value, gpointer data)
+{
+ return TRUE;
+}
+static void yg_hash_table_remove_all (GHashTable *hash_table)
+{
+ g_hash_table_foreach_remove (hash_table, hash_table_clear_cb, NULL);
+}
+
+void ygtk_wizard_clear_tree (YGtkWizard *wizard)
+{
+ GtkTreeView *tree = GTK_TREE_VIEW (wizard->m_navigation_widget);
+ gtk_tree_store_clear (GTK_TREE_STORE (gtk_tree_view_get_model (tree)));
+ yg_hash_table_remove_all (wizard->tree_ids);
+}
+
+gboolean ygtk_wizard_select_tree_item (YGtkWizard *wizard, const char *id)
+{
+ GtkTreePath *path = g_hash_table_lookup (wizard->tree_ids, id);
+ if (path == NULL)
+ return FALSE;
+
+ g_signal_handlers_block_by_func (wizard->m_navigation_widget,
+ (gpointer) tree_item_selected_cb, wizard);
+
+ GtkWidget *widget = wizard->m_navigation_widget;
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (widget), path);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), path,
+ NULL, FALSE);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget), path, NULL,
+ TRUE, 0.5, 0.5);
+
+ g_signal_handlers_unblock_by_func (wizard->m_navigation_widget,
+ (gpointer) tree_item_selected_cb, wizard);
+ return TRUE;
+}
+
+void ygtk_wizard_set_header_text (YGtkWizard *wizard, GtkWindow *window,
+ const char *text)
+{
+ gtk_label_set_text (GTK_LABEL (wizard->m_title_label), text);
+ if (window) {
+ char *title = g_strdup_printf ("%s - YaST", text);
+ gtk_window_set_title (window, title);
+ g_free (title);
+ }
+}
+
+gboolean ygtk_wizard_set_header_icon (YGtkWizard *wizard, GtkWindow *window,
+ const char *icon)
+{
+ GError *error = 0;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (icon, &error);
+ if (!pixbuf)
+ return FALSE;
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (wizard->m_title_image), pixbuf);
+ if (window)
+ gtk_window_set_icon (window, pixbuf);
+ g_object_unref (G_OBJECT (pixbuf));
+ return TRUE;
+}
+
+void ygtk_wizard_set_abort_button_label (YGtkWizard *wizard, const char *text)
+{
+ gtk_button_set_label (GTK_BUTTON (wizard->m_abort_button), text);
+ ENABLE_WIDGET_STR (text, wizard->m_abort_button);
+ ygutils_setStockIcon (wizard->m_abort_button, text);
+}
+
+void ygtk_wizard_set_back_button_label (YGtkWizard *wizard, const char *text)
+{
+ gtk_button_set_label (GTK_BUTTON (wizard->m_back_button), text);
+ ENABLE_WIDGET_STR (text, wizard->m_back_button);
+ ygutils_setStockIcon (wizard->m_back_button, text);
+}
+
+void ygtk_wizard_set_next_button_label (YGtkWizard *wizard, const char *text)
+{
+ gtk_button_set_label (GTK_BUTTON (wizard->m_next_button), text);
+ ENABLE_WIDGET_STR (text, wizard->m_next_button);
+ ygutils_setStockIcon (wizard->m_next_button, text);
+}
+
+void ygtk_wizard_set_back_button_id (YGtkWizard *wizard, gpointer id,
+ GDestroyNotify destroy_cb)
+{
+ g_object_set_data_full (G_OBJECT (wizard->m_back_button), "id", id, destroy_cb);
+}
+
+void ygtk_wizard_set_next_button_id (YGtkWizard *wizard, gpointer id,
+ GDestroyNotify destroy_cb)
+{
+ g_object_set_data_full (G_OBJECT (wizard->m_next_button), "id", id, destroy_cb);
+}
+
+void ygtk_wizard_set_abort_button_id (YGtkWizard *wizard, gpointer id,
+ GDestroyNotify destroy_cb)
+{
+ g_object_set_data_full (G_OBJECT (wizard->m_abort_button), "id", id, destroy_cb);
+}
+
+void ygtk_wizard_set_release_notes_button_label (YGtkWizard *wizard,
+ const gchar *text, gpointer id,
+ GDestroyNotify destroy_cb)
+{
+ gtk_button_set_label (GTK_BUTTON (wizard->m_release_notes_button), text);
+ g_object_set_data_full (G_OBJECT (wizard->m_release_notes_button), "id",
+ id, destroy_cb);
+ gtk_widget_show (wizard->m_release_notes_button);
+}
+
+void ygtk_wizard_show_release_notes_button (YGtkWizard *wizard, gboolean enable)
+{
+ ENABLE_WIDGET (enable, wizard->m_release_notes_button);
+}
+
+void ygtk_wizard_enable_back_button (YGtkWizard *wizard, gboolean enable)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (wizard->m_back_button), enable);
+}
+
+void ygtk_wizard_enable_next_button (YGtkWizard *wizard, gboolean enable)
+{
+ if (enable || !ygtk_wizard_is_next_button_protected (wizard))
+ gtk_widget_set_sensitive (GTK_WIDGET (wizard->m_next_button), enable);
+}
+
+void ygtk_wizard_enable_abort_button (YGtkWizard *wizard, gboolean enable)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (wizard->m_abort_button), enable);
+}
+
+gboolean ygtk_wizard_is_next_button_protected (YGtkWizard *wizard)
+{
+ return GPOINTER_TO_INT (g_object_get_data (
+ G_OBJECT (wizard->m_next_button), "protect"));
+}
+
+void ygtk_wizard_protect_next_button (YGtkWizard *wizard, gboolean protect)
+{
+ g_object_set_data (G_OBJECT (wizard->m_abort_button), "protect",
+ GINT_TO_POINTER (protect));
+}
+
+void ygtk_wizard_focus_next_button (YGtkWizard *wizard)
+{
+ gtk_widget_grab_focus (wizard->m_next_button);
+}
+
+void ygtk_wizard_focus_back_button (YGtkWizard *wizard)
+{
+ gtk_widget_grab_focus (wizard->m_back_button);
+}
+
+void ygtk_wizard_add_menu (YGtkWizard *wizard, const char *text,
+ const char *id)
+{
+ if (!wizard->m_menu) {
+ wizard->m_menu = gtk_menu_bar_new();
+ gtk_widget_set_parent (wizard->m_menu, GTK_WIDGET (wizard));
+ gtk_widget_queue_draw (GTK_WIDGET (wizard));
+ }
+
+ GtkWidget *entry = gtk_menu_item_new_with_mnemonic (text);
+ gtk_menu_shell_append (GTK_MENU_SHELL (wizard->m_menu), entry);
+
+ GtkWidget *submenu = gtk_menu_new();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (entry), submenu);
+
+ g_hash_table_insert (wizard->menu_ids, g_strdup (id), submenu);
+ gtk_widget_show_all (wizard->m_menu);
+}
+
+gboolean ygtk_wizard_add_menu_entry (YGtkWizard *wizard, const char *parent_id,
+ const char *text, const char *id)
+{
+ GtkWidget *parent = g_hash_table_lookup (wizard->menu_ids, parent_id);
+ if (!parent)
+ return FALSE;
+
+ GtkWidget *entry = gtk_menu_item_new_with_mnemonic (text);
+ gtk_menu_shell_append (GTK_MENU_SHELL (parent), entry);
+ gtk_widget_show (entry);
+
+ // we need to get YGtkWizard to send signal
+ g_object_set_data (G_OBJECT (entry), "wizard", wizard);
+ g_signal_connect_data (G_OBJECT (entry), "activate",
+ G_CALLBACK (selected_menu_item_cb), g_strdup (id),
+ (GClosureNotify) g_free, 0);
+ return TRUE;
+}
+
+gboolean ygtk_wizard_add_sub_menu (YGtkWizard *wizard, const char *parent_id,
+ const char *text, const char *id)
+{
+ GtkWidget *parent = g_hash_table_lookup (wizard->menu_ids, parent_id);
+ if (!parent)
+ return FALSE;
+
+ GtkWidget *entry = gtk_menu_item_new_with_mnemonic (text);
+ gtk_menu_shell_append (GTK_MENU_SHELL (parent), entry);
+
+ GtkWidget *submenu = gtk_menu_new();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (entry), submenu);
+
+ g_hash_table_insert (wizard->menu_ids, g_strdup (id), submenu);
+ gtk_widget_show_all (entry);
+ return TRUE;
+}
+
+gboolean ygtk_wizard_add_menu_separator (YGtkWizard *wizard, const char *parent_id)
+{
+ GtkWidget *parent = g_hash_table_lookup (wizard->menu_ids, parent_id);
+ if (!parent)
+ return FALSE;
+
+ GtkWidget *separator = gtk_separator_menu_item_new();
+ gtk_menu_shell_append (GTK_MENU_SHELL (parent), separator);
+ gtk_widget_show (separator);
+ return TRUE;
+}
+
+void ygtk_wizard_add_step_header (YGtkWizard *wizard, const char *text)
+{
+ g_return_if_fail (wizard->m_navigation_widget != NULL);
+ ygtk_steps_append_heading (YGTK_STEPS (wizard->m_navigation_widget), text);
+}
+
+void ygtk_wizard_add_step (YGtkWizard *wizard, const char* text, const char *id)
+{
+ guint step_nb;
+ g_return_if_fail (wizard->m_navigation_widget != NULL);
+ step_nb = ygtk_steps_append (YGTK_STEPS (wizard->m_navigation_widget), text);
+ g_hash_table_insert (wizard->steps_ids, g_strdup (id), GINT_TO_POINTER (step_nb));
+}
+
+gboolean ygtk_wizard_set_current_step (YGtkWizard *wizard, const char *id)
+{
+ gpointer step_nb = g_hash_table_lookup (wizard->steps_ids, id);
+ if (!step_nb)
+ return FALSE;
+ ygtk_steps_set_current (YGTK_STEPS (wizard->m_navigation_widget),
+ GPOINTER_TO_INT (step_nb));
+ return TRUE;
+}
+
+void ygtk_wizard_clear_steps (YGtkWizard *wizard)
+{
+ ygtk_steps_clear (YGTK_STEPS (wizard->m_navigation_widget));
+ yg_hash_table_remove_all (wizard->steps_ids);
+}
+
+static const gchar *found_key;
+static void hash_lookup_tree_path_value (gpointer _key, gpointer _value,
+ gpointer user_data)
+{
+ gchar *key = _key;
+ GtkTreePath *value = _value;
+ GtkTreePath *needle = user_data;
+
+ if (gtk_tree_path_compare (value, needle) == 0)
+ found_key = key;
+}
+
+const gchar *ygtk_wizard_get_tree_selection (YGtkWizard *wizard)
+{
+ GtkTreePath *path;
+ gtk_tree_view_get_cursor (GTK_TREE_VIEW (wizard->m_navigation_widget),
+ &path, NULL);
+ if (path == NULL)
+ return NULL;
+
+ /* A more elegant solution would be using a crossed hash table, but there
+ is none out of box, so we'll just iterate the hash table. */
+ found_key = 0;
+ g_hash_table_foreach (wizard->tree_ids, hash_lookup_tree_path_value, path);
+
+ gtk_tree_path_free (path);
+ return found_key;
+}
+
+void ygtk_wizard_set_sensitive (YGtkWizard *wizard, gboolean sensitive)
+{
+ // FIXME: check if this chains through
+ gtk_widget_set_sensitive (GTK_WIDGET (wizard), sensitive);
+
+ if (ygtk_wizard_is_next_button_protected (wizard))
+ gtk_widget_set_sensitive (wizard->m_next_button, TRUE);
+}
+
+static void ygtk_wizard_size_request (GtkWidget *widget, GtkRequisition *requisition)
+{
+ YGtkWizard *wizard = YGTK_WIZARD (widget);
+
+ gint border = GTK_CONTAINER (wizard)->border_width;
+ gint header_padding = get_header_padding (GTK_WIDGET (wizard));
+ gint content_padding = get_content_padding (GTK_WIDGET (wizard));
+ GtkRequisition req; // temp usage
+
+ requisition->width = 0;
+ requisition->height = border * 2;
+
+ if (wizard->m_menu) {
+ gtk_widget_size_request (wizard->m_menu, &req);
+ requisition->width = MAX (requisition->width, req.width);
+ requisition->height += req.height;
+ }
+
+ // title
+ gtk_widget_size_request (wizard->m_title, &req);
+ req.width += header_padding * 2 + border*2;
+ req.height += header_padding * 2;
+
+ requisition->width = MAX (MIN (req.width, 40), requisition->width);
+ requisition->height += req.height;
+
+ // body
+ {
+ GtkRequisition nav_req, child_req;
+
+ if (wizard->m_navigation) {
+ gtk_widget_size_request (wizard->m_navigation, &nav_req);
+ nav_req.width += content_padding * 2;
+ nav_req.height += content_padding * 2;
+ }
+ else
+ nav_req.width = nav_req.height = 0;
+
+ GtkWidget *child = GTK_BIN (wizard)->child;
+ if (child && GTK_WIDGET_VISIBLE (child))
+ gtk_widget_size_request (child, &child_req);
+ else
+ child_req.width = child_req.height = 0;
+ child_req.width += content_padding * 2 + CHILD_BORDER*2;
+ child_req.height += content_padding * 2 + CHILD_BORDER*2;
+
+ req.width = nav_req.width + child_req.width + border*2;
+ req.height = MAX (nav_req.height, child_req.height);
+
+ requisition->width = MAX (requisition->width, req.width);
+ requisition->height += req.height;
+ }
+
+ // buttons
+ gtk_widget_size_request (wizard->m_buttons, &req);
+ req.width += border*2;
+ req.height += BUTTONS_SPACING + border;
+
+ requisition->width = MAX (requisition->width, req.width);
+ requisition->height += req.height;
+}
+
+// helper -- applies padding to a GtkAllocation
+static inline void apply_allocation_padding (GtkAllocation *alloc, gint padding)
+{
+ alloc->x += padding;
+ alloc->y += padding;
+ alloc->width -= padding * 2;
+ alloc->height -= padding * 2;
+}
+
+static void ygtk_wizard_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ YGtkWizard *wizard = YGTK_WIZARD (widget);
+
+ gint border = GTK_CONTAINER (wizard)->border_width;
+ gint header_padding = get_header_padding (widget);
+ gint content_padding = get_content_padding (widget);
+ GtkRequisition req; // temp usage
+ // we use "areas" because we need to do some tweaking when doing the actual
+ // allocation and this makes it easier to place the other widgets.
+ GtkAllocation menu_area, title_area, nav_area, child_area, buttons_area;
+
+ // menu
+ menu_area.x = allocation->x;
+ menu_area.y = allocation->y;
+ if (wizard->m_menu) {
+ gtk_widget_get_child_requisition (wizard->m_menu, &req);
+ menu_area.width = allocation->width;
+ menu_area.height = req.height;
+ }
+ else
+ menu_area.width = menu_area.height = 0;
+
+ // title
+ gtk_widget_get_child_requisition (wizard->m_title, &req);
+ title_area.x = allocation->x + border;
+ title_area.y = menu_area.y + menu_area.height + border;
+ title_area.width = allocation->width - border*2;
+ title_area.height = req.height + header_padding*2;
+
+ // buttons
+ gtk_widget_get_child_requisition (wizard->m_buttons, &req);
+ buttons_area.x = title_area.x;
+ buttons_area.y = (allocation->y + allocation->height) - req.height - border;
+ buttons_area.width = title_area.width;
+ buttons_area.height = req.height;
+
+ // child (aka content aka containee)
+ child_area.x = title_area.x;
+ child_area.y = title_area.y + title_area.height;
+ child_area.width = title_area.width;
+ child_area.height = allocation->height - menu_area.height - title_area.height -
+ buttons_area.height - border*2 - BUTTONS_SPACING;
+
+ // navigation pane
+ nav_area.x = child_area.x;
+ nav_area.y = child_area.y;
+ nav_area.height = child_area.height;
+ if (wizard->m_navigation) {
+ gtk_widget_get_child_requisition (wizard->m_navigation, &req);
+ nav_area.width = req.width + content_padding*2;
+
+ child_area.x += nav_area.width;
+ child_area.width -= nav_area.width;
+ /* // align to child
+ title_area.x += nav_area.width;
+ title_area.width -= nav_area.width;*/
+ }
+ else
+ nav_area.width = 0;
+
+ // Actual allocations
+ // menu
+ if (wizard->m_menu)
+ gtk_widget_size_allocate (wizard->m_menu, &menu_area);
+
+ // title
+ apply_allocation_padding (&title_area, header_padding);
+ gtk_widget_size_allocate (wizard->m_title, &title_area);
+
+ // child
+ GtkWidget *child = GTK_BIN (wizard)->child;
+ if (child && GTK_WIDGET_VISIBLE (child)) {
+ apply_allocation_padding (&child_area, content_padding + CHILD_BORDER);
+ gtk_widget_size_allocate (child, &child_area);
+ }
+
+ // navigation pane
+ if (wizard->m_navigation) {
+ apply_allocation_padding (&nav_area, content_padding);
+ gtk_widget_size_allocate (wizard->m_navigation, &nav_area);
+ }
+
+ // buttons
+ gtk_widget_size_allocate (wizard->m_buttons, &buttons_area);
+
+ GTK_WIDGET_CLASS (ygtk_wizard_parent_class)->size_allocate (widget, allocation);
+}
+
+static gboolean ygtk_wizard_expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ if (!GTK_WIDGET_DRAWABLE (widget))
+ return FALSE;
+ YGtkWizard *wizard = YGTK_WIZARD (widget);
+
+ gint border = GTK_CONTAINER (wizard)->border_width;
+ gint header_padding = get_header_padding (widget);
+ gint content_padding = get_content_padding (widget);
+
+ // paint a colored box
+ cairo_t *cr = gdk_cairo_create (widget->window);
+ int x, y, w, h;
+
+ // (outer rectangle)
+ x = border;
+ y = border;
+ w = widget->allocation.width - border*2;
+ h = wizard->m_buttons->allocation.y - border - BUTTONS_SPACING;
+ if (wizard->m_menu) {
+ y += wizard->m_menu->allocation.height;
+ h -= wizard->m_menu->allocation.height;
+ }
+
+ gdk_cairo_set_source_color (cr, &widget->style->bg [GTK_STATE_SELECTED]);
+ cairo_rectangle (cr, x, y, w, h);
+ cairo_fill (cr);
+
+ // (inner rectangle)
+ x += content_padding;
+ w -= content_padding*2;
+ y += wizard->m_title->allocation.height + header_padding*2 + content_padding;
+ h -= wizard->m_title->allocation.height + header_padding*2 + content_padding*2;
+ if (wizard->m_navigation) {
+ int navigation_w = wizard->m_navigation->allocation.width;
+ x += navigation_w + content_padding;
+ w -= navigation_w + content_padding;
+ }
+
+ gdk_cairo_set_source_color (cr, &widget->style->bg [GTK_STATE_NORMAL]);
+ cairo_rectangle (cr, x, y, w, h);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+
+ // propagate expose
+ GtkContainer *container = GTK_CONTAINER (wizard);
+ if (wizard->m_menu)
+ gtk_container_propagate_expose (container, wizard->m_menu, event);
+ gtk_container_propagate_expose (container, wizard->m_title, event);
+ if (wizard->m_navigation)
+ gtk_container_propagate_expose (container, wizard->m_navigation, event);
+ gtk_container_propagate_expose (container, wizard->m_buttons, event);
+ if (GTK_BIN (container)->child)
+ gtk_container_propagate_expose (container, GTK_BIN (container)->child, event);
+ return TRUE;
+}
+
+static void ygtk_wizard_forall (GtkContainer *container, gboolean include_internals,
+ GtkCallback callback, gpointer callback_data)
+{
+ YGtkWizard *wizard = YGTK_WIZARD (container);
+ if (include_internals) {
+ (*callback) (wizard->m_title, callback_data);
+ (*callback) (wizard->m_buttons, callback_data);
+ if (wizard->m_menu)
+ (*callback) (wizard->m_menu, callback_data);
+ if (wizard->m_navigation)
+ (*callback) (wizard->m_navigation, callback_data);
+ }
+
+ GtkWidget *containee = GTK_BIN (container)->child;
+ if (containee)
+ (*callback) (containee, callback_data);
+}
+
+/* Accessibility support */
+
+static gint ygtk_wizard_accessible_get_n_children (AtkObject *accessible)
+{
+ return 1 /* content*/ + 5 /* buttons*/;
+}
+
+static AtkObject *ygtk_wizard_accessible_ref_child (AtkObject *accessible,
+ gint index)
+{
+ GtkWidget *widget = GTK_ACCESSIBLE (accessible)->widget;
+ if (!widget)
+ return NULL;
+ YGtkWizard *wizard = YGTK_WIZARD (widget);
+
+ if (index == 0) {
+ GtkWidget *child = GTK_BIN (wizard)->child;
+ if (child)
+ return g_object_ref (G_OBJECT (child));
+ return NULL;
+ }
+
+ if (index >= 1 && index <= 5) {
+ GtkWidget *buttons[5] = { wizard->m_back_button, wizard->m_abort_button,
+ wizard->m_next_button, wizard->m_help_button,
+ wizard->m_release_notes_button };
+ GtkWidget *button = buttons [index-1];
+
+ if (GTK_WIDGET_VISIBLE (button))
+ return g_object_ref (G_OBJECT (button));
+ return NULL;
+ }
+ // out of range
+ return NULL;
+}
+
+static void ygtk_wizard_accessible_class_init (AtkObjectClass *class)
+{
+ class->get_n_children = ygtk_wizard_accessible_get_n_children;
+ class->ref_child = ygtk_wizard_accessible_ref_child;
+}
+
+static GType ygtk_wizard_accessible_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ AtkObjectFactory *factory;
+ GType derived_type;
+ GTypeQuery query;
+ GType derived_atk_type;
+
+ derived_type = g_type_parent (YGTK_TYPE_WIZARD);
+ factory = atk_registry_get_factory (atk_get_default_registry (), derived_type);
+ derived_atk_type = atk_object_factory_get_accessible_type (factory);
+ g_type_query (derived_atk_type, &query);
+
+ GTypeInfo type_info = { 0 };
+ type_info.class_size = query.class_size;
+ type_info.class_init = (GClassInitFunc) ygtk_wizard_accessible_class_init;
+ type_info.instance_size = query.instance_size;
+
+ type = g_type_register_static (derived_atk_type, "YGtkWizardAccessible",
+ &type_info, 0);
+
+/*
+ type = g_type_register_static_simple (derived_atk_type,
+ "YGtkWizardAccessible", query.class_size,
+ (GClassInitFunc) ygtk_wizard_accessible_class_init,
+ query.instance_size, NULL, 0);
+*/
+ }
+ return type;
+}
+
+static AtkObject *ygtk_wizard_accessible_new (GObject *obj)
+{
+ AtkObject *accessible;
+ g_return_val_if_fail (YGTK_IS_WIZARD (obj), NULL);
+
+ accessible = g_object_new (ygtk_wizard_accessible_get_type (), NULL);
+ atk_object_initialize (accessible, obj);
+ return accessible;
+}
+
+static GType ygtk_wizard_accessible_factory_get_accessible_type()
+{
+ return ygtk_wizard_accessible_get_type ();
+}
+
+static AtkObject*ygtk_wizard_accessible_factory_create_accessible (GObject *obj)
+{
+ return ygtk_wizard_accessible_new (obj);
+}
+
+static void ygtk_wizard_accessible_factory_class_init (AtkObjectFactoryClass *class)
+{
+ class->create_accessible = ygtk_wizard_accessible_factory_create_accessible;
+ class->get_accessible_type = ygtk_wizard_accessible_factory_get_accessible_type;
+}
+
+static GType ygtk_wizard_accessible_factory_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ GTypeInfo type_info = { 0 };
+ type_info.class_size = sizeof (AtkObjectFactoryClass);
+ type_info.class_init = (GClassInitFunc) ygtk_wizard_accessible_factory_class_init;
+ type_info.instance_size = sizeof (AtkObjectFactory);
+
+ type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY,
+ "YGtkWizardAccessibleFactory", &type_info, 0);
+
+/*
+ type = g_type_register_static_simple (ATK_TYPE_OBJECT_FACTORY,
+ "YGtkWizardAccessibleFactory", sizeof (AtkObjectFactoryClass),
+ (GClassInitFunc) ygtk_wizard_accessible_factory_class_init,
+ sizeof (AtkObjectFactory), NULL, 0);
+*/
+ }
+ return type;
+}
+
+static AtkObject *ygtk_wizard_get_accessible (GtkWidget *widget)
+{
+ static gboolean first_time = TRUE;
+ if (first_time) {
+ AtkObjectFactory *factory;
+ AtkRegistry *registry;
+ GType derived_type;
+ GType derived_atk_type;
+
+ derived_type = g_type_parent (YGTK_TYPE_WIZARD);
+ registry = atk_get_default_registry ();
+ factory = atk_registry_get_factory (registry, derived_type);
+ derived_atk_type = atk_object_factory_get_accessible_type (factory);
+ if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE)) {
+ atk_registry_set_factory_type (registry, YGTK_TYPE_WIZARD,
+ ygtk_wizard_accessible_factory_get_type ());
+ }
+ first_time = FALSE;
+ }
+ return GTK_WIDGET_CLASS (ygtk_wizard_parent_class)->get_accessible (widget);
+}
+
+static void ygtk_wizard_class_init (YGtkWizardClass *klass)
+{
+ ygtk_wizard_parent_class = g_type_class_peek_parent (klass);
+
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
+ //** Get expose, so we can draw line border
+ widget_class->expose_event = ygtk_wizard_expose_event;
+ widget_class->realize = ygtk_wizard_realize;
+ widget_class->size_request = ygtk_wizard_size_request;
+ widget_class->size_allocate = ygtk_wizard_size_allocate;
+ widget_class->get_accessible = ygtk_wizard_get_accessible;
+
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ container_class->forall = ygtk_wizard_forall;
+
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
+ gtkobject_class->destroy = ygtk_wizard_destroy;
+
+ action_triggered_signal = g_signal_new ("action-triggered",
+ G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (YGtkWizardClass, action_triggered),
+ NULL, NULL, ygtk_marshal_VOID__POINTER_INT, G_TYPE_NONE,
+ 2, G_TYPE_POINTER, G_TYPE_INT);
+
+ // on F1, popup the help box
+ klass->popup_help = ygtk_wizard_popup_help;
+ g_signal_new ("popup_help", G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (YGtkWizardClass, popup_help),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ GtkBindingSet *binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_F1, 0, "popup_help", 0);
+}
+
Added: trunk/gtk/src/ygtkwizard.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkwizard.h?rev=42515&v…
==============================================================================
--- trunk/gtk/src/ygtkwizard.h (added)
+++ trunk/gtk/src/ygtkwizard.h Thu Nov 29 18:25:41 2007
@@ -0,0 +1,174 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+/* YGtkWizard is a widget based on GtkAssistant, which we couldn't
+ use (for starters, GtkAssistant comes from GtkWindow and we need
+ a widget, not a window).
+*/
+
+#ifndef YGTK_WIZARD_H
+#define YGTK_WIZARD_H
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbin.h>
+#include <gtk/gtkwindow.h>
+G_BEGIN_DECLS
+
+// YGtkHelpDialog (for showing help text)
+/* Shows help text. It is GtkWindow-inherited, rather than GtkDialog, because
+ we want to place a search entry next to the buttons. */
+
+#define YGTK_TYPE_HELP_DIALOG (ygtk_help_dialog_get_type ())
+#define YGTK_HELP_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_HELP_DIALOG, YGtkHelpDialog))
+#define YGTK_HELP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_HELP_DIALOG, YGtkHelpDialogClass))
+#define YGTK_IS_HELP_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_HELP_DIALOG))
+#define YGTK_IS_HELP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_HELP_DIALOG))
+#define YGTK_HELP_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_HELP_DIALOG, YGtkHelpDialogClass))
+
+typedef struct _YGtkHelpDialog
+{
+ GtkWindow parent;
+
+ // parent:
+ GtkWidget *title_box, *title_label, *title_image;
+ GtkWidget *help_box, *help_text;
+ GtkWidget *search_entry, *close_button;
+ GtkWidget *vbox;
+} YGtkHelpDialog;
+
+typedef struct _YGtkHelpDialogClass
+{
+ GtkWindowClass parent_class;
+
+ // signals
+ void (*find_next) (YGtkHelpDialog *dialog);
+ void (*close) (YGtkHelpDialog *dialog);
+} YGtkHelpDialogClass;
+
+GtkWidget *ygtk_help_dialog_new (GtkWindow *parent);
+GType ygtk_help_dialog_get_type (void) G_GNUC_CONST;
+
+void ygtk_help_dialog_set_text (YGtkHelpDialog *dialog, const char *text);
+
+// YGtkWizard
+
+#define YGTK_TYPE_WIZARD (ygtk_wizard_get_type ())
+#define YGTK_WIZARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ YGTK_TYPE_WIZARD, YGtkWizard))
+#define YGTK_WIZARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ YGTK_TYPE_WIZARD, YGtkWizardClass))
+#define YGTK_IS_WIZARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ YGTK_TYPE_WIZARD))
+#define YGTK_IS_WIZARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ YGTK_TYPE_WIZARD))
+#define YGTK_WIZARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ YGTK_TYPE_WIZARD, YGtkWizardClass))
+
+typedef struct _YGtkWizard
+{
+ GtkBin bin;
+
+ // private:
+ /* Hash tables to assign Yast Ids to Gtk entries. */
+ GHashTable *menu_ids; /* gchar* -> GtkWidget* */
+ GHashTable *tree_ids; /* gchar* -> GtkTreePath* */
+ GHashTable *steps_ids; /* gchar* -> guint */
+
+ /* Widgets for layout. */
+ GtkWidget *m_menu, *m_title, *m_navigation, *m_buttons;
+ // containee can be accessed via GTK_BIN (wizard)->child
+
+ /* Widgets we need to have access to. */
+ GtkWidget *m_title_label, *m_title_image, *m_navigation_widget,
+ *m_back_button, *m_abort_button, *m_next_button, *m_help_button,
+ *m_release_notes_button;
+
+ /* The help text. */
+ gchar *m_help;
+ GtkWidget *m_help_dialog;
+} YGtkWizard;
+
+typedef struct _YGtkWizardClass
+{
+ GtkBinClass parent_class;
+
+ // signals:
+ void (*action_triggered) (YGtkWizard *wizard, gpointer id, gint id_type);
+ void (*popup_help) (YGtkWizard *dialog);
+} YGtkWizardClass;
+
+GtkWidget *ygtk_wizard_new (void);
+GType ygtk_wizard_get_type (void) G_GNUC_CONST;
+
+// Enable a steps or tree pane widget -- should be called right after
+// initilization and only _one_ of them
+void ygtk_wizard_enable_steps (YGtkWizard *wizard);
+void ygtk_wizard_enable_tree (YGtkWizard *wizard);
+
+// convinience method that removes the current child, if set, and swaps it by
+// the given one (you may pass NULL to just remove current child)
+void ygtk_wizard_set_child (YGtkWizard *wizard, GtkWidget *widget);
+
+// commands
+// (commands that may fail return a sucess boolean.)
+void ygtk_wizard_set_help_text (YGtkWizard *wizard, const gchar *text);
+
+// you may pass a window widget if you want the title/icon to be set on it as well
+void ygtk_wizard_set_header_text (YGtkWizard *wizard, GtkWindow *window,
+ const char *text);
+gboolean ygtk_wizard_set_header_icon (YGtkWizard *wizard, GtkWindow *window,
+ const char *icon);
+
+void ygtk_wizard_set_back_button_label (YGtkWizard *wizard, const char *text);
+void ygtk_wizard_set_abort_button_label (YGtkWizard *wizard, const char *text);
+void ygtk_wizard_set_next_button_label (YGtkWizard *wizard, const char *text);
+void ygtk_wizard_set_back_button_id (YGtkWizard *wizard, gpointer id,
+ GDestroyNotify destroy_cb);
+void ygtk_wizard_set_next_button_id (YGtkWizard *wizard, gpointer id,
+ GDestroyNotify destroy_cb);
+void ygtk_wizard_set_abort_button_id (YGtkWizard *wizard, gpointer id,
+ GDestroyNotify destroy_cb);
+void ygtk_wizard_enable_back_button (YGtkWizard *wizard, gboolean enable);
+void ygtk_wizard_enable_next_button (YGtkWizard *wizard, gboolean enable);
+void ygtk_wizard_enable_abort_button (YGtkWizard *wizard, gboolean enable);
+gboolean ygtk_wizard_is_next_button_protected (YGtkWizard *wizard);
+void ygtk_wizard_protect_next_button (YGtkWizard *wizard, gboolean protect);
+void ygtk_wizard_focus_next_button (YGtkWizard *wizard);
+void ygtk_wizard_focus_back_button (YGtkWizard *wizard);
+
+void ygtk_wizard_add_menu (YGtkWizard *wizard, const char *text,
+ const char *id);
+gboolean ygtk_wizard_add_menu_entry (YGtkWizard *wizard, const char *parent_id,
+ const char *text, const char *id);
+gboolean ygtk_wizard_add_sub_menu (YGtkWizard *wizard, const char *parent_id,
+ const char *text, const char *id);
+gboolean ygtk_wizard_add_menu_separator (YGtkWizard *wizard, const char *parent_id);
+
+void ygtk_wizard_add_step_header (YGtkWizard *wizard, const char *text);
+void ygtk_wizard_add_step (YGtkWizard *wizard, const char* text, const char *id);
+gboolean ygtk_wizard_set_current_step (YGtkWizard *wizard, const char *id);
+void ygtk_wizard_clear_steps (YGtkWizard *wizard);
+
+gboolean ygtk_wizard_add_tree_item (YGtkWizard *wizard, const char *parent_id,
+ const char *text, const char *id);
+void ygtk_wizard_clear_tree (YGtkWizard *wizard);
+gboolean ygtk_wizard_select_tree_item (YGtkWizard *wizard, const char *id);
+const gchar *ygtk_wizard_get_tree_selection (YGtkWizard *wizard);
+
+void ygtk_wizard_set_release_notes_button_label (YGtkWizard *wizard,
+ const gchar *text, gpointer id,
+ GDestroyNotify destroy_cb);
+void ygtk_wizard_show_release_notes_button (YGtkWizard *wizard, gboolean enable);
+
+// You should call this method rather than GtkWidget's if you want
+// to honor next_button protect flag
+void ygtk_wizard_set_sensitive (YGtkWizard *wizard, gboolean sensitive);
+
+G_END_DECLS
+#endif /* YGTK_WIZARD_H */
Added: trunk/gtk/test.sh
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/test.sh?rev=42515&view=auto
==============================================================================
--- trunk/gtk/test.sh (added)
+++ trunk/gtk/test.sh Thu Nov 29 18:25:41 2007
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+echo "Hackish script to run a ton of yast2-gtk test that we know"
+echo "should work and layout fairly nicely."
+
+if test "z$1" = "z"; then
+ tests="Label3 HelloWorld PushButton2 RichText1 Spacing1 Frame2"
+else
+ tests="$@"
+fi
+yast="/usr/lib/YaST2/bin/y2base"
+
+for test in $tests; do
+ $yast /usr/share/doc/packages/yast2-core/libyui/examples/$test.ycp gtk >& /dev/null &
+done
Added: trunk/gtk/tests/Cursor.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Cursor.ycp?rev=42515&v…
==============================================================================
--- trunk/gtk/tests/Cursor.ycp (added)
+++ trunk/gtk/tests/Cursor.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,21 @@
+// Cursor test
+{
+ UI::OpenDialog (
+ `VBox (
+ `IntField (`id (`time), "Work for (secs):", 0, 10, 2),
+ `PushButton (`id (`work), "&Work!"),
+ `PushButton (`id (`cancel), "&Close")
+ )
+ );
+
+ any ret = nil;
+ repeat {
+ ret = UI::UserInput();
+
+ if (ret == `work)
+ sleep ((integer) UI::QueryWidget (`time, `Value) * 1000);
+
+ } until (ret == `cancel);
+
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/FileDialog.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/FileDialog.ycp?rev=425…
==============================================================================
--- trunk/gtk/tests/FileDialog.ycp (added)
+++ trunk/gtk/tests/FileDialog.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,62 @@
+// Tests for file dialog calls:
+// string UI::AskForExistingFile (startWith, filter, headline)
+// string UI::AskForSaveFileName (startWith, filter, headline)
+// string UI::AskForExistingDirectory (startWith, headline)
+
+{
+ define void show_selected (string selected)
+ {
+ UI::OpenDialog (
+ `VBox (
+ `HBox (
+ `Label ("You have selected:"),
+ `Label (`opt (`outputField), selected)
+ ),
+ `PushButton ("OK")
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+ };
+
+ while (true) {
+ UI::OpenDialog (
+ `VBox (
+ `ComboBox (`id (`combo_action), "Action:",
+ [
+ `item (`id (`open_file), "Open File"),
+ `item (`id (`save_file), "Save File"),
+ `item (`id (`select_folder), "Select Folder")
+ ] ),
+ `TextEntry (`id (`entry_path), "Some path:"),
+ `TextEntry (`id (`entry_filter), "Filter:", "*"),
+ `HBox (
+ `PushButton (`id (`ok), "OK"),
+ `PushButton (`id (`cancel), "Cancel")
+ )
+ )
+ );
+ any ret = UI::UserInput();
+
+ if (ret == `cancel)
+ break;
+
+ string start_path = (string) UI::QueryWidget (`id (`entry_path), `Value);
+ string filter_str = (string) UI::QueryWidget (`id (`entry_filter), `Value);
+
+ string ret_path = nil;
+
+ any action = UI::QueryWidget (`id (`combo_action), `Value);
+ UI::CloseDialog();
+
+ if (action == `open_file)
+ ret_path = UI::AskForSaveFileName (start_path, filter_str, "Choose a File");
+ else if (action == `save_file)
+ ret_path = UI::AskForSaveFileName (start_path, filter_str, "Choose a File");
+ else if (action == `select_folder)
+ ret_path = UI::AskForSaveFileName (start_path, filter_str, "Choose a Folder");
+
+ if (ret_path != nil)
+ show_selected (ret_path);
+ }
+}
Added: trunk/gtk/tests/Frame.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Frame.ycp?rev=42515&vi…
==============================================================================
--- trunk/gtk/tests/Frame.ycp (added)
+++ trunk/gtk/tests/Frame.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,27 @@
+{
+UI::OpenDialog (
+ `VBox (
+ `Frame ("CPU &Speed",
+ `VBox (
+ `RadioButtonGroup(
+ `VBox (
+ `Left(`RadioButton("Normal")),
+ `Left(`RadioButton("Overclocked")),
+ `Left(`RadioButton("Red Hot")),
+ `Left(`RadioButton("Melting", true)),
+ `Left(`TextEntry ("Delay:", "20"))
+ )
+ ),
+ `Frame
+ ( "Exact speed",
+ `Slider ("CPU", 0, 100, 85)
+ )
+ )
+ ),
+ `PushButton("&OK")
+ )
+ );
+
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/IconButton.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/IconButton.ycp?rev=425…
==============================================================================
--- trunk/gtk/tests/IconButton.ycp (added)
+++ trunk/gtk/tests/IconButton.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,20 @@
+// PushButton with icons (relative path)
+{
+ UI::OpenDialog (
+ `VBox (
+ `Heading( "YaST2 Mini Control Center" ),
+ `IconButton (`id ("keyboard "), "yast-keyboard.png", "Keyboard"),
+ `IconButton (`id ("mouse" ), "yast-mouse.png", "Mouse"),
+ `IconButton (`id ("timezone" ), "yast-timezone.png", "Time zone"),
+ `IconButton (`id ("lan" ), "yast-lan.png", "Network"),
+ `IconButton (`id ("sw_single"), "yast-software.png", "Software")
+ )
+ );
+
+ string tool = (string) UI::UserInput();
+ UI::CloseDialog();
+
+ UI::OpenDialog (`Label ("Running " + tool + "..."));
+ sleep (4000);
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/IconItems-ComboBox.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/IconItems-ComboBox.ycp…
==============================================================================
--- trunk/gtk/tests/IconItems-ComboBox.ycp (added)
+++ trunk/gtk/tests/IconItems-ComboBox.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,25 @@
+// ComboBox with icons
+{
+ UI::OpenDialog (
+ `VBox (
+ `Heading( "YaST2 Mini Control Center" ),
+ `ComboBox (`id (`mod), `opt (`editable), "Modules",
+ [ "Auto-Yast",
+ `item(`id ("keyboard" ), `icon( "yast-keyboard.png"), "Keyboard" ),
+ `item(`id ("mouse" ), `icon( "yast-mouse.png" ), "Mouse" ),
+ `item(`id ("timezone" ), `icon( "yast-timezone.png"), "Time zone"),
+ `item(`id ("lan" ), `icon( "yast-lan.png" ), "Network" ),
+ `item(`id ("sw_single"), `icon( "yast-software.png"), "Software" )
+ ] ),
+ `PushButton("&OK")
+ )
+ );
+
+ UI::UserInput();
+ string tool = (string) UI::QueryWidget (`id(`mod ), `Value);
+ UI::CloseDialog();
+
+ UI::OpenDialog (`Label ("Running " + tool + "..."));
+ sleep (4000);
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/IconItems-MultiSelectionBox.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/IconItems-MultiSelecti…
==============================================================================
--- trunk/gtk/tests/IconItems-MultiSelectionBox.ycp (added)
+++ trunk/gtk/tests/IconItems-MultiSelectionBox.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,31 @@
+// ComboBox with icons
+{
+ UI::OpenDialog (
+ `VBox (
+ `Heading( "YaST2 Mini Control Center" ),
+ `MultiSelectionBox (`id (`mod), "Modules",
+ [ "auto-yast",
+ `item(`id ("keyboard" ), `icon( "yast-keyboard.png"), "Keyboard", true ),
+ `item(`id ("mouse" ), `icon( "yast-mouse.png" ), "Mouse", true ),
+ `item(`id ("timezone" ), `icon( "yast-timezone.png"), "Time zone"),
+ `item(`id ("lan" ), `icon( "yast-lan.png" ), "Network" ),
+ `item(`id ("sw_single"), `icon( "yast-software.png"), "Software" )
+ ] ),
+ `PushButton("&OK")
+ )
+ );
+
+ UI::UserInput();
+ list mods = (list) UI::QueryWidget (`id(`mod ), `SelectedItems);
+ UI::CloseDialog();
+
+ string text = "Running ";
+ foreach (`it, mods,
+ ``{ text = sformat( "%1, %2", text, it); }
+ );
+ text = text + "...";
+
+ UI::OpenDialog (`Label (text));
+ sleep (4000);
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/IconItems-SelectionBox.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/IconItems-SelectionBox…
==============================================================================
--- trunk/gtk/tests/IconItems-SelectionBox.ycp (added)
+++ trunk/gtk/tests/IconItems-SelectionBox.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,25 @@
+// ComboBox with icons
+{
+ UI::OpenDialog (
+ `VBox (
+ `Heading( "YaST2 Mini Control Center" ),
+ `SelectionBox (`id (`mod), "Modules",
+ [ "Auto-Yast",
+ `item(`id ("keyboard" ), `icon( "yast-keyboard.png"), "Keyboard" ),
+ `item(`id ("mouse" ), `icon( "yast-mouse.png" ), "Mouse" ),
+ `item(`id ("timezone" ), `icon( "yast-timezone.png"), "Time zone"),
+ `item(`id ("lan" ), `icon( "yast-lan.png" ), "Network" ),
+ `item(`id ("sw_single"), `icon( "yast-software.png"), "Software" )
+ ] ),
+ `PushButton("&OK")
+ )
+ );
+
+ UI::UserInput();
+ string mod = (string) UI::QueryWidget (`id(`mod ), `CurrentItem);
+ UI::CloseDialog();
+
+ UI::OpenDialog (`Label ("Running " + mod + "..."));
+ sleep (4000);
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/Image.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Image.ycp?rev=42515&vi…
==============================================================================
--- trunk/gtk/tests/Image.ycp (added)
+++ trunk/gtk/tests/Image.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,68 @@
+// Image test
+string filename = "tests/image.gif";
+
+{
+ UI::OpenDialog (
+ `VBox (
+ `ReplacePoint (`id (`replace_image),
+ `ColoredLabel ("Choose an image type option!", `rgb (0, 0, 0),
+ `rgb (255, 0, 0), 5)
+ ),
+
+ `Frame ("Image type:",
+ `RadioButtonGroup (`id(`rb),
+ `VBox(
+ `Left (`RadioButton(`id (`static),`opt(`notify), "&Static")),
+ `Left (`RadioButton(`id (`animation), `opt(`notify), "&Animation"))
+ )
+ )
+ ),
+
+ `Frame ("Image effect:",
+ `RadioButtonGroup (`id(`rb),
+ `VBox(
+ `Left (`RadioButton(`id (`no_effect), `opt(`notify), "&None", true)),
+ `Left (`RadioButton(`id (`tiled_effect),`opt(`notify), "&Tiled")),
+ `Left (`RadioButton(`id (`scaled_effect), `opt(`notify), "&Scaled"))
+ )
+ )
+ ),
+ `Right (`Label ("Resize the window!")),
+ `PushButton(`id (`close), "&Close")
+ )
+ );
+
+ any ret = nil;
+ while (true)
+ {
+ ret = UI::UserInput();
+ if (ret == `close || ret == `cancel)
+ break;
+
+ any type_opt = nil;
+ if (!(boolean) UI::QueryWidget(`id(`static), `Value))
+ type_opt = `animated;
+
+ any effect_opt = nil;
+ if ((boolean) UI::QueryWidget(`id(`tiled_effect), `Value))
+ effect_opt = `tiled;
+ else if ((boolean) UI::QueryWidget(`id(`scaled_effect), `Value))
+ effect_opt = `scaleToFit;
+
+ // needed for tiling (scaling sets this automatically, anyway...)
+ any zerowidth = nil;
+ any zeroheight = nil;
+ if (effect_opt != nil) {
+ zerowidth = `zeroWidth;
+ zeroheight = `zeroHeight;
+ }
+
+ UI::ReplaceWidget (`replace_image,
+ `Image (`opt (type_opt, effect_opt, zerowidth, zeroheight),
+ filename, filename + " not found"));
+
+ }
+
+ UI::CloseDialog();
+}
+
Added: trunk/gtk/tests/ImageMng.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/ImageMng.ycp?rev=42515…
==============================================================================
--- trunk/gtk/tests/ImageMng.ycp (added)
+++ trunk/gtk/tests/ImageMng.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,91 @@
+// Image test
+// TODO: make it getting the filename as an argument
+
+{
+ UI::OpenDialog (
+ `VBox (
+ `ReplacePoint (`id (`replace_image),
+ `ColoredLabel ("Choose an image first!", `rgb (0, 0, 0),
+ `rgb (255, 0, 0), 5)
+ ),
+
+ `Frame ("Which MNG file:",
+ `RadioButtonGroup (`id(`rb),
+ `VBox(
+ `Left (`RadioButton(`id (`movie1), `opt(`notify), "&Movie1")),
+ `Left (`RadioButton(`id (`movie2), `opt(`notify), "&Movie2")),
+ `Left (`RadioButton(`id (`movie3), `opt(`notify), "&Movie3")),
+ `Left (`RadioButton(`id (`movie4), `opt(`notify), "&Movie4")),
+ `Left (`RadioButton(`id (`movie5), `opt(`notify), "&Movie5")),
+ `Left (`RadioButton(`id (`movie6), `opt(`notify), "&Movie6")),
+ `Left (`RadioButton(`id (`movie7), `opt(`notify), "&Movie7")),
+ `Left (`RadioButton(`id (`movie8), `opt(`notify), "&Movie8"))
+ )
+ )
+ ),
+
+ `Frame ("Image effect:",
+ `RadioButtonGroup (`id(`rb),
+ `VBox(
+ `Left (`RadioButton(`id (`no_effect), `opt(`notify), "&None", true)),
+ `Left (`RadioButton(`id (`tiled_effect),`opt(`notify), "&Tiled")),
+ `Left (`RadioButton(`id (`scaled_effect), `opt(`notify), "&Scaled"))
+ )
+ )
+ ),
+ `Right (`Label ("Resize the window!")),
+ `PushButton(`id (`close), "&Close")
+ )
+ );
+
+ any ret = nil;
+ while (true)
+ {
+ ret = UI::UserInput();
+ if (ret == `close || ret == `cancel)
+ break;
+
+ any effect_opt = nil;
+ if ((boolean) UI::QueryWidget(`id(`tiled_effect), `Value))
+ effect_opt = `tiled;
+ else if ((boolean) UI::QueryWidget(`id(`scaled_effect), `Value))
+ effect_opt = `scaleToFit;
+
+ // needed for tiling (scaling sets this automatically, anyway...)
+ any zerowidth = nil;
+ any zeroheight = nil;
+ if (effect_opt != nil) {
+ zerowidth = `zeroWidth;
+ zeroheight = `zeroHeight;
+ }
+
+ string filename = "";
+ if ((boolean) UI::QueryWidget(`id(`movie1), `Value))
+ filename = "tests/movie1.mng";
+ else if ((boolean) UI::QueryWidget(`id(`movie2), `Value))
+ filename = "tests/movie2.mng";
+ else if ((boolean) UI::QueryWidget(`id(`movie3), `Value))
+ filename = "tests/movie3.mng";
+ else if ((boolean) UI::QueryWidget(`id(`movie4), `Value))
+ filename = "tests/movie4.mng";
+ else if ((boolean) UI::QueryWidget(`id(`movie5), `Value))
+ filename = "tests/movie5.mng";
+ else if ((boolean) UI::QueryWidget(`id(`movie6), `Value))
+ filename = "tests/movie6.mng";
+ else if ((boolean) UI::QueryWidget(`id(`movie7), `Value))
+ filename = "tests/movie7.mng";
+ else
+ filename = "tests/movie8.mng";
+
+ // to test inline images, uncomment next line and pass it to `Image
+ //byteblock data = (byteblock) SCR::Read (.target.byte, filename);
+
+ UI::ReplaceWidget (`replace_image,
+ `Image (`opt (`animated, effect_opt, zerowidth, zeroheight),
+ filename, filename + " not found"));
+
+ }
+
+ UI::CloseDialog();
+}
+
Added: trunk/gtk/tests/Layout-Align-Weight.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Align-Weight.yc…
==============================================================================
--- trunk/gtk/tests/Layout-Align-Weight.ycp (added)
+++ trunk/gtk/tests/Layout-Align-Weight.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,11 @@
+// alignment - weight test
+{
+UI::OpenDialog(
+ `HBox(
+ `Right (`HWeight (1, `PushButton ("Left"))),
+ `Left (`HWeight (1, `PushButton ("Right")))
+ )
+);
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-AlignStretch.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-AlignStretch.yc…
==============================================================================
--- trunk/gtk/tests/Layout-AlignStretch.ycp (added)
+++ trunk/gtk/tests/Layout-AlignStretch.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,15 @@
+// alignment (test case for inst_productsources bug)
+{
+UI::OpenDialog(
+ `VBox(
+ `HBox(
+ `PushButton ("Fixed"),
+ `Bottom (`PushButton ("Test"))
+ ),
+ `VWeight( 1, `MultiLineEdit("Description", "bla bla") )
+ )
+);
+UI::UserInput();
+UI::CloseDialog();
+}
+
Added: trunk/gtk/tests/Layout-Expand.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Expand.ycp?rev=…
==============================================================================
--- trunk/gtk/tests/Layout-Expand.ycp (added)
+++ trunk/gtk/tests/Layout-Expand.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,32 @@
+// Widgets expand and align
+{
+// stand-alone
+UI::OpenDialog(
+ `HBox(
+ `VBox (
+ `MultiLineEdit ("Multi Line Edit", "some text"),
+ `PushButton ("Yes")
+ ),
+ `PushButton ("No")
+ )
+ );
+UI::UserInput();
+
+// on wizard
+UI::OpenDialog(
+ `Wizard (`back, "&Back", `abort, "Ab&ort", `next, "&Next")
+ );
+
+UI::ReplaceWidget (`id (`contents),
+ `HBox(
+ `VBox (
+ `MultiLineEdit ("Multi Line Edit", "some text"),
+ `PushButton ("Yes")
+ ),
+ `PushButton ("No")
+ )
+ );
+
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-Frame2.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Frame2.ycp?rev=…
==============================================================================
--- trunk/gtk/tests/Layout-Frame2.ycp (added)
+++ trunk/gtk/tests/Layout-Frame2.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,18 @@
+{
+ UI::OpenDialog( `VBox(
+ `Frame ( `opt (`vstretch), "CPU &Speed",
+ `RadioButtonGroup(
+ `VBox(
+ `Left(`RadioButton("Normal" )),
+ `Left(`RadioButton("Overclocked" )),
+ `Left(`RadioButton("Red Hot" )),
+ `Left(`RadioButton("Melting", true ))
+ )
+ )
+ ),
+ `PushButton("&OK")
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-HVCenter-Align.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-HVCenter-Align.…
==============================================================================
--- trunk/gtk/tests/Layout-HVCenter-Align.ycp (added)
+++ trunk/gtk/tests/Layout-HVCenter-Align.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,9 @@
+// HVCenter alignment test
+{
+UI::OpenDialog(
+ `HVCenter (`ColoredLabel(`opt (`hstretch, `vstretch), "Hello, World!", `rgb (200, 0, 0), `rgb (200, 200, 50), 20))
+);
+
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-ReplacePoint.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-ReplacePoint.yc…
==============================================================================
--- trunk/gtk/tests/Layout-ReplacePoint.ycp (added)
+++ trunk/gtk/tests/Layout-ReplacePoint.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,13 @@
+// replacement stretchable test
+{
+UI::OpenDialog(
+ `ReplacePoint (`id (`rp), `PushButton ("Push Me!"))
+);
+
+UI::UserInput();
+
+UI::ReplaceWidget (`rp, `MultiLineEdit ("", "I should be all stretched!"));
+
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-Split-Split.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Split-Split.ycp…
==============================================================================
--- trunk/gtk/tests/Layout-Split-Split.ycp (added)
+++ trunk/gtk/tests/Layout-Split-Split.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,21 @@
+// Split in a split behavior
+{
+UI::OpenDialog (`opt (`defaultsize), `HBox (`PushButton ("Okay")));
+UI::UserInput();
+
+UI::OpenDialog (`opt (`defaultsize), `HBox (`PushButton ("Okay"), `VBox (`PushButton ("Nay"), `PushButton ("Pay"))));
+UI::UserInput();
+
+UI::OpenDialog(`opt (`defaultsize), `Wizard (`back, "&Back", `abort, "Ab&ort", `next, "&Next"));
+UI::ReplaceWidget (`contents, `HBox (`VBox(`PushButton ("Okay")), `VBox (`PushButton ("Nay"), `PushButton ("Pay"))));
+UI::UserInput();
+
+UI::OpenDialog (`opt (`defaultsize), `VBox (`HBox (`VBox(`PushButton ("Okay")), `VBox (`PushButton ("Nay"), `PushButton ("Pay")))));
+UI::UserInput();
+
+UI::OpenDialog (`opt (`defaultsize), `VBox (`HBox(`PushButton ("Okay"))));
+UI::UserInput();
+
+UI::OpenDialog (`opt (`defaultsize), `HBox (`VBox(`PushButton ("Okay"))));
+UI::UserInput();
+}
Added: trunk/gtk/tests/Layout-Truncated-Widget.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Truncated-Widge…
==============================================================================
--- trunk/gtk/tests/Layout-Truncated-Widget.ycp (added)
+++ trunk/gtk/tests/Layout-Truncated-Widget.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,43 @@
+// Let's create and destroy something
+
+{
+
+list strings =
+ [ "What a long button I am :D", ":/" ];
+integer cur_string = 1;
+
+UI::OpenDialog
+ (
+ `VBox
+ (
+ `ReplacePoint(`id(`kill_replaceable), `PushButton( `id(`kill),
+ "I am a waste of space" )),
+ `PushButton( `id(`transform), select(strings, cur_string, nil) ),
+ `PushButton( `id(`quit), "Exit" )
+ )
+ );
+
+any button_id = nil;
+
+while (true)
+ {
+ button_id = UI::UserInput();
+
+ if (button_id == `quit)
+ break;
+
+ if (button_id == `transform)
+ {
+ cur_string = (cur_string + 1) % 2;
+ UI::ChangeWidget (`transform, `Label, select(strings, cur_string, nil));
+ }
+
+ if (button_id == `kill)
+ {
+ UI::ReplaceWidget (`kill_replaceable, `Empty());
+ }
+
+
+ }
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-Wizard-BackgroundWidget.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Wizard-Backgrou…
==============================================================================
--- trunk/gtk/tests/Layout-Wizard-BackgroundWidget.ycp (added)
+++ trunk/gtk/tests/Layout-Wizard-BackgroundWidget.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,15 @@
+// Widget with background on wizard
+{
+UI::OpenDialog (`opt(`defaultsize),
+ `Wizard (`back, "&Back", `abort, "Ab&ort", `next, "&Next")
+ );
+
+ UI::ReplaceWidget (`contents,
+ `VBox (
+ `HVCenter (`BackgroundPixmap ("wallpapers/welcome.jpg"),
+ `MultiLineEdit ("", "I should have a background around me."))
+ )
+ );
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-Wizard-OneWidget.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Wizard-OneWidge…
==============================================================================
--- trunk/gtk/tests/Layout-Wizard-OneWidget.ycp (added)
+++ trunk/gtk/tests/Layout-Wizard-OneWidget.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,13 @@
+// wizard, one widget test
+{
+UI::OpenDialog(
+ `Wizard (`back, "&Back", `abort, "Ab&ort", `next, "&Next")
+);
+
+UI::ReplaceWidget (`contents, `ColoredLabel(`opt (`hstretch, `vstretch), "Hello, World!", `rgb (200, 0, 0), `rgb (200, 200, 50), 20));
+// non-stretchable:
+//UI::ReplaceWidget (`contents, `ColoredLabel("Hello, World!", `rgb (200, 0, 0), `rgb (200, 200, 50), 20));
+
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Layout-Wizard3.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Layout-Wizard3.ycp?rev…
==============================================================================
--- trunk/gtk/tests/Layout-Wizard3.ycp (added)
+++ trunk/gtk/tests/Layout-Wizard3.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,30 @@
+// The widget should get center aligned on wizard, but not ordinary dialogs
+{
+// stand-alone
+UI::OpenDialog(
+ `VBox(
+ `Heading ("Header"),
+ `VSpacing (0.5),
+ `Label ("This text should get on top")
+ )
+ );
+UI::UserInput();
+
+// on wizard
+UI::OpenDialog(
+ `Wizard (`back, "&Back", `abort, "Ab&ort", `next, "&Next")
+ );
+
+
+UI::ReplaceWidget (`id (`contents),
+ `VBox(
+ `Heading ("Header"),
+ `VSpacing (0.5),
+ `Label ("This text should get centered")
+ )
+ );
+
+
+UI::UserInput();
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/MainDialogs.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/MainDialogs.ycp?rev=42…
==============================================================================
--- trunk/gtk/tests/MainDialogs.ycp (added)
+++ trunk/gtk/tests/MainDialogs.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,38 @@
+// This is a test for the usage of multiple main dialogs
+// (that is with the defaultsize attribute). They should
+// all share the same window.
+
+{
+ UI::OpenDialog (`opt (`defaultsize),
+ `VBox (
+ `Heading ("First dialog"),
+ `PushButton (`id (`next), "Next"),
+ `PushButton ("Close")
+ )
+ );
+
+ while (UI::UserInput() == `next) {
+ UI::OpenDialog (`opt (`defaultsize),
+ `VBox (
+ `Heading ("Second dialog"),
+ `PushButton (`id (`next), "Next"),
+ `PushButton ("Back")
+ )
+ );
+
+ while (UI::UserInput() == `next) {
+ UI::OpenDialog (`opt (`defaultsize),
+ `VBox (
+ `Heading ("Third dialog"),
+ `PushButton ("Close")
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+ }
+
+ UI::CloseDialog();
+ }
+
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/MultiProgressMeterHuge.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/MultiProgressMeterHuge…
==============================================================================
--- trunk/gtk/tests/MultiProgressMeterHuge.ycp (added)
+++ trunk/gtk/tests/MultiProgressMeterHuge.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,39 @@
+// Simple example for MultiProgressMeter
+{
+ if ( ! UI::HasSpecialWidget(`HMultiProgressMeter ) )
+ {
+ UI::OpenDialog(
+ `VBox(
+ `Label("Error: This UI doesn't support the MultiProgressMeter widget!"),
+ `PushButton(`opt(`default), "&OK")
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+
+ return;
+ }
+
+
+ UI::OpenDialog(
+ `VBox(
+ `HMultiProgressMeter(`id(`prog), [ 10000, 200, 500, 20, 100 ] ),
+ `PushButton(`opt(`default), "&Ok" )
+ )
+ );
+
+ UI::ChangeWidget(`prog, `Values, [ 1000, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 800, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 500, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 200, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 200, 500, 20, 100 ] ); UI::UserInput();
+
+ UI::ChangeWidget(`prog, `Values, [ 0, 100, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 20, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 500, 20, 100 ] ); UI::UserInput();
+
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 400, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 300, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 200, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 100, 20, 100 ] ); UI::UserInput();
+}
Added: trunk/gtk/tests/MultiProgressMeterVer.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/MultiProgressMeterVer.…
==============================================================================
--- trunk/gtk/tests/MultiProgressMeterVer.ycp (added)
+++ trunk/gtk/tests/MultiProgressMeterVer.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,39 @@
+// Simple example for MultiProgressMeter
+{
+ if ( ! UI::HasSpecialWidget(`HMultiProgressMeter ) )
+ {
+ UI::OpenDialog(
+ `VBox(
+ `Label("Error: This UI doesn't support the MultiProgressMeter widget!"),
+ `PushButton(`opt(`default), "&OK")
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+
+ return;
+ }
+
+
+ UI::OpenDialog(
+ `VBox(
+ `VMultiProgressMeter(`id(`prog), [ 100, 200, 500, 20, 100 ] ),
+ `PushButton(`opt(`default), "&Ok" )
+ )
+ );
+
+ UI::ChangeWidget(`prog, `Values, [ 1000, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 800, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 500, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 200, 200, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 200, 500, 20, 100 ] ); UI::UserInput();
+
+ UI::ChangeWidget(`prog, `Values, [ 0, 100, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 20, 500, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 500, 20, 100 ] ); UI::UserInput();
+
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 400, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 300, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 200, 20, 100 ] ); UI::UserInput();
+ UI::ChangeWidget(`prog, `Values, [ 0, 0, 100, 20, 100 ] ); UI::UserInput();
+}
Added: trunk/gtk/tests/MultiSelectionBox.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/MultiSelectionBox.ycp?…
==============================================================================
--- trunk/gtk/tests/MultiSelectionBox.ycp (added)
+++ trunk/gtk/tests/MultiSelectionBox.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,16 @@
+// MultiSelectionBox -- test notify flag
+{
+list items =
+ [ "Spaghetti", "Steak Sandwich", "Chili", "Salami Baguette" ];
+
+UI::OpenDialog (
+ `MinSize (30, 10,
+ `MultiSelectionBox (`id(`list), `opt (`notify),
+ "Plates", items)
+ )
+ );
+
+UI::UserInput();
+UI::CloseDialog();
+}
+
Added: trunk/gtk/tests/PollInput.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/PollInput.ycp?rev=4251…
==============================================================================
--- trunk/gtk/tests/PollInput.ycp (added)
+++ trunk/gtk/tests/PollInput.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,26 @@
+// Event pooling -- test bug that causes package manager post-script
+// `cancel events to be ignored.
+{
+ UI::OpenDialog (
+ `VBox(
+ `Label ("Blocked - UserInput()"),
+ `PushButton (`id (`button), "Ok")
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+
+ UI::OpenDialog (
+ `VBox(
+ `Label ("Un-blocked - PollInput()"),
+ `PushButton (`id (`button), "Ok")
+ )
+ );
+ any event = nil;
+ repeat {
+ sleep (1000);
+ event = UI::PollInput();
+ } until (event != nil);
+ UI::CloseDialog();
+}
+
Added: trunk/gtk/tests/ProgressPulse.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/ProgressPulse.ycp?rev=…
==============================================================================
--- trunk/gtk/tests/ProgressPulse.ycp (added)
+++ trunk/gtk/tests/ProgressPulse.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,30 @@
+// Simple ProgressBar example
+{
+ integer max_progress = 0;
+ integer progress = 0;
+
+ UI::OpenDialog(
+ `VBox(
+ `ProgressBar(`id(`pr), "Sample progress bar", max_progress, progress ),
+ `PushButton(`id(`next), "Next"),
+ `Right(`PushButton(`id(`close), "&Close" ) )
+ )
+ );
+
+
+ while ( progress < 20 )
+ {
+ symbol button = (symbol) UI::UserInput();
+
+ if ( button == `next )
+ {
+ progress = progress + 1;
+ UI::ChangeWidget(`id(`pr), `Value, progress);
+ UI::ChangeWidget(`id(`pr), `Label, sformat("Progress %1 of %2", progress, max_progress ));
+ }
+ else if ( button == `close )
+ break;
+ }
+
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/RichText1.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/RichText1.ycp?rev=4251…
==============================================================================
--- trunk/gtk/tests/RichText1.ycp (added)
+++ trunk/gtk/tests/RichText1.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,26 @@
+// RichText test
+
+{
+ UI::OpenDialog (
+ `VBox (
+ `RichText (`id (`rtext), ""),
+ `MultiLineEdit (`id (`source), `opt(`notify), "Source code", ""),
+ `PushButton (`id (`close), `opt(`default), "&Close")
+ )
+ );
+
+ any ret = nil;
+ repeat
+ {
+ ret = UI::UserInput();
+
+ if (ret == `source)
+ {
+ UI::ChangeWidget (`id (`rtext), `Value,
+ (string) UI::QueryWidget(`id(`source), `Value));
+ }
+
+ } until (ret == `close || ret == `cancel);
+
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/RichText2.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/RichText2.ycp?rev=4251…
==============================================================================
--- trunk/gtk/tests/RichText2.ycp (added)
+++ trunk/gtk/tests/RichText2.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,89 @@
+// RichText test (with a list of examples)
+{
+ list texts = [
+ // simple
+ "<p><a href=\"nowhere\">Hello world!</a></p>",
+ "<h1>Operating Systems</h1><h2>Linux</h2> Suse",
+
+ // the br & hr tags
+ "Drinking <u>ice</u> tea <br> <hr> is <b>good</b> for you.",
+
+ // Broken end element
+ "Broken end element </ul> elided",
+
+ // the li tags
+ "Things to do <li>foo <li>baa <li>baz.",
+
+ // unclosed tags
+ "No outer tag<p>Unclosed paragraphs<p>several of them <b>unclosed bold</b>",
+
+ // Some more complete text, with an image
+ "<center><h1><font color=blue>Super <font color=red>Man</font></font> "
+ + "to the rescue</h1></center><a "
+ + "href=http://en.wikipedia.org/wiki/Superman>Super Man</a> is a very "
+ + "estimated super hero in Metropolis, but he is looked down by others "
+ + "like mad scientists and politiceans. <img src=\"tests/image.gif\">",
+
+ // table (from SlideShow)
+ "<table cellspacing=\"10\" cellpadding=\"5\">"
+ + "<tr>"
+ + "<td width =\"*\">"
+ + "<img src=\"/opt/gnome/share/icons/hicolor/32x32/apps/gnome-media-player.png\""
+ + "width=\"100\" align=\"left\">"
+ + "</td>"
+ + "<td width=\"*\">"
+ + "<p><font color=\"#00007f\"><b>XMMS and JuK - Powerful Jukeboxes</b></font></p>"
+ + "<p>XMMS is an excellent sound player for Linux. It is easy to use and supports"
+ + "various formats, including audio CDs. Test the many visualization plug-ins or"
+ + "download your favorite XMMS skins from the web.</p>"
+ + "<p>New in KDE: JuK, which classifies your MP3s and organizes your music"
+ + "collection.</p>"
+ + "<p><b>Want More?</b></p>"
+ + "<p>The SUSE distribution features a wide range of applications for playing"
+ + "your CDs and MP3 songs. For example, KsCD is a user-friendly CD player. The"
+ + "track information for most CDs is available on the Internet. Simply activate"
+ + "the respective function to display the list.</p>"
+ + "</td>"
+ + "</tr>"
+ + "</table>"
+ ];
+
+ UI::OpenDialog (
+ `VBox (
+ `RichText (`id (`rtext), texts[0]:nil),
+ `MultiLineEdit (`id (`source), `opt(`notify), "Source code", texts[0]:nil),
+ `Label (`id(`link), `opt(`hstretch), ""),
+ `Slider (`id (`slider), `opt(`notify), "Test text case:", 0, size (texts)-1, 0),
+ `PushButton (`id (`close), `opt(`icon ("close")), "&Close")
+ )
+ );
+
+ any ret = nil;
+ repeat
+ {
+ ret = UI::UserInput();
+
+ if (ret == `slider)
+ {
+ integer cur_text = (integer) UI::QueryWidget(`id(`slider), `Value );
+ UI::ChangeWidget (`id (`source), `Value, texts[cur_text]:nil);
+ UI::ChangeWidget (`id (`rtext), `Value, texts[cur_text]:nil);
+ UI::ChangeWidget (`id(`link), `Value, "");
+ }
+
+ else if (ret == `source)
+ {
+ UI::ChangeWidget (`id (`rtext), `Value,
+ (string) UI::QueryWidget(`id(`source), `Value));
+ }
+
+ else
+ { // RichText doesn't seem to pass its id...
+ string url = sformat ("%1", ret);
+ UI::ChangeWidget (`id(`link), `Value, "You pressed: " + url);
+ }
+
+ } until (ret == `close || ret == `cancel);
+
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/SelectionBox.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/SelectionBox.ycp?rev=4…
==============================================================================
--- trunk/gtk/tests/SelectionBox.ycp (added)
+++ trunk/gtk/tests/SelectionBox.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,45 @@
+// SelectionBox change and lookup test
+{
+list itemlist1 =
+ [ "Spaghetti", "Steak Sandwich", "Chili", "Salami Baguette" ];
+
+list itemlist2 =
+ [ "Mercedes", "AUDI", "VW", "BMW", "Porsche" ];
+
+list itemslists = [ itemlist1, itemlist2 ];
+
+integer listnum = 0;
+
+UI::OpenDialog (
+ `VBox (
+ `MinSize (30, 10,
+ `SelectionBox (`id(`list), `opt (`immediate),
+ "Prices", itemlist1)
+ ),
+ `TextEntry (`id(`text), "Current item:", ""),
+ `Right (
+ `HBox (
+ `PushButton (`id (`next), "Change &List Contents"),
+ `PushButton (`id (`cancel), "&Close")
+ )
+ )
+ )
+ );
+
+any ret = nil;
+while (ret != `cancel) {
+ ret = UI::UserInput();
+
+ if (ret == `next) {
+ listnum = 1 - listnum;
+ UI::ChangeWidget (`id(`list), `Items, select (itemslists, listnum, nil));
+ }
+
+ if (ret == `list) {
+ string item = (string) UI::QueryWidget(`id(`list), `CurrentItem);
+ UI::ChangeWidget (`id (`text), `Value, item);
+ }
+}
+
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/StockIcons.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/StockIcons.ycp?rev=425…
==============================================================================
--- trunk/gtk/tests/StockIcons.ycp (added)
+++ trunk/gtk/tests/StockIcons.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,55 @@
+// Stock Icons test
+
+{
+ list stock_icons = [
+ "ok",
+ "cancel",
+ "abort",
+ "apply",
+ "about",
+ "connect",
+ "disconnect",
+ "edit",
+ "open",
+ "close",
+ "new",
+ "quit",
+ "print",
+ "save",
+ "save-as",
+ "yes",
+ "no",
+
+ ];
+ integer i = 0;
+
+ UI::OpenDialog (
+ `ReplacePoint (`id (`rp),
+ `PushButton (`opt (`icon (stock_icons[i]:nil)), stock_icons[i]:"")
+ )
+ );
+
+ any ret = nil;
+ while (true)
+ {
+ ret = UI::TimeoutUserInput (1000);
+
+ if (ret == `timeout)
+ {
+ i = i + 1;
+ if (i == size (stock_icons))
+ break;
+ else
+ UI::ReplaceWidget (`rp,
+ `PushButton (`opt (`icon (stock_icons[i]:nil)), stock_icons[i]:"")
+ );
+ UI::RecalcLayout();
+ }
+
+ else
+ break;
+
+ };
+
+ UI::CloseDialog();
+}
Added: trunk/gtk/tests/Table3-4.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Table3-4.ycp?rev=42515…
==============================================================================
--- trunk/gtk/tests/Table3-4.ycp (added)
+++ trunk/gtk/tests/Table3-4.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,68 @@
+// merge of Table3 and Table4 tests
+{
+list itemlist1 =
+ [ `item(`id(3), "Spaghetti", 8),
+ `item(`id(4), "Steak Sandwich", 12),
+ `item(`id(1), "Chili", 6),
+ `item(`id(2), "Salami Baguette", nil)
+ ];
+
+list itemlist2 =
+ [ `item(`id(0), "Mercedes", 60000),
+ `item(`id(1), "AUDI", 50000),
+ `item(`id(2), "VW", 40000),
+ `item(`id(3), "BMW", 60000),
+ `item(`id(3), "Porsche", 80000)
+ ];
+
+list itemslists = [ itemlist1, itemlist2 ];
+
+integer listnum = 0;
+
+UI::OpenDialog (
+ `VBox (
+ `Heading ("Prices"),
+ `MinSize (30, 10,
+ `Table (`id(`table), `header("Name", "price"), itemlist1)
+ ),
+ `Right (
+ `HBox (
+ `PushButton (`id (`lookup), "&Lookup"),
+ `PushButton (`id (`next), "Change &Table Contents"),
+ `PushButton (`id (`cancel), "&Close")
+ )
+ )
+ )
+ );
+
+any ret = nil;
+while (ret != `cancel) {
+ ret = UI::UserInput();
+
+ if (ret == `next) {
+ listnum = 1 - listnum;
+ UI::ChangeWidget(`id(`table), `Items, select(itemslists, listnum, nil));
+ }
+
+ if (ret == `lookup) {
+ any id = UI::QueryWidget(`id(`table), `CurrentItem);
+ if (is(id, integer)) {
+ string text = sformat (
+ "Line: %1", UI::QueryWidget(`id(`table), `Item(id)));
+ UI::OpenDialog (
+ `MarginBox (1, 0.2,
+ `VBox (
+ `Left (`Label ("Current Table Item")),
+ `Label(`opt(`outputField), text),
+ `PushButton("&OK")
+ )
+ )
+ );
+ UI::UserInput();
+ UI::CloseDialog();
+ }
+ }
+}
+
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/Tree3.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Tree3.ycp?rev=42515&vi…
==============================================================================
--- trunk/gtk/tests/Tree3.ycp (added)
+++ trunk/gtk/tests/Tree3.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,123 @@
+{
+ // Build a dialog with a tree for directory selection, three
+ // buttons with common values and a label that directly echoes any
+ // selected directory.
+ //
+ // The tree in this example uses the `notify option that makes
+ // UI::UserInput() return immediately as soon as the user selects a
+ // tree item rather than the default behaviour which waits for the
+ // user to activate a button.
+
+ UI::OpenDialog(
+ `MinWidth( 50,
+ `VBox(
+ `Tree(`id(`dest_dir),
+ `opt(`notify),
+ "Select destination directory:",
+ [
+ `item( "/" , true,
+ [
+ `item( "etc",
+ [
+ `item("opt"),
+ `item("SuSEconfig"),
+ `item("X11")
+ ]
+ ),
+ `item( "usr", false,
+ [
+ "bin",
+ "lib",
+ `item("share",
+ [
+ "man",
+ "info",
+ "emacs"
+ ]
+ ),
+ `item( `id(`usr_local), "local" ),
+ `item("X11R6",
+ [
+ "bin",
+ "lib",
+ "share",
+ "man",
+ "etc"
+ ]
+ )
+ ]
+ ),
+ `item( `id(`opt), "opt", true,
+ [
+ "kde",
+ "netscape",
+ "Office51"
+ ]
+ ),
+ `item("home"),
+ "work",
+ `item( "<other>")
+ ]
+ )
+ ] ),
+ `HBox(
+ `PushButton(`id(`sel_opt), `opt(`hstretch), "/&opt" ),
+ `PushButton(`id(`sel_usr), `opt(`hstretch), "/&usr" ),
+ `PushButton(`id(`sel_usr_local), `opt(`hstretch), "/usr/&local" )
+ ),
+ `HBox(
+ `HWeight( 2, `Label("Current Item:") ),
+ `HWeight( 5, `Label(`id(`echoItem), `opt(`outputField, `hstretch), "") )
+ ),
+ `HBox(
+ `HWeight( 2, `Label("Current Branch:") ),
+ `HWeight( 5, `Label(`id(`echoBranch), `opt(`outputField, `hstretch), "") )
+ ),
+ `HBox(
+ `HWeight( 2, `Label("Current Path:") ),
+ `HWeight( 5, `Label(`id(`echoPath), `opt(`outputField, `hstretch), "") )
+ ),
+ `PushButton(`id(`ok), `opt(`default, `icon ("ok")), "&OK")
+ )
+ )
+ );
+
+ any id = nil;
+
+ repeat
+ {
+ id = UI::UserInput();
+
+ if ( id == `sel_usr) UI::ChangeWidget( `id( `dest_dir ), `CurrentItem, "usr" );
+ else if ( id == `sel_usr_local) UI::ChangeWidget( `id( `dest_dir ), `CurrentItem, `usr_local );
+ else if ( id == `sel_opt) UI::ChangeWidget( `id( `dest_dir ), `CurrentItem, `opt );
+ else if ( id == `dest_dir)
+ {
+ any current_dir = UI::QueryWidget(`dest_dir, `CurrentItem );
+
+ if ( current_dir != nil )
+ UI::ChangeWidget( `id( `echoItem ), `Value, sformat( "%1", current_dir ) );
+
+ list<string> current_branch = (list<string>) UI::QueryWidget(`dest_dir, `CurrentBranch );
+
+ if ( current_branch != nil )
+ {
+ UI::ChangeWidget(`echoBranch, `Value, sformat( "%1", current_branch) );
+
+ string current_path = mergestring( current_branch, "/" );
+ if ( size( current_path ) > 2 )
+ // Remove duplicate "/" at start
+ current_path = substring( current_path, 1, size( current_path )-1 );
+
+ UI::ChangeWidget(`echoPath, `Value, sformat( "%1", current_path ) );
+ }
+ }
+
+ } until ( id == `ok );
+
+
+ // Close the dialog.
+ // Remember to read values from the dialog's widgets BEFORE closing it!
+ UI::CloseDialog();
+
+}
Added: trunk/gtk/tests/WizardList.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/WizardList.ycp?rev=425…
==============================================================================
--- trunk/gtk/tests/WizardList.ycp (added)
+++ trunk/gtk/tests/WizardList.ycp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,33 @@
+{
+UI::OpenDialog(
+ `Wizard (`opt (`treeEnabled),
+ `back, "", `cancel, "", `cancel, "&Exit")
+ );
+
+UI::WizardCommand (`AddTreeItem ("", "Computer", "computer"));
+UI::WizardCommand (`AddTreeItem ("computer", "Hardware", "hardware"));
+UI::WizardCommand (`AddTreeItem ("hardware", "CPU", "cpu@hardware"));
+UI::WizardCommand (`AddTreeItem ("cpu@hardware", "MMU", "mmu"));
+UI::WizardCommand (`AddTreeItem ("hardware", "RAM", "ram@hardware"));
+UI::WizardCommand (`AddTreeItem ("computer", "Software", "software"));
+
+any ret = nil;
+repeat {
+ ret = UI::UserInput();
+
+ string selected = (string) UI::QueryWidget (`id(`wizard), `CurrentItem );
+
+ if (selected == "mmu") {
+ UI::ReplaceWidget (`id (`contents),
+ `Label ("MMU setup")
+ );
+ }
+ if (selected == "ram@hardware") {
+ UI::ReplaceWidget (`id (`contents),
+ `Label ("RAM setup")
+ );
+ }
+} until (ret == `cancel);
+
+UI::CloseDialog();
+}
Added: trunk/gtk/tests/image.gif
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/image.gif?rev=42515&vi…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie1.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie1.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie2.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie2.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie3.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie3.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie4.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie4.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie5.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie5.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie6.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie6.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie7.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie7.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/tests/movie8.mng
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/movie8.mng?rev=42515&v…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/yast2-gtk.spec.in
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/yast2-gtk.spec.in?rev=42515&…
==============================================================================
--- trunk/gtk/yast2-gtk.spec.in (added)
+++ trunk/gtk/yast2-gtk.spec.in Thu Nov 29 18:25:41 2007
@@ -0,0 +1,35 @@
+@HEADER-COMMENT@
+
+@HEADER@
+Source2: yast2-gtk-rpmlintrc
+BuildRequires: blocxx-devel gcc-c++ libxcrypt-devel libzypp-devel yast2-core-devel yast2-devtools gtk2-devel
+Summary: YaST2 - Gtk Graphical User Interface
+Provides: yast2_ui
+
+%description
+One of several user interfaces available for YaST2, based on GTK and
+the X Window System.
+
+
+
+Authors:
+--------
+ Ricardo Cruz
+ Michael Meeks
+
+@PREP@
+
+@BUILD@
+
+@INSTALL@
+rm $RPM_BUILD_ROOT%{_libdir}/YaST2/plugin/libpy2gtk.la
+
+@CLEAN@
+
+%files
+%defattr (-, root, root)
+%doc @docdir@
+%{_libdir}/YaST2/plugin/libpy2gtk.so.*
+%{_libdir}/YaST2/plugin/libpy2gtk.so
+
+
Added: trunk/gtk/ycc.sh
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/ycc.sh?rev=42515&view=auto
==============================================================================
--- trunk/gtk/ycc.sh (added)
+++ trunk/gtk/ycc.sh Thu Nov 29 18:25:41 2007
@@ -0,0 +1,53 @@
+#!/bin/sh
+# Usage: Run this script with no argument to be presented
+# with Yast modules. 'z' argument for Yast-core shipped
+# examples. 'x' for our own set of tests.
+
+ZENITY_BINARY=zenity
+Y2BASE_BINARY="/usr/lib/YaST2/bin/y2base -l /dev/stderr"
+
+DEFAULT_DIR=/usr/share/YaST2/clients
+RUN_QT=0
+
+if [ $# -gt 0 ]; then
+ if [ "$1" == "z" ]; then
+ DEFAULT_DIR=/usr/share/doc/packages/yast2-core/libyui/examples
+ fi
+ if [ "$1" == "x" ]; then
+ DEFAULT_DIR=.
+ # go to the tests directory
+ # (this doesn't affect user's cwd because this
+ # is running in its own shell.)
+ cd "`dirname $0`/tests"
+ fi
+ if [ "$1" == "help" ]; then
+ echo "ycc.sh usage:"
+ echo " \"$0\" - yast modules"
+ echo " \"$0 z\" - yast-core examples"
+ echo " \"$0 x\" - our set of tests"
+ echo " pass \"qt\" to also run the qt frontend"
+ echo ""
+ exit
+ fi
+ if [ "$1" == "qt" ]; then
+ RUN_QT=1
+ fi
+fi
+
+if [ $# -eq 2 ] && [ "$2" == "qt" ]; then
+ RUN_QT=1
+fi
+
+module_list=`ls $DEFAULT_DIR/*.ycp | sed 's/.*\///'`
+while true; do
+ module=`$ZENITY_BINARY --title "Yast Control Center" \
+ --list --column "Available modules:" $module_list`;
+ if [ "$module" ]; then
+ if [ $RUN_QT -eq 1 ]; then
+ $Y2BASE_BINARY "$DEFAULT_DIR/$module" qt &
+ fi
+ $Y2BASE_BINARY "$DEFAULT_DIR/$module" gtk
+ else
+ exit 0;
+ fi
+done
Added: trunk/gtk/ycc/Makefile
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/ycc/Makefile?rev=42515&view=…
==============================================================================
--- trunk/gtk/ycc/Makefile (added)
+++ trunk/gtk/ycc/Makefile Thu Nov 29 18:25:41 2007
@@ -0,0 +1,16 @@
+# Yast Control Center (Yast-GTK)
+
+CC = g++
+CFLAGS = -Wall `pkg-config gtk+-2.0 --cflags`
+LIBS =`pkg-config gtk+-2.0 --libs`
+
+all: ycc-gtk
+
+ycc.o: ycc.cpp
+ $(CC) $(CFLAGS) ycc.cpp -c -o ycc.o
+
+ycc-gtk: ycc.o
+ $(CC) $(LIBS) ycc.o -o ycc-gtk
+
+clean:
+ rm -f *.o *~ ycc-gtk
Added: trunk/gtk/ycc/ycc.cpp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/ycc/ycc.cpp?rev=42515&view=a…
==============================================================================
--- trunk/gtk/ycc/ycc.cpp (added)
+++ trunk/gtk/ycc/ycc.cpp Thu Nov 29 18:25:41 2007
@@ -0,0 +1,269 @@
+/* Yast Control Center (Yast-GTK) */
+
+#include <string>
+#include <set>
+#include <map>
+#include <list>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Definitions */
+#define YAST_GROUPS "/usr/share/applications/YaST2/groups/"
+#define YAST_ENTRIES "/usr/share/applications/YaST2/"
+#define ICONS "/usr/share/YaST2/theme/current/icons/32x32/apps/"
+
+/* Globals */
+static GtkWidget *window;
+
+/* Get all names of files in a certain directory. */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+std::set<std::string> subfiles(const std::string& path) {
+ DIR *dirStructP;
+ struct dirent *direntp;
+ std::set <std::string> sfiles;
+
+ if((dirStructP = opendir(path.c_str())) != NULL) {
+ while((direntp = readdir(dirStructP)) != NULL) {
+ std::string filename;
+ struct stat buf;
+ filename = path + "/" + direntp->d_name;
+
+ if(std::string (direntp->d_name) == "." ||
+ std::string (direntp->d_name) == "..")
+ continue; // ignore . and .. directories
+
+ if (stat(filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
+ sfiles.insert(direntp->d_name);
+ }
+ closedir(dirStructP);
+ }
+ return sfiles;
+}
+
+/* Erase everything from the given characters. */
+void erase_from (std::string &str, const std::string &chars)
+{
+ for (unsigned int i = 0; i < chars.length(); i++) {
+ std::string::size_type pos;
+ pos = str.find (chars[i], 0);
+ if (pos != std::string::npos)
+ str.erase (pos);
+ }
+}
+
+/* The widget with the icons. */
+class View {
+ GtkWidget *m_widget;
+ GtkAdjustment *adjustment;
+ std::map <std::string, GtkListStore*> m_stores;
+ std::list <std::string> sort_keys;
+
+public:
+ View()
+ {
+ m_widget = gtk_notebook_new();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (m_widget), GTK_POS_LEFT);
+ }
+
+ ~View() {}
+
+ GtkWidget *getWidget()
+ { return m_widget; }
+
+ void addGroup (const gchar *name, const gchar *icon_path,
+ const gchar *nick, const gchar *sort_key)
+ {
+ // calculate position
+ int pos;
+ {
+ std::list <std::string>::iterator it;
+ for (it = sort_keys.begin(), pos = 0; it != sort_keys.end(); it++, pos++)
+ if (strcmp (it->c_str(), sort_key) >= 0)
+ break;
+ sort_keys.insert (it, sort_key);
+ }
+
+ // label widget
+ GtkWidget *tab_label, *image, *label;
+
+ GdkPixbuf *icon = NULL;
+ if (icon_path) {
+ GError *error = 0;
+ std::string path = ICONS + std::string (icon_path) + ".png";
+ icon = gdk_pixbuf_new_from_file (path.c_str(), &error);
+ if (!icon)
+ g_warning ("Could not load icon: %s.\nReason: %s", icon_path, error->message);
+ }
+
+ tab_label = gtk_hbox_new (FALSE, 0);
+ label = gtk_label_new (name);
+ if (icon)
+ image = gtk_image_new_from_pixbuf (icon);
+
+ if (icon)
+ gtk_box_pack_start (GTK_BOX (tab_label), image, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (tab_label), label, TRUE, TRUE, icon ? 6 : 0);
+
+ // page widget
+ GtkListStore *store = gtk_list_store_new (3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+ m_stores [nick] = store;
+
+ GtkWidget *icons_view;
+ icons_view = gtk_icon_view_new_with_model (GTK_TREE_MODEL (store));
+ gtk_icon_view_set_text_column (GTK_ICON_VIEW (icons_view), 0);
+ gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (icons_view), 1);
+ g_signal_connect(G_OBJECT (icons_view), "item-activated",
+ G_CALLBACK (executeCommand), this);
+
+ GtkWidget *page;
+ page = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (page), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (page), icons_view);
+
+ // add those to the notebook
+ gtk_widget_show_all (tab_label);
+ gtk_notebook_insert_page_menu (GTK_NOTEBOOK (m_widget), page, tab_label, NULL, pos);
+ }
+
+ void addEntry (const gchar *group, const gchar *name,
+ const gchar *icon_path, const gchar *execute)
+ {
+ GtkListStore *store = m_stores [group];
+ if (!store) {
+ g_warning ("Didn't find group '%s' for entry '%s'.", group, name);
+ return;
+ }
+
+ GdkPixbuf *icon = NULL;
+ if (icon_path) {
+ GError *error = 0;
+ std::string path = ICONS + std::string (icon_path) + ".png";
+ icon = gdk_pixbuf_new_from_file (path.c_str(), &error);
+ if (!icon)
+ g_warning ("Could not load icon: %s.\nReason: %s", icon_path, error->message);
+ }
+
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, name, 1, icon, 2, execute, -1);
+ }
+
+ static void executeCommand (GtkIconView *iconview, GtkTreePath *path, View *pThis)
+ {
+ GtkTreeModel *model = gtk_icon_view_get_model (iconview);
+ GtkTreeIter iter;
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ gchar *command_;
+ gtk_tree_model_get (model, &iter, 2, &command_, -1);
+
+ std::string command = command_;
+ g_free (command_);
+
+ command += " &";
+ printf ("running %s\n", command.c_str());
+ system (command.c_str());
+
+ static GdkCursor *cursor = NULL;
+ if (!cursor) {
+ GdkDisplay *display = gtk_widget_get_display (window);
+ cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+ }
+ gdk_window_set_cursor (window->window, cursor);
+ g_timeout_add (1500, set_normal_cursor_cb, NULL);
+ }
+ }
+
+ static gboolean set_normal_cursor_cb (gpointer data)
+ {
+ gdk_window_set_cursor (window->window, NULL);
+ return FALSE;
+ }
+};
+
+/* Main code */
+int main(int argc, char* argv[])
+{
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "Suse Control Center");
+ gtk_window_set_default_size (GTK_WINDOW (window), 650, 400);
+ g_signal_connect(G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ bool is_root = getuid () == 0;
+
+ View view;
+ { // adding groups
+ GKeyFile *file = g_key_file_new();
+ std::set <std::string> groups = subfiles (YAST_GROUPS);
+ for (std::set <std::string>::iterator it = groups.begin();
+ it != groups.end(); it++) {
+ if (!g_key_file_load_from_file (file, (YAST_GROUPS + (*it)).c_str(),
+ G_KEY_FILE_NONE, NULL))
+ continue;
+
+ gchar* name = g_key_file_get_locale_string (file, "Desktop Entry", "Name", 0, NULL);
+ gchar *nick = g_key_file_get_string (file, "Desktop Entry", "X-SuSE-YaST-Group", NULL);
+ gchar *icon = g_key_file_get_string (file, "Desktop Entry", "Icon", NULL);
+ gchar *sort_key = g_key_file_get_string (file, "Desktop Entry",
+ "X-SuSE-YaST-SortKey", NULL);
+ if (name && nick)
+ view.addGroup (name, icon, nick, sort_key);
+
+ if (name) g_free (name);
+ if (nick) g_free (nick);
+ if (icon) g_free (icon);
+ if (sort_key) g_free (sort_key);
+ }
+ g_key_file_free (file);
+ }
+ { // adding entries
+ GKeyFile *file = g_key_file_new();
+ std::set <std::string> entries = subfiles (YAST_ENTRIES);
+ for (std::set <std::string>::iterator it = entries.begin();
+ it != entries.end(); it++) {
+ if (!g_key_file_load_from_file (file, (YAST_ENTRIES + (*it)).c_str(),
+ G_KEY_FILE_NONE, NULL))
+ continue;
+
+ gchar *group = g_key_file_get_string (file, "Desktop Entry", "X-SuSE-YaST-Group", NULL);
+ gchar* name = g_key_file_get_locale_string (file, "Desktop Entry", "Name", 0, NULL);
+ gchar *icon = g_key_file_get_string (file, "Desktop Entry", "Icon", NULL);
+ gchar *command = g_key_file_get_string (file, "Desktop Entry", "Exec", NULL);
+ gboolean needs_root = g_key_file_get_boolean (file, "Desktop Entry",
+ "X-SuSE-YaST-RootOnly", NULL);
+
+ if (group && name && command && (!needs_root || is_root))
+ view.addEntry (group, name, icon, command);
+
+ if (group) g_free (group);
+ if (name) g_free (name);
+ if (icon) g_free (icon);
+ if (command) g_free (command);
+ }
+ g_key_file_free (file);
+ }
+
+ gtk_container_add (GTK_CONTAINER (window), view.getWidget());
+ gtk_widget_show_all (window);
+
+ if (!is_root) {
+ GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+ GtkDialogFlags (0), GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
+ "You are executing the control center as an ordinary user.\n"
+ "Only a few modules will be available.");
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
+
+ gtk_main();
+ return 0;
+}
--
To unsubscribe, e-mail: yast-commit+unsubscribe(a)opensuse.org
For additional commands, e-mail: yast-commit+help(a)opensuse.org
1
0
[yast-commit] r42514 - in /trunk/gtk/unstable: integrate/ mockups/ mockups/package-selector/ mockups/wizard-look/ package/ src/ src/icons/ tests/ ycc/
by rpmcruz@svn.opensuse.org 29 Nov '07
by rpmcruz@svn.opensuse.org 29 Nov '07
29 Nov '07
Author: rpmcruz
Date: Thu Nov 29 18:22:01 2007
New Revision: 42514
URL: http://svn.opensuse.org/viewcvs/yast?rev=42514&view=rev
Log:
Branching.
Added:
trunk/gtk/unstable/integrate/
trunk/gtk/unstable/integrate/YaST2.call
trunk/gtk/unstable/integrate/yast2 (with props)
trunk/gtk/unstable/integrate/yast2-funcs
trunk/gtk/unstable/mockups/
trunk/gtk/unstable/mockups/package-selector/
trunk/gtk/unstable/mockups/package-selector/christian-package-selector-1.png (with props)
trunk/gtk/unstable/mockups/package-selector/christian-package-selector-2.png (with props)
trunk/gtk/unstable/mockups/package-selector/christian-patterns.png (with props)
trunk/gtk/unstable/mockups/package-selector/martin-package-selector-1.gif (with props)
trunk/gtk/unstable/mockups/package-selector/packagekit-groups.png (with props)
trunk/gtk/unstable/mockups/package-selector/packagekit-search.png (with props)
trunk/gtk/unstable/mockups/package-selector/ricado-split-use-cases.svg
trunk/gtk/unstable/mockups/package-selector/ubuntu-add-remove-applications.jpg (with props)
trunk/gtk/unstable/mockups/wizard-look/
trunk/gtk/unstable/mockups/wizard-look/installer-mockup.png (with props)
trunk/gtk/unstable/mockups/wizard-look/jakub-installer-mockup.jpg (with props)
trunk/gtk/unstable/mockups/wizard-look/jakub-mockup.svg
trunk/gtk/unstable/mockups/wizard-look/ricardo-installer-mockup.svg
trunk/gtk/unstable/mockups/wizard-look/tools-mockup.png (with props)
trunk/gtk/unstable/package/
trunk/gtk/unstable/package/yast2-gtk-rpmlintrc
trunk/gtk/unstable/package/yast2-gtk.changes
trunk/gtk/unstable/src/
trunk/gtk/unstable/src/.cvsignore
trunk/gtk/unstable/src/Makefile
trunk/gtk/unstable/src/Makefile.am
trunk/gtk/unstable/src/Makefile.in
trunk/gtk/unstable/src/Y2CCGtk.cc
trunk/gtk/unstable/src/YGBarGraph.cc
trunk/gtk/unstable/src/YGComboBox.cc
trunk/gtk/unstable/src/YGDialog.cc
trunk/gtk/unstable/src/YGDialog.h
trunk/gtk/unstable/src/YGDumbTab.cc
trunk/gtk/unstable/src/YGFrame.cc
trunk/gtk/unstable/src/YGImage.cc
trunk/gtk/unstable/src/YGIntField.cc
trunk/gtk/unstable/src/YGLabel.cc
trunk/gtk/unstable/src/YGLayout.cc
trunk/gtk/unstable/src/YGMenuButton.cc
trunk/gtk/unstable/src/YGMultiLineEdit.cc
trunk/gtk/unstable/src/YGPackageSelector.cc
trunk/gtk/unstable/src/YGPackageSelector.cc-ori
trunk/gtk/unstable/src/YGProgressBar.cc
trunk/gtk/unstable/src/YGPushButton.cc
trunk/gtk/unstable/src/YGRadioButton.cc
trunk/gtk/unstable/src/YGTable.cc
trunk/gtk/unstable/src/YGTextEntry.cc
trunk/gtk/unstable/src/YGTime.cc
trunk/gtk/unstable/src/YGTree.cc
trunk/gtk/unstable/src/YGUI.cc
trunk/gtk/unstable/src/YGUI.h
trunk/gtk/unstable/src/YGUtils.cc
trunk/gtk/unstable/src/YGUtils.h
trunk/gtk/unstable/src/YGWidget.cc
trunk/gtk/unstable/src/YGWidget.h
trunk/gtk/unstable/src/YGWizard.cc
trunk/gtk/unstable/src/YGi18n.h
trunk/gtk/unstable/src/dummy.cc
trunk/gtk/unstable/src/icons/
trunk/gtk/unstable/src/icons/cat-development.xpm
trunk/gtk/unstable/src/icons/cat-documentation.xpm
trunk/gtk/unstable/src/icons/cat-emulators.xpm
trunk/gtk/unstable/src/icons/cat-games.xpm
trunk/gtk/unstable/src/icons/cat-hardware.xpm
trunk/gtk/unstable/src/icons/cat-multimedia.xpm
trunk/gtk/unstable/src/icons/cat-network.xpm
trunk/gtk/unstable/src/icons/cat-office.xpm
trunk/gtk/unstable/src/icons/cat-system.xpm
trunk/gtk/unstable/src/icons/cat-utilities.xpm
trunk/gtk/unstable/src/icons/pkg-3D.xpm
trunk/gtk/unstable/src/icons/pkg-available-locked.xpm
trunk/gtk/unstable/src/icons/pkg-available.xpm
trunk/gtk/unstable/src/icons/pkg-install-auto.xpm
trunk/gtk/unstable/src/icons/pkg-install.xpm
trunk/gtk/unstable/src/icons/pkg-installed-locked.xpm
trunk/gtk/unstable/src/icons/pkg-installed-upgradable-locked.xpm
trunk/gtk/unstable/src/icons/pkg-installed-upgradable.xpm
trunk/gtk/unstable/src/icons/pkg-installed.xpm
trunk/gtk/unstable/src/icons/pkg-list-mode.xpm
trunk/gtk/unstable/src/icons/pkg-locked.xpm
trunk/gtk/unstable/src/icons/pkg-remove-auto.xpm
trunk/gtk/unstable/src/icons/pkg-remove.xpm
trunk/gtk/unstable/src/icons/pkg-tiles-mode.xpm
trunk/gtk/unstable/src/icons/pkg-unlocked.xpm
trunk/gtk/unstable/src/mng-loader.c
trunk/gtk/unstable/src/mng-loader.h
trunk/gtk/unstable/src/test.cc
trunk/gtk/unstable/src/ygdkmngloader.c
trunk/gtk/unstable/src/ygdkmngloader.c-old
trunk/gtk/unstable/src/ygdkmngloader.h
trunk/gtk/unstable/src/ygtkbargraph.c
trunk/gtk/unstable/src/ygtkbargraph.h
trunk/gtk/unstable/src/ygtkfieldentry.c
trunk/gtk/unstable/src/ygtkfieldentry.h
trunk/gtk/unstable/src/ygtkfindentry.c
trunk/gtk/unstable/src/ygtkfindentry.h
trunk/gtk/unstable/src/ygtkhtmlwrap.c
trunk/gtk/unstable/src/ygtkhtmlwrap.h
trunk/gtk/unstable/src/ygtkmenubutton.c
trunk/gtk/unstable/src/ygtkmenubutton.h
trunk/gtk/unstable/src/ygtkratiobox.c
trunk/gtk/unstable/src/ygtkratiobox.h
trunk/gtk/unstable/src/ygtkrichtext.c
trunk/gtk/unstable/src/ygtkrichtext.h
trunk/gtk/unstable/src/ygtksteps.c
trunk/gtk/unstable/src/ygtksteps.h
trunk/gtk/unstable/src/ygtkwizard.c
trunk/gtk/unstable/src/ygtkwizard.h
trunk/gtk/unstable/src/ygtkzyppwrapper.cc
trunk/gtk/unstable/src/ygtkzyppwrapper.h
trunk/gtk/unstable/src/yzyppwrapper.cc
trunk/gtk/unstable/src/yzyppwrapper.h
trunk/gtk/unstable/tests/
trunk/gtk/unstable/tests/Beep.ycp (with props)
trunk/gtk/unstable/tests/Cursor.ycp
trunk/gtk/unstable/tests/FileDialog.ycp
trunk/gtk/unstable/tests/Frame.ycp
trunk/gtk/unstable/tests/IconButton.ycp (with props)
trunk/gtk/unstable/tests/IconItems-ComboBox.ycp (with props)
trunk/gtk/unstable/tests/IconItems-MultiSelectionBox.ycp (with props)
trunk/gtk/unstable/tests/IconItems-SelectionBox.ycp (with props)
trunk/gtk/unstable/tests/Image.ycp
trunk/gtk/unstable/tests/ImageMng.ycp
trunk/gtk/unstable/tests/Layout-Align-Weight.ycp (with props)
trunk/gtk/unstable/tests/Layout-AlignStretch.ycp
trunk/gtk/unstable/tests/Layout-Expand.ycp (with props)
trunk/gtk/unstable/tests/Layout-Frame2.ycp (with props)
trunk/gtk/unstable/tests/Layout-HVCenter-Align.ycp (with props)
trunk/gtk/unstable/tests/Layout-ReplacePoint.ycp (with props)
trunk/gtk/unstable/tests/Layout-Split-Split.ycp (with props)
trunk/gtk/unstable/tests/Layout-Truncated-Widget.ycp (with props)
trunk/gtk/unstable/tests/Layout-Wizard-BackgroundWidget.ycp (with props)
trunk/gtk/unstable/tests/Layout-Wizard-OneWidget.ycp (with props)
trunk/gtk/unstable/tests/Layout-Wizard3.ycp (with props)
trunk/gtk/unstable/tests/MainDialogs.ycp
trunk/gtk/unstable/tests/MultiProgressMeterHuge.ycp
trunk/gtk/unstable/tests/MultiProgressMeterVer.ycp
trunk/gtk/unstable/tests/MultiSelectionBox.ycp
trunk/gtk/unstable/tests/ProgressPulse.ycp
trunk/gtk/unstable/tests/RichText1.ycp
trunk/gtk/unstable/tests/RichText2.ycp
trunk/gtk/unstable/tests/SelectionBox.ycp (with props)
trunk/gtk/unstable/tests/StockIcons.ycp
trunk/gtk/unstable/tests/Table3-4.ycp (with props)
trunk/gtk/unstable/tests/TransientDialog.ycp
trunk/gtk/unstable/tests/Tree3.ycp
trunk/gtk/unstable/tests/WizardList.ycp
trunk/gtk/unstable/tests/image.gif (with props)
trunk/gtk/unstable/tests/movie-endless.mng-old (with props)
trunk/gtk/unstable/tests/movie1.mng (with props)
trunk/gtk/unstable/tests/movie2.mng (with props)
trunk/gtk/unstable/tests/movie3.mng (with props)
trunk/gtk/unstable/tests/movie4.mng (with props)
trunk/gtk/unstable/tests/movie5.mng (with props)
trunk/gtk/unstable/tests/movie6.mng (with props)
trunk/gtk/unstable/tests/movie7.mng (with props)
trunk/gtk/unstable/tests/movie8.mng (with props)
trunk/gtk/unstable/ycc/
trunk/gtk/unstable/ycc/Makefile
trunk/gtk/unstable/ycc/ycc.cpp
Added: trunk/gtk/unstable/integrate/YaST2.call
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/integrate/YaST2.cal…
==============================================================================
--- trunk/gtk/unstable/integrate/YaST2.call (added)
+++ trunk/gtk/unstable/integrate/YaST2.call Thu Nov 29 18:22:01 2007
@@ -0,0 +1,779 @@
+#!/bin/sh
+#================
+# FILE : YaST2.call
+#----------------
+# PROJECT : YaST (Yet another Setup Tool v2)
+# COPYRIGHT : (c) 2004 SUSE Linux AG, Germany. All rights reserved
+# :
+# AUTHORS : Steffen Winterfeldt <snwint(a)suse.de>
+# . Arvin Schnell <arvin(a)suse.de>
+# : Marcus Schaefer <ms(a)suse.de>
+# :
+# BELONGS TO : System installation and Administration
+# :
+# DESCRIPTION : This is the main script to start the YaST2 installer
+# : according to the possible installation environments
+# : These are:
+# : ---
+# : - Standard Installation Qt/X11 or text based
+# : - Via serial line ttyS0/115200 baud, 8N1, RTS/CTS
+# : which is the same as the NCURSES mode
+# : - VNC Installation via browser
+# :
+# :
+# STATUS : $Id: YaST2.call 32688 2006-09-04 14:05:17Z locilka $
+#----------------
+#
+#set -x
+
+. /etc/YaST2/XVersion
+
+#=============================================
+# Functions...
+#---------------------------------------------
+#----[ wait_for_x11 ]----#
+function wait_for_x11() {
+#------------------------------------------------------
+# after a X-Server has been started you can wait until
+# the server is ready for requests using this function
+# ---
+ server_running=0
+ TESTX=/usr/sbin/testX
+ while kill -0 $xserver_pid 2>/dev/null ; do
+ sleep 1
+ if test -e /tmp/.X11-unix/X0 && test -x $TESTX ; then
+ $TESTX "$YaST2color" 2>/dev/null
+ err=$?
+ # exit code 1 -> XOpenDisplay failed...
+ if test $err = 1;then
+ log "\tTestX: XOpenDisplay failed"
+ server_running=0
+ continue
+ fi
+ # exit code 2 -> color or dimensions doesn't fit...
+ if test $err = 2;then
+ log "\tTestX: color or dimensions doesn't fit"
+ kill $xserver_pid
+ server_running=0
+ break;
+ fi
+ server_running=1
+ break
+ fi
+ done
+}
+
+#----[ get_bus_id ]----#
+function get_bus_id () {
+#------------------------------------------------------
+# ask the PCi bus for the location of the first
+# graphics card.
+# ---
+ for line in $(/sbin/lspci -n | grep "Class 0300" | cut -f 1 -d " ");do
+ echo $line |\
+ grep -q -E "^[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]"
+ if [ $? = 0 ];then
+ PCIBus=$(echo $line | cut -f1 -d:);
+ PCISlot=$(echo $line | cut -f2 -d: | cut -f 1 -d.);
+ PCIFunc=$(echo $line | cut -f2 -d.);
+ log "\tFound standard BusID: $PCIBus:$PCISlot:$PCIFunc"
+ printf "PCI:%d@0:%d:%d" \
+ 0x$PCIBus 0x$PCISlot 0x$PCIFunc
+ break
+ else
+ echo $line |\
+ grep -q -E "^[0-9a-f]{4}:[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]"
+ if [ $? = 0 ];then
+ PCIDomain=$(echo $line | cut -f1 -d:);
+ PCIBus=$(echo $line | cut -f2 -d:);
+ PCISlot=$(echo $line | cut -f3 -d: | cut -f 1 -d.);
+ PCIFunc=$(echo $line | cut -f2 -d.);
+ log "\tFound domain BusID: $PCIBus@$PCIDomain:$PCISlot $PCIFunc"
+ printf "PCI:%d@%d:%d:%d" \
+ 0x$PCIBus 0x$PCIDomain 0x$PCISlot 0x$PCIFunc
+ break
+ fi
+ fi
+ done
+}
+
+#----[ count_qt_geometry ]----#
+function count_qt_geometry () {
+ # current X-resolution, display 0
+ XRES=$(/usr/sbin/xquery -d :0 -r)
+
+ log "\t===Qt Geometry==="
+ log "\tResolution: ${XRES}"
+
+ # current X and Y resolution
+ XRES_X=$(echo $XRES | sed 's|[0123456789]\+ \([0123456789]\+\)x[0123456789]\+|\1|') #'
+ XRES_Y=$(echo $XRES | sed 's|[0123456789]\+ [0123456789]\+x\([0123456789]\+\)|\1|') #'
+
+ log "\tX: ${XRES_X}"
+ log "\tY: ${XRES_Y}"
+
+ # default values, minimal window 640x480
+ WINDOW_SIZE_X=640
+ WINDOW_SIZE_Y=480
+ OFFSET_X=0
+ OFFSET_Y=0
+ BACKGROUND_IMAGE=""
+
+ # cannot get any X-resolution
+ if [ "${XRES}" == "" ]; then
+ # cannot find out X resolution
+ WINDOW_SIZE_X=800
+ WINDOW_SIZE_Y=600
+ # reasonable
+ else
+ # FIXME: recount background image
+ BACKGROUND_IMAGE="/usr/lib/YaST2/startup/bkg.png"
+
+ # must be bigger or equal to 1400x1050
+ if [ "$(expr $XRES_X \>= 1400)" == "1" ] && [ "$(expr $XRES_Y \>= 1050)" == "1" ]; then
+ WINDOW_SIZE_X=1024
+ WINDOW_SIZE_Y=786
+ # must be bigger or equal to 800x600
+ elif [ "$(expr $XRES_X \>= 800)" == "1" ] && [ "$(expr $XRES_Y \>= 600)" == "1" ]; then
+ WINDOW_SIZE_X=800
+ WINDOW_SIZE_Y=600
+ fi
+
+ # X and Y offsets
+ OFFSET_X=$(expr ${XRES_X} - ${WINDOW_SIZE_X})
+ OFFSET_X=$(expr ${OFFSET_X} / 2)
+ OFFSET_Y=$(expr ${XRES_Y} - ${WINDOW_SIZE_Y})
+ OFFSET_Y=$(expr ${OFFSET_Y} / 2)
+ fi
+
+ log "\tWindow size X: ${WINDOW_SIZE_X}"
+ log "\tWindow size X: ${WINDOW_SIZE_Y}"
+ log "\tOffset X: ${OFFSET_X}"
+ log "\tOffset X: ${OFFSET_Y}"
+
+ # final window geometry, 'Window_XxWindow_Y+Offset_X+Offset_Y'
+ X_GEOMETRY="${WINDOW_SIZE_X}x${WINDOW_SIZE_Y}+${OFFSET_X}+${OFFSET_Y}"
+
+ log "\tUsed geometry: ${X_GEOMETRY}"
+}
+
+#----[ prepare_for_qt ]----#
+function prepare_for_qt () {
+#------------------------------------------------------
+# prepare Qt installation
+# ---
+ export LD_LIBRARY_PATH="/opt/gnome/lib:$LD_LIBRARY_PATH"
+
+ #=============================================
+ # Setup Qt environment
+ #---------------------------------------------
+ set_inst_qt_env
+ set_splash 100
+
+ #=============================================
+ # patch X11 conf. if not update/continue mode
+ #---------------------------------------------
+ if [ ! -f /var/lib/YaST2/runme_at_boot ];then
+ if [ ! -f /etc/X11/xorg.conf.instorig ];then
+ # create backup copy...
+ cp /etc/X11/xorg.conf /etc/X11/xorg.conf.instorig
+
+ # Activate correct device/screen section...
+ sed -e "s#Screen.*Screen\[.*\]#Screen "\""Screen[$X11_CONFIG_ID]#" \
+ /etc/X11/xorg.conf >/etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+
+ # update core pointer input device section...
+ if [ -f "/usr/sbin/xupdate" ];then
+ cat /etc/X11/xorg.conf | \
+ /usr/sbin/xupdate > /etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+ fi
+
+ # update driver and busID if accelerated driver should be used...
+ if [ "$X11_CONFIG_ID" = 0 ];then
+ # replace BusID placeholder with real busID
+ XBusID=$(get_bus_id)
+ if [ ! -z "$XBusID" ];then
+ sed -e 's/#BusID/BusID/' \
+ -e "s#1:0:0#$XBusID#" /etc/X11/xorg.conf \
+ > /etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+ fi
+
+ # replace driver placeholder with real name
+ sed -e "s#ChangeMe#$XServer#" /etc/X11/xorg.conf \
+ > /etc/X11/xorg.conf.new
+ mv /etc/X11/xorg.conf.new /etc/X11/xorg.conf
+ fi
+ fi
+ fi
+ #=============================================
+ # start X-Server and wait until ready
+ #---------------------------------------------
+ if [ ! -z "$NEED_XSERVER" ];then
+ export DISPLAY=:0
+ [ -z $Xstartpath ] || ln -snf $Xbindir/XFree86 /var/X11R6/bin/X
+ $Xexecutable -deferglyphs 16 2>/dev/tty8 1>&2 vt07 &
+ xserver_pid=$!
+ wait_for_x11
+ if [ "$server_running" = 1 ];then
+ log "\tX-Server is ready: $xserver_pid"
+ fi
+ fi
+ #=============================================
+ # set YaST2 Qt options for local displays
+ #---------------------------------------------
+ if [ ! -z "$NEED_XSERVER" ];then
+ Y2_UI_ARGS="--noborder --auto-fonts"
+ count_qt_geometry
+ if [ "${X_GEOMETRY}" != "" ]; then
+ Y2_UI_ARGS="${Y2_UI_ARGS} -geometry ${X_GEOMETRY}"
+ fi
+ fi
+}
+
+#----[ prepare_for_ncurses ]----#
+function prepare_for_ncurses () {
+#------------------------------------------------------
+# prepare NCURSES installation
+# ---
+ #=============================================
+ # Create Braille config if not update mode
+ #---------------------------------------------
+ if [ $INST_MODE = "normal" ];then
+ if [ ! -z "$Braille" ];then
+ log "Braille config needed, setting up braille display"
+ sed -e "s#brlname=.*#brlname=$Braille#" \
+ -e "s#brlport=.*#brlport=$Brailledevice#" /etc/suse-blinux.conf \
+ >/tmp/suse-blinux.conf
+ mv -f /tmp/suse-blinux.conf /etc
+ /etc/init.d/suse-blinux start
+ fi
+ fi
+ #=============================================
+ # Check for FbIterm
+ #---------------------------------------------
+ check_run_fbiterm
+ log "\tCheck for FB-I-terminal: RUN_FBITERM = $RUN_FBITERM"
+}
+
+#----[ prepare_for_ssh ]----#
+function prepare_for_ssh () {
+#------------------------------------------------------
+# prepare SSH installation
+# ---
+#
+ :
+}
+
+#----[ prepare_for_vnc ]----#
+function prepare_for_vnc () {
+#------------------------------------------------------
+# prepare VNC installation
+# ---
+#
+ #=============================================
+ # Setup splash screen
+ #---------------------------------------------
+ set_splash 100
+
+ #=============================================
+ # Setup y2base options
+ #---------------------------------------------
+ # xxx
+ #Y2_UI_ARGS="--fullscreen --noborder --auto-fonts"
+ Y2_UI_ARGS="--noborder --auto-fonts"
+
+ #=============================================
+ # Setup VNC server and start it
+ #---------------------------------------------
+ setupVNCAuthentication
+ if [ $VNCPASS_EXCEPTION = 0 ];then
+ disable_splash
+ startVNCServer
+ wait_for_x11
+ if [ "$server_running" = 1 ];then
+ log "\tXvnc-Server is ready: $xserver_pid"
+ fi
+ fi
+}
+
+function check_gtk()
+{
+ echo "silly stub check_gtk"
+ return 0
+}
+
+#----[ check_Qt ]----#
+function check_Qt () {
+#------------------------------------------------------
+# check if the prepared medium Qt is valid
+# ---
+ if [ ! -z "$NEED_XSERVER" ];then
+ if [ "$server_running" = 0 ];then
+ # /.../
+ # X-Server couldn't be started, selecting
+ # NCURSES mode as fallback ?
+ # ---
+ log "\tX-Server couldn't be started, falling back to ncurses"
+ Y2_MODE_FLAGS='("text_fallback")'
+ SELECTED_MEDIUM="NCURSES"
+ prepare_for_ncurses
+ Y2_MODE=ncurses
+ fi
+ else
+ /usr/sbin/testX --fast 2>/dev/null
+ if test $? = 1;then
+ log "\tCannot access Display: $DISPLAY, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ prepare_for_ncurses
+ Y2_MODE=ncurses
+ fi
+ fi
+}
+
+#----[ check_network ]----#
+function check_network () {
+#------------------------------------------------------
+# check if the prepared medium SSH is valid. It is valid
+# if there is a network interface accessable and we are
+# able to use ncurses or X11
+# ---
+ if ! found_iface ; then
+ # /.../
+ # No network interface found for SSH or VNC installation
+ # this is a fatal error here
+ # ---
+ log "\tNo network interface found, fatal error"
+ fatalError
+ fi
+ if [ ! -z "$DISPLAY" ];then
+ log "\tDisplay: $DISPLAY found for network install"
+ Y2_MODE=gtk
+ fi
+ if ! check_gtk ; then
+ log "\tQt plugin check failed falling back to ncurses"
+ Y2_MODE=ncurses
+ fi
+}
+
+#----[ check_vnc ]----#
+function check_vnc () {
+#------------------------------------------------------
+# check if the prepared medium VNC is valid
+# ---
+ check_network
+ if [ $VNCPASS_EXCEPTION = 1 ];then
+ log "\tVNC access has been disabled due to a password exception"
+ log "\tPlease make sure the password is at least 8 characters long"
+ fatalError
+ fi
+ if [ "$server_running" = 0 ];then
+ # /.../
+ # XVnc server couldn't be started, what to do now, I think
+ # this is a fatal error here
+ # ---
+ log "\tXVnc server couldn't be started, fatal error"
+ fatalError
+ fi
+}
+
+#----[ start_yast ]----#
+function start_yast () {
+#------------------------------------------------------
+# Start YaST2 refering to the contents of the Y2_*
+# startup variables
+# ---
+ local overcommit
+ read overcommit < /proc/sys/vm/overcommit_memory
+ echo "*** Starting YaST2 ***"
+ log "\tAllow big memory allocation: overcommit_memory=1"
+ echo 1 > /proc/sys/vm/overcommit_memory
+ if [ "$SPLASH" = yes -a -x /sbin/splash -a -n "$SPLASHCFG" ];then
+ /sbin/splash -t "YaST running"
+ fi
+ export QT_IM_MODULE=xim
+
+ if [ "$RUN_FBITERM" = "1" ]; then
+ OPT_FBITERM=/usr/bin/fbiterm
+ else
+ OPT_FBITERM=
+ fi
+
+ # set up a background if any needed
+ if [ "${BACKGROUND_IMAGE}" != "" ]; then
+ log "\tUsing background: ${BACKGROUND_IMAGE}"
+ fvwm-root --dither ${BACKGROUND_IMAGE}
+ fi
+
+ log "\tStarting YaST2:"
+ log "\tMODULE_NAME: $Y2_MODULE_NAME"
+ log "\tMODE_FLAGS: $Y2_MODE_FLAGS"
+ log "\tMODULE_ARGS: $Y2_MODULE_ARGS"
+ log "\tMODE: $Y2_MODE"
+ log "\tUI_ARGS: $Y2_UI_ARGS"
+ log "\tQT_IM_MODULE:$QT_IM_MODULE"
+ $OPT_FBITERM y2base \
+ "$Y2_MODULE_NAME" \
+ $Y2_MODE_FLAGS \
+ $Y2_MODULE_ARGS \
+ $Y2_MODE \
+ $Y2_UI_ARGS
+ Y2_EXIT_CODE=$?
+ Y2_ABORT_MESSAGE="YaST seems to be aborted abnormally !"
+ Y2_OK_MESSAGE="YaST procedure ended successfully"
+ if [ -s /etc/yast.inf ];then
+ #=============================================
+ # check yast.inf contents
+ #---------------------------------------------
+ cat /etc/yast.inf | grep -q -i "Aborted: 1"
+ if [ $? = 0 ];then
+ log "\t$Y2_ABORT_MESSAGE"
+ fi
+ else
+ #=============================================
+ # YaST ended successfully
+ #---------------------------------------------
+ log "\t$Y2_OK_MESSAGE"
+ fi
+ if [ $SELECTED_MEDIUM = "SSH" ] && [ ! "$VNC" = 1 ];then
+ echo "*** Preparing SSH installation for reboot ***"
+ echo "*** NOTE: after reboot, you have to reconnect and call ***"
+ echo "*** /usr/lib/YaST2/startup/YaST2.ssh ***"
+ log "\tPreparing SSH installation for reboot"
+ echo $Y2_EXIT_CODE > /tmp/YaST2_ssh_installation_finished
+ fi
+ if [ $Y2_EXIT_CODE -eq 0 ];then
+ start_yast_and_reboot
+ start_yast_again
+ fi
+ log "\tReset memory allocation: overcommit_memory=$overcommit"
+ echo $overcommit > /proc/sys/vm/overcommit_memory
+}
+
+#----[ start_yast_and_reboot ]----#
+function start_yast_and_reboot () {
+#------------------------------------------------------
+# This function will reboot the system and start yast
+# again by touching the file /var/lib/YaST2/runme_at_boot.
+# The function is triggered by the file /var/lib/YaST2/reboot
+# ---
+ if [ -f /var/lib/YaST2/reboot ];then
+ rm -f /var/lib/YaST2/reboot
+ touch /var/lib/YaST2/runme_at_boot
+ /sbin/shutdown -r now
+ fi
+}
+
+#----[ start_yast_again ]----#
+function start_yast_again () {
+#------------------------------------------------------
+# This function will restart yast again with the same
+# options as used before. The function is triggered by
+# the file /var/lib/YaST2/restart_yast
+# ---
+ if [ -f /var/lib/YaST2/restart_yast ];then
+ rm -f /var/lib/YaST2/restart_yast
+ start_yast
+ fi
+}
+
+#=============================================
+# Start the Magic :-)
+#=============================================
+# 1) Source common script functions
+#---------------------------------------------
+. /usr/lib/YaST2/startup/common/functions.sh
+. /usr/lib/YaST2/startup/requires
+. /usr/lib/YaST2/startup/arch/ia64/x11.sh
+
+#=============================================
+# 1.1) set splash progress bar to 90%
+#---------------------------------------------
+set_splash 90
+#=============================================
+# 1.2) set root HOME directory
+#---------------------------------------------
+export HOME=/root
+#=============================================
+# 1.3) set HTTP/FTP proxy and configure syslog
+#---------------------------------------------
+set_syslog ; set_proxy
+
+#=============================================
+# 2) Initialize...
+#---------------------------------------------
+# 2.1) setup PATH
+PATH=$ybindir:$PATH
+[ -z Xstartpath ] || PATH=/var/X11R6/bin:$PATH
+#=============================================
+# 2.2) get X11 driver directory
+#---------------------------------------------
+X11_DRIVER_DIR=$Xdriverpath
+if [ -d $Xdriver64path ];then
+ X11_DRIVER_DIR=$Xdriver64path
+fi
+#=============================================
+# 2.3) obtain RAM size in Kb
+#---------------------------------------------
+MEM_TOTAL=`awk '/^MemTotal:/{ print $2 }' /proc/meminfo`
+if [ ${#MEM_TOTAL} -gt 9 ];then
+ MEM_TOTAL=1000000000
+fi
+#=============================================
+# 2.4) check for valid framebuffer
+#---------------------------------------------
+FBDEV_OK=0
+if (: < /dev/fb0) 2>/dev/null ; then
+ FBDEV_OK=1
+fi
+#=============================================
+# 2.5) setup installation mode (update y/n)
+#---------------------------------------------
+INST_MODE="normal"
+if [ -f /var/lib/YaST2/update_mode ];then
+ INST_MODE="update"
+fi
+#=============================================
+# 2.6) import install.inf
+#---------------------------------------------
+import_install_inf
+
+#=============================================
+# 2.7) set LOG prefix
+#---------------------------------------------
+LOG_PREFIX="Stage [call]"
+
+#=============================================
+# 3) Medium prequalification
+#---------------------------------------------
+# Check which installation mediums can be used. There are
+# four mediums available: Qt(0) SSH(1), VNC(2) and NCURSES(3).
+# The following checks will create an array which contains
+# the possible mediums. An index of 1 indicates "can be used"
+# an index of 0 indicated "cannot be used"
+# ---
+MEDIUM=(1 1 1 1)
+
+#=============================================
+# 3.1) prequalification checks for Qt
+#---------------------------------------------
+log "Starting prequalification checks..."
+log "==================================="
+# 3.1.1) Qt plugin check...
+if ! check_gtk ; then
+ log "\tQt plugin check failed -> Medium Qt disabled"
+ MEDIUM[0]=0
+fi
+# 3.1.2) X-Server module check...
+# BEG IA64: use accelerated X11 driver
+ia64_check_x11
+# END IA64:
+XServerAccel=$XServer
+if [ "$XServer" = "vmware" ];then
+ if [ ! -f "$X11_DRIVER_DIR/${XServer}_drv.so" ];then
+ log "\t$XServer driver not installed -> Medium Qt disabled"
+ MEDIUM[0]=0
+ fi
+ X11_CONFIG_ID=vmware
+else
+ XServer=fbdev
+ if [ $FBDEV_OK -eq 0 ];then
+ log "\tNo Framebuffer available: Using vesa driver"
+ XServer=vesa
+ fi
+ if [ ! -f "$X11_DRIVER_DIR/${XServer}_drv.so" ];then
+ log "\t$XServer driver not installed -> Medium Qt disabled"
+ MEDIUM[0]=0
+ fi
+ X11_CONFIG_ID=$XServer
+fi
+if [ "$acceleratedx" = "1" ];then
+ if [ ! -f "$X11_DRIVER_DIR/${XServerAccel}_drv.so" ];then
+ log "\t$XServerAccel driver not installed -> X11 acceleration disabled"
+ else
+ log "\tUsing accelerated driver -> $XServerAccel"
+ MEDIUM[0]=1
+ XServer=$XServerAccel
+ X11_CONFIG_ID=0
+ fi
+fi
+# 3.1.3) Memory check >= 90MB for Qt/X11...
+if [ $MEM_TOTAL -lt "$MEM_NEEDED" ];then
+ log "\tMemory requirement > 90MB not fulfilled -> Medium Qt disabled"
+ MEDIUM[0]=0
+fi
+# 3.1.4) Check if we need to start our own X11 server...
+if [ -z "$DISPLAY" ];then
+ NEED_XSERVER=1
+fi
+# 3.1.5) Check for xorg.conf...
+if [ ! -f /etc/X11/xorg.conf ];then
+if [ ! -f $Xorgconftempl ];then
+ log "\tNo X11 configuration template found -> Medium Qt disabled"
+ MEDIUM[0]=0
+else
+ cp $Xorgconftempl /etc/X11/xorg.conf
+fi
+fi
+# 3.1.6) Check for WindowManager configuration
+if [ ! -f $Xsharedir/fvwm/fvwmrc.yast2 ];then
+ log "\tNo Windowmanager configuration found -> Medium Qt disabled"
+ MEDIUM[0]=0
+fi
+# 3.1.7) Check for remote display usage
+if [ ! -z $Display_IP ];then
+ log "\tRemote Display usage -> Medium Qt enabled"
+ log "\tExporting DISPLAY to host: $Display_IP:0.0"
+ export DISPLAY="$Display_IP:0.0"
+ NEED_XSERVER=""
+ MEDIUM[0]=1
+fi
+
+#=============================================
+# 3.2) prequalification checks for SSH
+#---------------------------------------------
+# 3.2.1) Check for SSH daemon
+if [ -f /var/run/sshd.*pid ];then
+ ps `cat /var/run/sshd.*pid` >/dev/null || MEDIUM[2]=0
+else
+ log "\tNo SSH daemon running -> Medium SSH disabled"
+ MEDIUM[1]=0
+fi
+
+#=============================================
+# 3.3) prequalification checks for VNC
+#---------------------------------------------
+# 3.3.1) Check for WindowManager configuration
+if [ ! -f $Xsharedir/fvwm/fvwmrc.yast2 ];then
+ log "\tNo Windowmanager configuration found -> Medium VNC disabled"
+ MEDIUM[2]=0
+fi
+# 3.3.2) Check for VNC X-Server binary
+if [ ! -x $Xbindir/Xvnc ] ; then
+ log "\tNo Xvnc server installed -> Medium VNC disabled"
+ MEDIUM[2]=0
+fi
+# 3.3.3) Check for testX binary
+if [ ! -x /usr/sbin/testX ] ; then
+ log "\tNo testX binary installed -> Medium VNC disabled"
+ MEDIUM[2]=0
+fi
+
+#=============================================
+# 4) Evaluate medium selection
+#---------------------------------------------
+# At this point we are evaluating the variables which have
+# been imported from the install.inf file into the current
+# environment. The standard method of installing the system
+# should be Qt based. Refering to the variables Textmode,
+# Braille, UseSSH and VNC another medium could be selected
+# VNC overrides UseSSH
+# ---
+log "Evaluate medium selection..."
+log "============================"
+SELECTED_MEDIUM="QT"
+if [ "$Textmode" = 1 ];then
+ log "\tMedium Textmode (ncurses) has been selected"
+ SELECTED_MEDIUM="NCURSES"
+fi
+if [ ! -z "$Braille" ];then
+ log "\tMedium Braille (ncurses) has been selected"
+ SELECTED_MEDIUM="NCURSES"
+fi
+if [ "$UseSSH" = 1 ];then
+ log "\tMedium SSH has been selected"
+ SELECTED_MEDIUM="SSH"
+fi
+if [ "$VNC" = 1 ];then
+ log "\tMedium VNC has been selected"
+ SELECTED_MEDIUM="VNC"
+fi
+
+#=============================================
+# 5) Check selected medium
+#---------------------------------------------
+# Refering to the prequalification check results we need to
+# check if the selected medium is valid according to the
+# MEDIUM flag entry. If the medium is not valid we will
+# fallback to NCURSES mode
+# ---
+log "Check selected medium..."
+log "========================"
+log "\tWished medium is: $SELECTED_MEDIUM"
+case $SELECTED_MEDIUM in
+ QT) {
+ if [ ${MEDIUM[0]} -eq 0 ];then
+ log "\tMedium Qt not available, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ fi
+ } ;;
+ SSH) {
+ if [ ${MEDIUM[1]} -eq 0 ];then
+ log "\tMedium SSH not available, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ fi
+ } ;;
+ VNC) {
+ if [ ${MEDIUM[2]} -eq 0 ];then
+ log "\tMedium VNC not available, falling back to ncurses"
+ SELECTED_MEDIUM="NCURSES"
+ fi
+ } ;;
+esac
+log "\tSelected medium is: $SELECTED_MEDIUM"
+
+#=============================================
+# 6) Prepare selected medium
+#---------------------------------------------
+case $SELECTED_MEDIUM in
+ QT) prepare_for_qt ; Y2_MODE=gtk ;;
+ SSH) prepare_for_ssh ; Y2_MODE=ncurses ;;
+ VNC) prepare_for_vnc ; Y2_MODE=gtk ;;
+ NCURSES) prepare_for_ncurses ; Y2_MODE=ncurses ;;
+esac
+
+#=============================================
+# 7) Check prepared medium
+#---------------------------------------------
+case $SELECTED_MEDIUM in
+ QT) check_Qt ;;
+ SSH) check_network ;;
+ VNC) check_vnc ;;
+esac
+
+# The prepare_for_ncurses in step 6 is kinda useless if step 7 can
+# change Y2MODE to ncurses in several ways
+# Anyway, #150799
+if [ "$Y2_MODE" = "ncurses" ]; then
+ Y2_UI_ARGS=--nothreads
+fi
+
+#=============================================
+# 8) Call YaST2
+#---------------------------------------------
+Y2_MODULE_NAME=${1:-installation}; shift
+Y2_MODULE_ARGS=\(\"$*\"\)
+start_yast
+
+#=============================================
+# 9) Clean sweep
+#---------------------------------------------
+# 9.1) clear Qt environment...
+clr_inst_qt_env
+
+# 9.2) kill X-Server...
+if [ "$server_running" = 1 ];then
+ sleep 1 && kill $xserver_pid
+ while kill -0 $xserver_pid 2>/dev/null ; do
+ sleep 1
+ done
+fi
+
+#=============================================
+# 10) exit with YaST2 exit code
+#---------------------------------------------
+exit $Y2_EXIT_CODE
+
+
Added: trunk/gtk/unstable/integrate/yast2
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/integrate/yast2?rev…
==============================================================================
--- trunk/gtk/unstable/integrate/yast2 (added)
+++ trunk/gtk/unstable/integrate/yast2 Thu Nov 29 18:22:01 2007
@@ -0,0 +1,280 @@
+#!/bin/bash
+
+# File: /sbin/yast2
+# Module: yast2
+# Summary: YaST2 launch script
+#
+# This script is responsable to start the YaST setup tools. If no arguments
+# are given, a control center should be launched that will call this same script
+# with the wanted setup tool as an argument. In which case, we shall detect the
+# best YaST frontend to provide (eg. gtk for gnome, qt for kde, ncurses for console).
+#
+
+export PATH=/sbin:/usr/sbin:$PATH
+
+# load common script functions
+# (like the detection of frontend plugins)
+. /usr/lib/YaST2/bin/yast2-funcs
+
+# allow user to over-rule the default frontend via a global file
+FRONTEND="auto"
+if test -f /etc/sysconfig/yast2; then
+ . /etc/sysconfig/yast2
+fi
+
+# Arguments to be passed for frontend and the control center (like the --fullscreen)
+YAST_ARGS=""
+
+printhelp()
+{
+ echo "Usage: $0 [OPTIONS] [MODULE] [module specific parameters]"
+ echo
+ echo "OPTIONS:"
+ echo " -l, --list list all available modules"
+ echo " -g, --geometry default window size (graphical frontend only)"
+ echo " --noborder no window manager border for main window (graphical frontend only)"
+ echo " --fullscreen use full screen (graphical frontend only)"
+ echo " -s, --style widget style (qt only)"
+ echo " -h, --help this message"
+ echo
+ echo "exceptional case for installing packages:"
+ echo "$0 OPTION <package> [<package> [...]]"
+ echo
+ echo "OPTION:"
+ echo " -i, --install install rpm package"
+ echo
+ echo "<package> can be a single short package name (e.g. gvim)"
+ echo "which will be installed with dependency checking, or the full"
+ echo "path to an rpm package (e.g /tmp/gvim.rpm) which will be"
+ echo "installed without dependency checking"
+ echo
+}
+
+listmodules()
+{
+ list=`/bin/ls -1 /usr/share/applications/YaST2/*.desktop 2>/dev/null`
+
+ if [ -z "$list" ] ; then
+ echo "No modules installed"
+ else
+ echo "Available modules:"
+ echo
+ grep -h "Exec=/sbin/yast2 " $list | \
+ sed 's|Exec=/sbin/yast2 \([^ ]\+\)\( .*\)\?|\1|' | \
+ sort -u
+ fi
+}
+
+YCP_MENU="$ybindir/y2base menu"
+QT_MENU="$ybindir/y2controlcenter"
+GTK_MENU="/opt/gnome/bin/control-center"
+run_yast_menu()
+{
+ if [ $FRONTEND == "ncurses" ]; then
+ while true ; do
+ $YCP_MENU ncurses $YAST_ARGS
+ if [ ! -e "/var/lib/YaST2/restart_menu" ] ; then
+ break
+ fi
+ done
+ else # gtk or qt
+ if echo $WINDOWMANAGER | grep -qi "gnome" &&
+ [ -e $GTK_MENU ]; then
+ $GTK_MENU $YAST_ARGS
+ elif [ -e $QT_CONTROL_CENTER ]; then
+ $QT_MENU $YAST_ARGS
+ else
+ # run the same YCP menu of ncurses
+ $YCP_MENU $FRONTEND $YAST_ARGS
+ fi
+ fi
+}
+
+## PARSE arguments
+TEMP=`/usr/bin/getopt -o hlg:s:Si --long help,list,kcontrol,geometry:,style:,strings,install,fullscreen,noborder \
+ -n 'yast2' -- "$@"`
+
+if [ $? != 0 ] ; then
+ echo "Exit." >&2
+ exit 1
+fi
+
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+while true ; do
+ case "$1" in
+ -h|--help) printhelp; exit 0 ;;
+ -l|--list) listmodules; exit 0 ;;
+ -g|--geometry) YAST_ARGS="$YAST_ARGS -geometry $2"; shift 2; ;;
+ -i|--install) Y2_INSTALL_PACKAGES=true; shift ;;
+ --fullscreen) YAST_ARGS="$YAST_ARGS --fullscreen"; shift ;;
+ --noborder) YAST_ARGS="$YAST_ARGS --noborder" ; shift ;;
+ --kcontrol) YAST_ARGS="$YAST_ARGS --kcontrol_id YaST" ; shift ;;
+ --) shift ; break ;;
+ *) echo "Unrecognized option $1" ; exit 1 ;;
+
+ # IMPORTANT: Remember to change that "getopt" call above, too
+ # if you change anything here!
+ esac
+done
+
+if [ "$Y2_INSTALL_PACKAGES" = "true" ]; then
+ export module=sw_single
+else
+ # allow module as argument, defaults to "menu"
+ export module="${1-menu}"
+ shift
+fi
+
+case "`/usr/bin/basename $0`" in
+ YaST|yast|yast1|zast)
+ unset DISPLAY
+ ;;
+esac
+
+if [ "$UID" = 0 ]; then
+ echo $$ > /var/run/yast.pid
+fi
+set_lang_from_sysconfig
+
+## CHECK what frontend we should use
+if [ $FRONTEND != "ncurses" ] && [ $FRONTEND != "qt" ] && [ $FRONTEND != "gtk" ] && \
+ [ $FRONTEND != "auto" ]; then
+ echo "Warning: specified frontend $FRONTEND is unknown."
+ FRONTEND="auto"
+fi
+
+if [ $FRONTEND == "auto" ]; then
+ if [ -z "$DISPLAY" ]; then
+ # using the terminal
+ FRONTEND="ncurses"
+ else
+ # running on X11
+ # TODO: maybe GTK could be the default one? ;-)
+ if echo $WINDOWMANAGER | grep -qi "gnome" || \
+ echo $WINDOWMANAGER | grep -qi "xfce" ; then
+ FRONTEND="gtk"
+ else
+ FRONTEND="qt"
+ fi
+ fi
+fi
+
+# fallbacks should go here so that an user preferred frontend also fallback
+if [ $FRONTEND == "gtk" ] && ! check_gtk && check_qt ; then
+ FRONTEND="qt"
+fi
+if [ $FRONTEND == "qt" ] && ! check_qt && check_gtk ; then
+ FRONTEND="gtk"
+fi
+if [ $FRONTEND != "ncurses" ] && ! check_qt && ! check_gtk ; then
+ FRONTEND="ncurses"
+fi
+if [ $FRONTEND == "ncurses" ] && ! check_ncurses; then
+ echo "Error: please install yast2-ncurses to use the YaST2 text mode interface"
+ exit 1
+fi
+
+## SET frontend specific environment settings and whatever they need
+if [ $FRONTEND == "ncurses" ]; then
+ TTY=`/usr/bin/tty`
+ # on console, start yast in UTF-8 locale (only on a 'local' console)
+ if [ "$TERM" = "linux" -a \( "$TTY" = /dev/console -o "$TTY" != "${TTY#/dev/tty[0-9]}" \) ] ; then
+ case "$LANG" in
+ # if it is known that a language doesn't yet work well with ncurses
+ # on console use English instead:
+ ja*|ko*|zh*)
+ export LANG=en_US.UTF-8
+ export LC_CTYPE=en_US.UTF-8
+ ;;
+ *)
+ # get rid of encoding and/or modifier
+ export LANG=${LANG%%[.(a)]*}.UTF-8
+ export LC_CTYPE=${LANG%%[.(a)]*}.UTF-8
+ ;;
+ esac
+ if /bin/testutf8 ; [ $? -ne 2 ] ; then
+ /usr/bin/test -x /bin/unicode_start && /bin/unicode_start
+ uc_started=1
+ fi
+ else
+ case "$TERM" in
+ vt*|xterm*|linux|screen*)
+ # probe terminal and fix lang settings
+ UTF8TESTED=0
+ # binary /bin/testutf8 is missing at least on s390x, #158001
+ /usr/bin/test -x /bin/testutf8 && UTF8TESTED=1 && /bin/testutf8
+ # return code of the /bin/testutf8
+ # 0=utf-unknown, 1=utf-ok, 2=utf-err
+ UTF8STATUS=$?
+
+ # not tested or not working UTF-8 support
+ if [ "$UTF8TESTED" == "1" ] && [ $UTF8STATUS -ne 2 ] ; then
+ /usr/bin/test -n "$LANG" && LANG=${LANG%.UTF-8}
+ /usr/bin/test -n "$LC_CTYPE" && LC_CTYPE=${LC_CTYPE%.UTF-8}
+ else
+ /usr/bin/test -n "$LANG" && LANG=${LANG%%[.(a)]*}.UTF-8
+ /usr/bin/test -n "$LC_CTYPE" && LC_CTYPE=${LC_CTYPE%%[.(a)]*}.UTF-8
+ fi
+ ;;
+ esac
+ fi
+
+ # this fixes launching of interactive subprocesses, #150799
+ YAST_ARGS="$YAST_ARGS --nothreads"
+fi
+
+if [ $FRONTEND == "qt" ]; then
+ set_qt_home_dir
+
+ # FIXME: why the hack was this done? full screening something that
+ # takes so much time to load is just annoying!
+ if echo $WINDOWMANAGER | grep -qi "kde" ; then
+ if [ $module == "sw_single" ] ; then
+ case "$YAST_ARGS" in
+ *fullscreen*) ;;
+ *) YAST_ARGS="$YAST_ARGS --fullscreen" ;;
+ esac
+ fi
+ fi
+fi
+
+## RUN the requested module
+if [ $module == "menu" ]; then
+ run_yast_menu
+else
+ # we do a cycle because we want to keep the online_update module alive as long
+ # as there are pending patches
+ while true ; do
+ # Transform every argument into a ycp string, that is surround all
+ # args by ("..."). args may contain spaces.
+ a=("$@")
+ b=("${a[@]/#/(\"}")
+ c=("${b[@]/%/\")}")
+ set -- "${c[@]}"
+
+ $ybindir/y2base $module "$@" $FRONTEND "$YAST_ARGS"
+
+ if [ ! $module == "online_update" ] || [ ! -e "/var/lib/YaST2/selected_patches.ycp" ] ; then
+ break
+ fi
+ done
+fi
+
+## LAST frontend specific changes
+if [ $FRONTEND == "ncurses" ]; then
+ if [ "$uc_started" ] ; then
+ /usr/bin/test -x /bin/unicode_stop && /bin/unicode_stop
+ fi
+fi
+
+## EXIT
+exit_code=$?
+
+if [ "$UID" = 0 ]; then
+ rm -f /var/run/yast.pid
+fi
+
+exit $exit_code
+
Added: trunk/gtk/unstable/integrate/yast2-funcs
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/integrate/yast2-fun…
==============================================================================
--- trunk/gtk/unstable/integrate/yast2-funcs (added)
+++ trunk/gtk/unstable/integrate/yast2-funcs Thu Nov 29 18:22:01 2007
@@ -0,0 +1,141 @@
+# File: /usr/share/YaST2/bin/yast2-funcs
+# Module: yast2
+# Summary: Common functions for YaST2 start scripts
+# Authors: Arvin Schnell <arvin(a)suse.de>
+#
+# $Id: yast2-funcs 24861 2005-08-12 11:10:25Z locilka $
+
+# some path definitions
+ybindir=/usr/lib/YaST2/bin
+logdir=/var/log/YaST2
+
+
+# font for qt
+# obsolete, we should not need it anymore, adrian
+# Y2_XFONT="-gnu-unifont-medium-r-normal--16-160-75-75-p-80-iso10646-1"
+
+
+#
+# check if plugins are in lib or lib64 subdir and sets the variable
+# plugindir accordingly
+#
+function get_plugindir()
+{
+ plugindir=/usr/lib/YaST2/plugin
+ if `ldd $ybindir/y2base | egrep --quiet "/lib64/(.*/)?libc.so"` ; then
+ plugindir=/usr/lib64/YaST2/plugin
+ fi
+}
+
+#
+# check if the gtk plugin and all necessary libaries are present
+#
+function check_gtk()
+{
+ get_plugindir
+ Y2_GTK=$plugindir/libpy2gtk.so.2
+
+ if [ -e "$Y2_GTK" ] ; then
+ if ! `/usr/bin/ldd "$Y2_GTK" | grep --quiet "=> not found"` ; then
+ return 0 # success
+ fi
+ echo "warning: the gtk frontend is installed but does not work"
+ sleep 1
+ fi
+
+ return 1 # failure
+}
+
+#
+# check if the qt plugin and all necessary libaries are present
+#
+function check_qt()
+{
+ get_plugindir
+ Y2_QT=$plugindir/libpy2qt.so.2
+
+ if [ -e "$Y2_QT" ] ; then
+ if ! `/usr/bin/ldd "$Y2_QT" | grep --quiet "=> not found"` ; then
+ return 0 # success
+ fi
+ echo "warning: the qt frontend is installed but does not work"
+ sleep 1
+ fi
+
+ return 1 # failure
+}
+
+
+#
+# check if the ncurses plugin and all necessary libaries are present
+#
+function check_ncurses()
+{
+ get_plugindir
+ Y2_NCURSES=$plugindir/libpy2ncurses.so.2
+
+ if [ -e "$Y2_NCURSES" ] ; then
+ if ! `/usr/bin/ldd "$Y2_NCURSES" | grep --quiet "=> not found"` ; then
+ return 0 # success
+ fi
+ echo "warning: the ncurses frontend is installed but does not work"
+ sleep 1
+ fi
+
+ return 1 # failure
+}
+
+
+#
+# if LANG is empty set LANG to RC_LANG in /etc/sysconfig/language
+#
+function set_lang_from_sysconfig()
+{
+ # if LANG is "POSIX", unset LANG
+ # SL 9.3 had default LANG set to ""
+ # SL 10.0 has default LANG set to "POSIX"
+ if [ "$LANG" == "POSIX" ] ; then
+ LANG=""
+ fi
+
+ # if LANG is not empty and /etc/sysconfig/language exists
+ if [ -z "$LANG" -a -r /etc/sysconfig/language ] ; then
+ . /etc/sysconfig/language
+ if [ -n "$RC_LANG" ] ; then
+ export LANG=$RC_LANG
+ fi
+ fi
+}
+
+
+function set_qt_home_dir()
+{
+ local user="$USER"
+ if [ "$KDESU_USER" ]; then
+ user="$KDESU_USER"
+ fi
+ temp_QT_HOME_DIR="`eval echo ~$user/.qt/`"
+ if test -r "$temp_QT_HOME_DIR/qtrc"; then
+ export QT_HOME_DIR="$temp_QT_HOME_DIR"
+ fi
+}
+
+
+function set_inst_qt_env()
+{
+ export XCURSOR_THEME="crystalwhite"
+ export QT_HOME_DIR="`eval echo /tmp/.qt/`"
+ mkdir -p /tmp/.qt
+ [ -e /usr/share/desktop-data/qtrc ] && cp /usr/share/desktop-data/qtrc /tmp/.qt/
+}
+
+
+function clr_inst_qt_env()
+{
+ rm -rf /tmp/.qt/
+}
+
+
+### Local Variables: ***
+### mode: shell-script ***
+### End: ***
Added: trunk/gtk/unstable/mockups/package-selector/christian-package-selector-1.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/package-selector/christian-package-selector-2.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/package-selector/christian-patterns.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/package-selector/martin-package-selector-1.gif
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/package-selector/packagekit-groups.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/package-selector/packagekit-search.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/package-selector/ricado-split-use-cases.svg
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
--- trunk/gtk/unstable/mockups/package-selector/ricado-split-use-cases.svg (added)
+++ trunk/gtk/unstable/mockups/package-selector/ricado-split-use-cases.svg Thu Nov 29 18:22:01 2007
@@ -0,0 +1,634 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ width="720"
+ height="410"
+ sodipodi:docbase="/home/rick2/Documents/yast/gtk/mockups/package-selector"
+ sodipodi:docname="ricado-split-use-cases.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0">
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5" />
+ <sodipodi:namedview
+ inkscape:window-height="777"
+ inkscape:window-width="939"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="1"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:zoom="1"
+ inkscape:cx="372.04724"
+ inkscape:cy="228.70418"
+ inkscape:window-x="334"
+ inkscape:window-y="42"
+ inkscape:current-layer="svg2"
+ showgrid="false"
+ width="720px"
+ height="410px" />
+ <rect
+ style="fill:#fff966;fill-opacity:1;stroke:none;stroke-width:1.59800005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8339"
+ width="718"
+ height="409"
+ x="2"
+ y="1" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="267"
+ y="41.362183"
+ id="text7070"><tspan
+ sodipodi:role="line"
+ id="tspan7072"
+ x="267"
+ y="41.362183">Action:</tspan></text>
+ <path
+ sodipodi:type="arc"
+ id="path7074"
+ sodipodi:cx="167"
+ sodipodi:cy="74.862183"
+ sodipodi:rx="19"
+ sodipodi:ry="16.5"
+ d="M 186 74.862183 A 19 16.5 0 1 1 148,74.862183 A 19 16.5 0 1 1 186 74.862183 z"
+ transform="matrix(0.6614424,0,0,0.7616609,239.03913,-22.157412)"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2.76719594;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1" />
+ <path
+ sodipodi:type="arc"
+ style="fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path8045"
+ sodipodi:cx="128"
+ sodipodi:cy="161.36218"
+ sodipodi:rx="10"
+ sodipodi:ry="9"
+ d="M 138 161.36218 A 10 9 0 1 1 118,161.36218 A 10 9 0 1 1 138 161.36218 z"
+ transform="matrix(0.85,0,0,1,240.7,-127)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="369"
+ y="41.362183"
+ id="text8047"><tspan
+ sodipodi:role="line"
+ id="tspan8049"
+ x="369"
+ y="41.362183">Install</tspan></text>
+ <path
+ sodipodi:type="arc"
+ id="path8053"
+ sodipodi:cx="167"
+ sodipodi:cy="74.862183"
+ sodipodi:rx="19"
+ sodipodi:ry="16.5"
+ d="M 186 74.862183 A 19 16.5 0 1 1 148,74.862183 A 19 16.5 0 1 1 186 74.862183 z"
+ transform="matrix(0.6614424,0,0,0.7616609,339.53912,-20.657415)"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2.76719594;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="471"
+ y="41.362183"
+ id="text8059"><tspan
+ sodipodi:role="line"
+ id="tspan8061"
+ x="471"
+ y="41.362183">Remove</tspan></text>
+ <path
+ sodipodi:type="arc"
+ id="path8063"
+ sodipodi:cx="167"
+ sodipodi:cy="74.862183"
+ sodipodi:rx="19"
+ sodipodi:ry="16.5"
+ d="M 186 74.862183 A 19 16.5 0 1 1 148,74.862183 A 19 16.5 0 1 1 186 74.862183 z"
+ transform="matrix(0.6614424,0,0,0.7616609,464.53912,-20.657415)"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2.76719594;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="595"
+ y="42.362183"
+ id="text8065"><tspan
+ sodipodi:role="line"
+ id="tspan8067"
+ x="595"
+ y="42.362183">Upgrade</tspan></text>
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.56370759;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8069"
+ width="132.43629"
+ height="269.43628"
+ x="263.78186"
+ y="77.144043" />
+ <g
+ id="g8078"
+ transform="matrix(0.7085094,0,0,0.8192639,-8.44843,-87.77487)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8071"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8075">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8073"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <path
+ sodipodi:type="star"
+ style="fill:#cfcfff;fill-opacity:1;stroke:#000000;stroke-width:0.6525771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="path8087"
+ sodipodi:sides="4"
+ sodipodi:cx="207"
+ sodipodi:cy="178.36218"
+ sodipodi:r1="30.413813"
+ sodipodi:r2="21.505814"
+ sodipodi:arg1="0.76214654"
+ sodipodi:arg2="1.5475447"
+ inkscape:flatsided="true"
+ inkscape:rounded="0.07"
+ inkscape:randomized="0"
+ d="M 229,199.36218 C 226.92111,201.54007 188.17789,202.44108 186,200.36218 C 183.82211,198.28329 182.92111,159.54007 185,157.36218 C 187.07889,155.18429 225.82211,154.28329 228,156.36218 C 230.17789,158.44108 231.07889,197.18429 229,199.36218 z "
+ transform="matrix(2.6971042,0,0,0.9494303,-87.80056,-41.980263)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="422"
+ y="133.36218"
+ id="text8089"><tspan
+ sodipodi:role="line"
+ id="tspan8091"
+ x="422"
+ y="133.36218">Install</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="314"
+ y="103.36218"
+ id="text8093"><tspan
+ sodipodi:role="line"
+ id="tspan8095"
+ x="314"
+ y="103.36218">Emacs</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="323"
+ y="152.36218"
+ id="text8097"><tspan
+ sodipodi:role="line"
+ id="tspan8099"
+ x="323"
+ y="152.36218">Yast</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="322"
+ y="192.36218"
+ id="text8101"><tspan
+ sodipodi:role="line"
+ id="tspan8103"
+ x="322"
+ y="192.36218">Gnome</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="333"
+ y="229.36218"
+ id="text8105"><tspan
+ sodipodi:role="line"
+ id="tspan8107"
+ x="333"
+ y="229.36218">. . .</tspan></text>
+ <g
+ id="g8109"
+ transform="matrix(0.7085094,0,0,0.8192639,-7.44842,-45.774865)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8111"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8113">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8115"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <g
+ id="g8117"
+ transform="matrix(0.7085094,0,0,0.8192639,-6.44842,-4.774865)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8119"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8121">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8123"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <g
+ id="g8125"
+ transform="matrix(0.7085094,0,0,0.8192639,-6.44842,33.225135)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8127"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8129">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8131"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <g
+ id="g8133"
+ transform="matrix(0.7085094,0,0,0.8192639,-5.44842,70.225135)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8135"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8137">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8139"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <g
+ id="g8141"
+ transform="matrix(0.7085094,0,0,0.8192639,-4.44842,110.22514)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8143"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8145">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8147"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <path
+ sodipodi:type="star"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.59800005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="path8149"
+ sodipodi:sides="3"
+ sodipodi:cx="257"
+ sodipodi:cy="206.36218"
+ sodipodi:r1="38.897301"
+ sodipodi:r2="27.504545"
+ sodipodi:arg1="0.80357798"
+ sodipodi:arg2="1.8507755"
+ inkscape:flatsided="true"
+ inkscape:rounded="0.07"
+ inkscape:randomized="0"
+ d="M 284,234.36218 C 280.60518,237.63576 220.38888,220.32166 219.25129,215.74487 C 218.1137,211.16808 263.2163,167.67628 267.74871,168.9795 C 272.28112,170.28271 287.39482,231.08861 284,234.36218 z "
+ transform="matrix(-0.5046744,-9.1938879e-2,0.1000384,-0.2995076,614.5839,212.26209)" />
+ <path
+ sodipodi:type="star"
+ style="fill:#cfcfff;fill-opacity:1;stroke:#000000;stroke-width:0.6525771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="path8151"
+ sodipodi:sides="4"
+ sodipodi:cx="207"
+ sodipodi:cy="178.36218"
+ sodipodi:r1="30.413813"
+ sodipodi:r2="21.505814"
+ sodipodi:arg1="0.76214654"
+ sodipodi:arg2="1.5475447"
+ inkscape:flatsided="true"
+ inkscape:rounded="0.07"
+ inkscape:randomized="0"
+ d="M 229,199.36218 C 226.92111,201.54007 188.17789,202.44108 186,200.36218 C 183.82211,198.28329 182.92111,159.54007 185,157.36218 C 187.07889,155.18429 225.82211,154.28329 228,156.36218 C 230.17789,158.44108 231.07889,197.18429 229,199.36218 z "
+ transform="matrix(-2.6971042,0,0,0.9494303,1029.3006,29.019722)" />
+ <path
+ sodipodi:type="star"
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.59800005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="path8157"
+ sodipodi:sides="3"
+ sodipodi:cx="257"
+ sodipodi:cy="206.36218"
+ sodipodi:r1="38.897301"
+ sodipodi:r2="27.504545"
+ sodipodi:arg1="0.80357798"
+ sodipodi:arg2="1.8507755"
+ inkscape:flatsided="true"
+ inkscape:rounded="0.07"
+ inkscape:randomized="0"
+ d="M 284,234.36218 C 280.60518,237.63576 220.38888,220.32166 219.25129,215.74487 C 218.1137,211.16808 263.2163,167.67628 267.74871,168.9795 C 272.28112,170.28271 287.39482,231.08861 284,234.36218 z "
+ transform="matrix(0.5046744,-9.1938879e-2,-0.1000384,-0.2995076,329.17835,283.26208)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="459"
+ y="203.36218"
+ id="text8159"><tspan
+ sodipodi:role="line"
+ id="tspan8161"
+ x="459"
+ y="203.36218">Undo</tspan></text>
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.56370759;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8163"
+ width="132.43629"
+ height="269.43628"
+ x="552.78186"
+ y="76.644043" />
+ <g
+ id="g8169"
+ transform="matrix(0.7085094,0,0,0.8192639,280.55158,-85.77486)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8171"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8173">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8175"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <g
+ id="g8177"
+ transform="matrix(0.7085094,0,0,0.8192639,280.55158,-45.774865)">
+ <rect
+ y="212.26196"
+ x="393.89227"
+ height="37.200428"
+ width="46.215443"
+ id="rect8179"
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.79179287;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1" />
+ <a
+ id="a8181">
+ <rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.58312905;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8183"
+ width="44.19965"
+ height="13.608962"
+ x="395.26849"
+ y="213.00041" />
+ </a>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="606"
+ y="110.36218"
+ id="text8189"><tspan
+ sodipodi:role="line"
+ id="tspan8191"
+ x="606"
+ y="110.36218">VIM</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12.81681156px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="655.58746"
+ y="135.82359"
+ id="text8193"
+ transform="scale(0.9154865,1.0923154)"><tspan
+ sodipodi:role="line"
+ id="tspan8195"
+ x="655.58746"
+ y="135.82359">Dependency 1</tspan></text>
+ <path
+ sodipodi:type="star"
+ style="fill:#cfcfff;fill-opacity:1;stroke:#000000;stroke-width:0.6525771;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="path8278"
+ sodipodi:sides="4"
+ sodipodi:cx="207"
+ sodipodi:cy="178.36218"
+ sodipodi:r1="30.413813"
+ sodipodi:r2="21.505814"
+ sodipodi:arg1="0.76214654"
+ sodipodi:arg2="1.5475447"
+ inkscape:flatsided="true"
+ inkscape:rounded="0.07"
+ inkscape:randomized="0"
+ d="M 229,199.36218 C 226.92111,201.54007 188.17789,202.44108 186,200.36218 C 183.82211,198.28329 182.92111,159.54007 185,157.36218 C 187.07889,155.18429 225.82211,154.28329 228,156.36218 C 230.17789,158.44108 231.07889,197.18429 229,199.36218 z "
+ transform="matrix(-2.8494521,1.1259094e-2,4.9738035e-3,0.7992946,1200.4495,232.96761)" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.59565759;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 662.75191,371.04823 L 656.66967,388.11409 L 648.24809,368.61027 L 657.13753,388.11409 L 662.75191,371.04823 z "
+ id="path8268" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="553"
+ y="385.36218"
+ id="text8281"><tspan
+ sodipodi:role="line"
+ id="tspan8283"
+ x="553"
+ y="385.36218">Packages</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="487.1709"
+ y="384.49109"
+ id="text8285"><tspan
+ sodipodi:role="line"
+ id="tspan8287"
+ x="487.1709"
+ y="384.49109">Type:</tspan></text>
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.03835428;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8222"
+ width="169.29662"
+ height="289.12125"
+ x="43.576736"
+ y="92.37149" />
+ <path
+ style="fill:#ffffdb;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 30,25.862183 L 138,23.862183 L 238,67.862183 L 240,397.86218 L 21,398.86218 L 20,25.862183 L 30,25.862183 z "
+ id="path8224" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="34"
+ y="52.862183"
+ id="text8230"><tspan
+ sodipodi:role="line"
+ id="tspan8232"
+ x="34"
+ y="52.862183">Filters</tspan></text>
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.29615057;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:20;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8234"
+ width="182.30185"
+ height="24.301849"
+ x="35.849075"
+ y="68.711258" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.76469111px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 41.459552,88.95369 L 50.117654,88.95369 L 44.922793,89.96676 L 44.922793,72.744533 L 48.963241,72.744533 L 40.882346,73.7576 L 45.5,72.744533 L 46.654414,72.744533 L 44.345586,72.744533 L 44.345586,90.97983 L 41.459552,88.95369 z "
+ id="path8240" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.79200006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 41.759684,107.70843 L 62.153755,114.1277 L 38.846245,123.01593 L 62.153755,113.63391 L 41.759684,107.70843 z "
+ id="path8242" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="72"
+ y="120.86218"
+ id="text8244"><tspan
+ sodipodi:role="line"
+ id="tspan8246"
+ x="72"
+ y="120.86218">Categories</tspan></text>
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.79200006;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:6.4;stroke-opacity:1"
+ id="rect8248"
+ width="180"
+ height="158"
+ x="39"
+ y="135.86218" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 52,152.86218 L 51,276.86218 L 92,275.86218 L 51,275.86218 L 52,171.86218 L 86,171.86218 L 85,253.86218 L 125,252.86218 L 84,253.86218 L 86,209.86218 L 123,209.86218 L 85,209.86218 L 86,172.86218 L 52,172.86218 L 52,152.86218 z "
+ id="path8250"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="95"
+ y="179.86218"
+ id="text8252"><tspan
+ sodipodi:role="line"
+ id="tspan8254"
+ x="95"
+ y="179.86218">Office</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:13.26576328px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="155.67979"
+ y="177.31532"
+ id="text8256"
+ transform="scale(0.8291102,1.2061123)"><tspan
+ sodipodi:role="line"
+ id="tspan8258"
+ x="155.67979"
+ y="177.31532">Word Processors</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:14.71323204px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="141.53064"
+ y="238.04373"
+ id="text8260"
+ transform="scale(0.919577,1.0874565)"><tspan
+ sodipodi:role="line"
+ id="tspan8262"
+ x="141.53064"
+ y="238.04373">Spreedsheets</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="99"
+ y="280.86218"
+ id="text8264"><tspan
+ sodipodi:role="line"
+ id="tspan8266"
+ x="99"
+ y="280.86218">Multimedia</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.79200006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 60.74032,314.20843 L 40.34625,320.6277 L 63.65375,329.51593 L 40.34625,320.13391 L 60.74032,314.20843 z "
+ id="path8333" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="79.5625"
+ y="328.03308"
+ id="text8270"><tspan
+ sodipodi:role="line"
+ id="tspan8272"
+ x="79.5625"
+ y="328.03308">Repositories</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="49"
+ y="361.86218"
+ id="text8274"><tspan
+ sodipodi:role="line"
+ id="tspan8276"
+ x="49"
+ y="361.86218">. . .</tspan></text>
+</svg>
Added: trunk/gtk/unstable/mockups/package-selector/ubuntu-add-remove-applications.jpg
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/package-sel…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/wizard-look/installer-mockup.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/wizard-look…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/wizard-look/jakub-installer-mockup.jpg
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/wizard-look…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/mockups/wizard-look/jakub-mockup.svg
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/wizard-look…
==============================================================================
--- trunk/gtk/unstable/mockups/wizard-look/jakub-mockup.svg (added)
+++ trunk/gtk/unstable/mockups/wizard-look/jakub-mockup.svg Thu Nov 29 18:22:01 2007
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="512"
+ height="512"
+ id="svg3164"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ version="1.0"
+ sodipodi:docbase="/home/jimmac/gfx/suse"
+ sodipodi:docname="yast-face-mockup.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/jimmac/gfx/suse/yast-face-mockup.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs3166">
+ <linearGradient
+ id="linearGradient9896">
+ <stop
+ style="stop-color:#cecece;stop-opacity:1;"
+ offset="0"
+ id="stop9898" />
+ <stop
+ style="stop-color:#9e9e9e;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop9900" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9868">
+ <stop
+ id="stop9870"
+ offset="0.0000000"
+ style="stop-color:#4e4e4e;stop-opacity:1.0000000;" />
+ <stop
+ id="stop9872"
+ offset="1.0000000"
+ style="stop-color:#616161;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9854">
+ <stop
+ style="stop-color:#4e4e4e;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop9856" />
+ <stop
+ style="stop-color:#ababab;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop9858" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9830">
+ <stop
+ style="stop-color:#505050;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop9832" />
+ <stop
+ style="stop-color:#181818;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop9834" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3800">
+ <stop
+ id="stop3802"
+ offset="0.0000000"
+ style="stop-color:#f4d9b1;stop-opacity:1.0000000;" />
+ <stop
+ id="stop3804"
+ offset="1.0000000"
+ style="stop-color:#df9725;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4163">
+ <stop
+ id="stop4165"
+ offset="0.0000000"
+ style="stop-color:#3b74bc;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4167"
+ offset="1.0000000"
+ style="stop-color:#2d5990;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3824">
+ <stop
+ id="stop3826"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop3828"
+ offset="1.0000000"
+ style="stop-color:#c9c9c9;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4338">
+ <stop
+ style="stop-color:#e9b15e;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop4340" />
+ <stop
+ style="stop-color:#966416;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop4342" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4344">
+ <stop
+ id="stop4346"
+ offset="0"
+ style="stop-color:#727e0a;stop-opacity:1;" />
+ <stop
+ id="stop4348"
+ offset="1.0000000"
+ style="stop-color:#5b6508;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ x="-0.016093679"
+ width="1.0321873"
+ y="-0.12716499"
+ height="1.25433"
+ id="filter6146">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.68335658"
+ id="feGaussianBlur6148" />
+ </filter>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5749"
+ id="linearGradient5212"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.560438,0,0,1,-180.35099,80.000027)"
+ x1="527.00006"
+ y1="337.49994"
+ x2="527.00006"
+ y2="349.99997" />
+ <linearGradient
+ id="linearGradient5749">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop5751" />
+ <stop
+ style="stop-color:#dcdcd8;stop-opacity:1;"
+ offset="1"
+ id="stop5753" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5749"
+ id="linearGradient5218"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.736263,0,0,1,10.989174,79.000022)"
+ x1="527.00006"
+ y1="337.49994"
+ x2="527.00006"
+ y2="349.99997" />
+ <linearGradient
+ id="linearGradient6107">
+ <stop
+ style="stop-color:#3465a4;stop-opacity:1"
+ offset="0"
+ id="stop6109" />
+ <stop
+ id="stop6115"
+ offset="0.5"
+ style="stop-color:#83a6d9;stop-opacity:1;" />
+ <stop
+ style="stop-color:#3465a4;stop-opacity:1"
+ offset="1"
+ id="stop6111" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6107"
+ id="linearGradient6113"
+ x1="196.5"
+ y1="263"
+ x2="602.5"
+ y2="263"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.9160495,0,0,2.1052305,-103.9617,-168.61518)" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="241.72408"
+ inkscape:cy="244.38808"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="512px"
+ height="512px"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ showgrid="false"
+ inkscape:window-width="1083"
+ inkscape:window-height="908"
+ inkscape:window-x="149"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata3169">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;color:#000000;fill:url(#linearGradient6113);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5220"
+ width="371"
+ height="386.85565"
+ x="76.5"
+ y="56.644333"
+ rx="4.5823212"
+ ry="4.5823212" />
+ <rect
+ style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5138"
+ width="366"
+ height="355"
+ x="79"
+ y="86"
+ rx="0"
+ ry="0" />
+ <rect
+ style="color:#000000;fill:url(#linearGradient5218);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:2.99999976;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5140"
+ width="66.999771"
+ height="24.000029"
+ x="365.5"
+ y="404.49997"
+ rx="2.9687498"
+ ry="2.96875" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
+ x="385.99982"
+ y="421.00003"
+ id="text5142"><tspan
+ sodipodi:role="line"
+ id="tspan5144"
+ x="385.99982"
+ y="421.00003">Next</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 386.96852,422.50002 L 392.90602,422.50002"
+ id="path5170" />
+ <rect
+ ry="2.96875"
+ rx="2.9687474"
+ y="405.49997"
+ x="89.5"
+ height="24.000029"
+ width="50.999733"
+ id="rect5180"
+ style="color:#000000;fill:url(#linearGradient5212);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:0.99999958;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <text
+ id="text5182"
+ y="422.00003"
+ x="101.99992"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="422.00003"
+ x="101.99992"
+ id="tspan5184"
+ sodipodi:role="line">Help</tspan></text>
+ <path
+ id="path5186"
+ d="M 103.49993,423.50002 L 108.49993,423.50002"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text6122"
+ y="56.362183"
+ x="203.67383"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.49714284;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;filter:url(#filter6146);font-family:Segoe"
+ xml:space="preserve"
+ transform="matrix(1.18725,0,0,1.18725,-40.3025,10.144894)"><tspan
+ y="56.362183"
+ x="203.67383"
+ id="tspan6124"
+ sodipodi:role="line">Hardware Setup</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:14.24700165px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Trebuchet MS"
+ x="201.50928"
+ y="75.873657"
+ id="text6118"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan6120"
+ x="201.50928"
+ y="75.873657">Hardware Setup</tspan></text>
+ <g
+ id="g4295"
+ transform="translate(3.330917,-21.00005)">
+ <text
+ id="text4287"
+ y="136.00006"
+ x="88.071426"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="136.00006"
+ x="88.071426"
+ id="tspan4289"
+ sodipodi:role="line">Choose Driver:</tspan></text>
+ <path
+ id="path4291"
+ d="M 89.510984,137.50005 L 95.411632,137.50005"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+ </g>
+ <rect
+ style="fill:#ffffff;stroke:#babdb6;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect4293"
+ width="344"
+ height="265.99997"
+ x="89.5"
+ y="125.50002"
+ rx="2.9687476"
+ ry="2.96875" />
+ </g>
+</svg>
Added: trunk/gtk/unstable/mockups/wizard-look/ricardo-installer-mockup.svg
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/wizard-look…
==============================================================================
--- trunk/gtk/unstable/mockups/wizard-look/ricardo-installer-mockup.svg (added)
+++ trunk/gtk/unstable/mockups/wizard-look/ricardo-installer-mockup.svg Thu Nov 29 18:22:01 2007
@@ -0,0 +1,378 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="512"
+ height="512"
+ id="svg3164"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ version="1.0"
+ sodipodi:docbase="/home/rick2"
+ sodipodi:docname="installer-mockup.svg"
+ inkscape:export-filename="/home/jimmac/gfx/suse/yast-face-mockup.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs3166">
+ <linearGradient
+ id="linearGradient9896">
+ <stop
+ style="stop-color:#cecece;stop-opacity:1;"
+ offset="0"
+ id="stop9898" />
+ <stop
+ style="stop-color:#9e9e9e;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop9900" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9868">
+ <stop
+ id="stop9870"
+ offset="0.0000000"
+ style="stop-color:#4e4e4e;stop-opacity:1.0000000;" />
+ <stop
+ id="stop9872"
+ offset="1.0000000"
+ style="stop-color:#616161;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9854">
+ <stop
+ style="stop-color:#4e4e4e;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop9856" />
+ <stop
+ style="stop-color:#ababab;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop9858" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9830">
+ <stop
+ style="stop-color:#505050;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop9832" />
+ <stop
+ style="stop-color:#181818;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop9834" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3800">
+ <stop
+ id="stop3802"
+ offset="0.0000000"
+ style="stop-color:#f4d9b1;stop-opacity:1.0000000;" />
+ <stop
+ id="stop3804"
+ offset="1.0000000"
+ style="stop-color:#df9725;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4163">
+ <stop
+ id="stop4165"
+ offset="0.0000000"
+ style="stop-color:#3b74bc;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4167"
+ offset="1.0000000"
+ style="stop-color:#2d5990;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3824">
+ <stop
+ id="stop3826"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop3828"
+ offset="1.0000000"
+ style="stop-color:#c9c9c9;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4338">
+ <stop
+ style="stop-color:#e9b15e;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop4340" />
+ <stop
+ style="stop-color:#966416;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop4342" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4344">
+ <stop
+ id="stop4346"
+ offset="0"
+ style="stop-color:#727e0a;stop-opacity:1;" />
+ <stop
+ id="stop4348"
+ offset="1.0000000"
+ style="stop-color:#5b6508;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5749"
+ id="linearGradient5212"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.560438,0,0,1,-81.05688,145.6536)"
+ x1="527.00006"
+ y1="337.49994"
+ x2="527.00006"
+ y2="349.99997" />
+ <linearGradient
+ id="linearGradient5749">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop5751" />
+ <stop
+ style="stop-color:#dcdcd8;stop-opacity:1;"
+ offset="1"
+ id="stop5753" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5749"
+ id="linearGradient5218"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.736263,0,0,1,68.94996,149)"
+ x1="527.00006"
+ y1="337.49994"
+ x2="527.00006"
+ y2="349.99997" />
+ <linearGradient
+ id="linearGradient6107">
+ <stop
+ style="stop-color:#3465a4;stop-opacity:1"
+ offset="0"
+ id="stop6109" />
+ <stop
+ id="stop6115"
+ offset="0.5"
+ style="stop-color:#83a6d9;stop-opacity:1;" />
+ <stop
+ style="stop-color:#3465a4;stop-opacity:1"
+ offset="1"
+ id="stop6111" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.1953125"
+ inkscape:cx="256"
+ inkscape:cy="271.20829"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="512px"
+ height="512px"
+ borderlayer="true"
+ inkscape:showpageshadow="false"
+ showgrid="false"
+ inkscape:window-width="1440"
+ inkscape:window-height="828"
+ inkscape:window-x="0"
+ inkscape:window-y="26" />
+ <metadata
+ id="metadata3169">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="color:black;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect5138"
+ width="513"
+ height="511"
+ x="-1"
+ y="1"
+ rx="0"
+ ry="0" />
+ <rect
+ style="color:black;fill:url(#linearGradient5218);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:2.99999976;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect5140"
+ width="66.999771"
+ height="24.000029"
+ x="423.46078"
+ y="474.49997"
+ rx="2.9687498"
+ ry="2.96875" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
+ x="443.63379"
+ y="490.00003"
+ id="text5142"><tspan
+ sodipodi:role="line"
+ id="tspan5144"
+ x="443.63379"
+ y="490.00003">Next</tspan></text>
+ <rect
+ ry="2.96875"
+ rx="2.9687474"
+ y="471.15356"
+ x="188.79411"
+ height="24.000029"
+ width="50.999733"
+ id="rect5180"
+ style="color:black;fill:url(#linearGradient5212);fill-opacity:1;fill-rule:nonzero;stroke:#888a85;stroke-width:0.99999958;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <text
+ id="text5182"
+ y="485.98041"
+ x="200.80385"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="485.98041"
+ x="200.80385"
+ id="tspan5184"
+ sodipodi:role="line">Help</tspan></text>
+ <rect
+ style="fill:white;stroke:#babdb6;stroke-width:1.14902854;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect4293"
+ width="302.04697"
+ height="325.17773"
+ x="191.37843"
+ y="123.24775"
+ rx="3.1898239"
+ ry="3.6478913" />
+ <path
+ style="fill:#87bd87;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 7.1111107,520.72932 C 7.1111107,520.72932 135.78292,525.54946 135.58744,471.36984 C 135.392,417.1999 135.97832,457.14761 135.97832,457.14761 L 136.85488,126.69001 C 136.85488,126.69001 135.59675,103.14234 145.82517,90.297902 C 157.15075,76.075702 173.17392,75.657432 173.17392,75.657432 C 173.17392,75.657432 365.17061,79.723792 464.44254,78.167232 C 518.57963,77.330632 519.94771,8.7293224 519.94771,8.7293224 L 7.1111107,7.8927224 L 7.1111107,520.72932 z "
+ id="path4669"
+ sodipodi:nodetypes="czccscsccc" />
+ <path
+ style="fill:#87d958;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -0.41829972,512.83464 C -0.41829972,512.83464 128.25351,517.65478 128.05803,463.47516 C 127.86259,409.30522 128.44891,449.25293 128.44891,449.25293 L 129.32547,118.79533 C 129.32547,118.79533 128.06734,95.247664 138.29576,82.403217 C 149.62134,68.181022 165.64451,67.76275 165.64451,67.76275 C 165.64451,67.76275 357.6412,71.829111 456.91313,70.272551 C 511.05022,69.435951 512.4183,0.83464057 512.4183,0.83464057 L -0.41829972,-0.0019620281 L -0.41829972,512.83464 z "
+ id="path3730"
+ sodipodi:nodetypes="czccscsccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:bold;fill:white;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="117.96078"
+ y="40.156864"
+ id="text3732"><tspan
+ sodipodi:role="line"
+ id="tspan3734"
+ x="117.96078"
+ y="40.156864">Hardware Setup</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="34.300655"
+ y="116.28758"
+ id="text3736"><tspan
+ sodipodi:role="line"
+ id="tspan3738"
+ x="34.300655"
+ y="116.28758">Welcome</tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="128.78758"
+ id="tspan3740"></tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="141.28758"
+ id="tspan3744">Choose language</tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="153.78758"
+ id="tspan3742" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="166.28758"
+ id="tspan3746">Format disk</tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="178.78758"
+ id="tspan3748" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="191.28758"
+ id="tspan3750">Install packages</tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="203.78758"
+ id="tspan3752" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="216.28758"
+ id="tspan3754">Add users</tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="228.78758"
+ id="tspan3756" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="241.28758"
+ id="tspan3758" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="253.78758"
+ id="tspan3760" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="266.28758"
+ id="tspan3762">Check updates</tspan><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="278.78758"
+ id="tspan3764" /><tspan
+ sodipodi:role="line"
+ x="34.300655"
+ y="291.28758"
+ id="tspan3766">Done</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10px;font-style:normal;font-weight:bold;fill:white;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="30.117647"
+ y="238.43135"
+ id="text3768"><tspan
+ sodipodi:role="line"
+ id="tspan3770"
+ x="30.117647"
+ y="238.43135">Hardware setup</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="197.43791"
+ y="105.41177"
+ id="text3776"><tspan
+ sodipodi:role="line"
+ id="tspan3778"
+ x="197.43791"
+ y="105.41177">Choose driver:</tspan></text>
+ <path
+ style="fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.73778713px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 12.231207,229.93425 L 26.90235,234.95978 L 11.581307,241.07227 L 12.231207,229.93425 z "
+ id="path3782"
+ sodipodi:nodetypes="cccc" />
+ </g>
+</svg>
Added: trunk/gtk/unstable/mockups/wizard-look/tools-mockup.png
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/mockups/wizard-look…
==============================================================================
Binary file - no diff available.
Added: trunk/gtk/unstable/package/yast2-gtk-rpmlintrc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/package/yast2-gtk-r…
==============================================================================
--- trunk/gtk/unstable/package/yast2-gtk-rpmlintrc (added)
+++ trunk/gtk/unstable/package/yast2-gtk-rpmlintrc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,2 @@
+# yast2 likes a .so file for it's plugin that looks like a -devel pkg thing
+addFilter("devel-file-in-non-devel-package")
Added: trunk/gtk/unstable/package/yast2-gtk.changes
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/package/yast2-gtk.c…
==============================================================================
--- trunk/gtk/unstable/package/yast2-gtk.changes (added)
+++ trunk/gtk/unstable/package/yast2-gtk.changes Thu Nov 29 18:22:01 2007
@@ -0,0 +1,107 @@
+-------------------------------------------------------------------
+Wed Oct 6 15:32:01 BST 2007 - mmichael(a)suse.de
+
+- n#300750: big speedup wrt. search / sort
+
+-------------------------------------------------------------------
+Wed Aug 26 15:32:01 BST 2007 - mmichael(a)suse.de
+
+- n#300390: warn if cancelling a non-submitted transaction.
+
+-------------------------------------------------------------------
+Wed Aug 8 15:32:01 BST 2007 - mmichael(a)suse.de
+
+- #296945: pulse progress bar impl.
+
+-------------------------------------------------------------------
+Fri Aug 10 18:01:20 CEST 2007 - mvidner(a)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(a)suse.de
+
+- FaTE #302018: details on how to print the license
+- 2.15.8
+
+-------------------------------------------------------------------
+Wed Aug 8 09:22:32 CEST 2007 - mvidner(a)suse.cz
+
+- Don't build-require yast2-devel-doc.
+- 2.15.7.2
+
+-------------------------------------------------------------------
+Mon Aug 6 14:00:37 CEST 2007 - mvidner(a)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(a)suse.cz
+
+- removed yast2-devel from BuildRequires
+- 2.15.7
+
+-------------------------------------------------------------------
+Mon Jul 23 15:32:01 BST 2007 - mmichael(a)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(a)suse.cz
+
+- adapted to new libzypp
+- added support for translations
+- 2.15.5
+
+-------------------------------------------------------------------
+Thu Jun 21 10:24:55 CEST 2007 - mmichael(a)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(a)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(a)suse.de
+
+- upgrade to yast2-gtk-2.15.2, fixes upgrade.ycp
+
+-------------------------------------------------------------------
+Fri Mar 16 13:36:04 CET 2007 - mmichael(a)suse.de
+
+- upgrade to yast2-gtk-2.15.1, several fixes, including #247682, #247683
+
+-------------------------------------------------------------------
+Wed Feb 7 11:26:07 CET 2007 - mmichael(a)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(a)suse.de
+
+- added yast2-gtk-autogen.patch to fix build with latests yast2-devtools
+
+-------------------------------------------------------------------
+Mon Aug 28 11:34:13 CEST 2006 - cthiel(a)suse.de
+
+- fix build
+
+-------------------------------------------------------------------
+Wed Aug 23 18:20:30 CEST 2006 - mmichael(a)suse.de
+
+- import yast2-gtk into autobuild.
+
Added: trunk/gtk/unstable/src/.cvsignore
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/.cvsignore?rev=…
==============================================================================
--- trunk/gtk/unstable/src/.cvsignore (added)
+++ trunk/gtk/unstable/src/.cvsignore Thu Nov 29 18:22:01 2007
@@ -0,0 +1,7 @@
+Makefile.in
+Makefile
+*.lo
+*.la
+.libs
+.deps
+dummy
Added: trunk/gtk/unstable/src/Makefile
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/Makefile?rev=42…
==============================================================================
--- trunk/gtk/unstable/src/Makefile (added)
+++ trunk/gtk/unstable/src/Makefile Thu Nov 29 18:22:01 2007
@@ -0,0 +1,754 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# src/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+
+
+pkgdatadir = $(datadir)/yast2-gtk
+pkglibdir = $(libdir)/yast2-gtk
+pkgincludedir = $(includedir)/yast2-gtk
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = i686-suse-linux-gnu
+host_triplet = i686-suse-linux-gnu
+target_triplet = i686-suse-linux-gnu
+noinst_PROGRAMS = dummy$(EXEEXT)
+check_PROGRAMS = test$(EXEEXT)
+subdir = src
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(plugindir)"
+pluginLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libpy2gtk_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libpy2gtk_la_OBJECTS = Y2CCGtk.lo YGUtils.lo YGUI.lo YGDialog.lo \
+ YGLayout.lo YGWidget.lo YGLabel.lo YGPushButton.lo \
+ YGProgressBar.lo YGTextEntry.lo YGMultiLineEdit.lo \
+ YGIntField.lo YGRadioButton.lo YGImage.lo YGFrame.lo \
+ YGComboBox.lo YGTable.lo YGTree.lo YGMenuButton.lo \
+ YGBarGraph.lo YGDumbTab.lo YGWizard.lo YGTime.lo \
+ YGPackageSelector.lo ygtkratiobox.lo ygtkbargraph.lo \
+ ygtksteps.lo ygtkfieldentry.lo ygtkmenubutton.lo ygtkwizard.lo \
+ ygtkfindentry.lo ygdkmngloader.lo ygtkhtmlwrap.lo \
+ ygtkrichtext.lo yzyppwrapper.lo ygtkzyppwrapper.lo
+libpy2gtk_la_OBJECTS = $(am_libpy2gtk_la_OBJECTS)
+libpy2gtk_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libpy2gtk_la_LDFLAGS) $(LDFLAGS) -o $@
+PROGRAMS = $(noinst_PROGRAMS)
+am_dummy_OBJECTS = dummy.$(OBJEXT)
+dummy_OBJECTS = $(am_dummy_OBJECTS)
+dummy_DEPENDENCIES = libpy2gtk.la
+am_test_OBJECTS = test.$(OBJEXT)
+test_OBJECTS = $(am_test_OBJECTS)
+test_DEPENDENCIES = $(top_builddir)/src/$(plugin_LTLIBRARIES)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libpy2gtk_la_SOURCES) $(dummy_SOURCES) $(test_SOURCES)
+DIST_SOURCES = $(libpy2gtk_la_SOURCES) $(dummy_SOURCES) \
+ $(test_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/rick2/Documents/yast/gtk/unstable/missing --run aclocal-1.10
+AGENT_LIBADD = -L$(libdir) -lscr
+ALLOCA =
+AMTAR = ${SHELL} /home/rick2/Documents/yast/gtk/unstable/missing --run tar
+AR = ar
+AUTOCONF = ${SHELL} /home/rick2/Documents/yast/gtk/unstable/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/rick2/Documents/yast/gtk/unstable/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/rick2/Documents/yast/gtk/unstable/missing --run automake-1.10
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2 -Wall -Wformat=2 -Wmissing-prototypes
+CPP = gcc -E
+CPPFLAGS =
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 -Wall -Wformat=2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO = echo
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /usr/bin/grep -E
+EXEEXT =
+F77 =
+FFLAGS =
+GREP = /usr/bin/grep
+GTK_CFLAGS = -pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng12
+GTK_LIBS = -pthread -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lpango-1.0 -lcairo -lgmodule-2.0 -ldl -lgthread-2.0 -lrt -lgobject-2.0 -lglib-2.0
+INSTALL = /usr/bin/install -c -p
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS =
+LIBOBJS =
+LIBS =
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+LTLIBOBJS =
+MAINTAINER = Ricardo Cruz <rpmcruz(a)alunos.dcc.fc.up.pt> Michael Meeks <michael.meeks(a)novell.com>
+MAKEINFO = ${SHELL} /home/rick2/Documents/yast/gtk/unstable/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = yast2-gtk
+PACKAGE_BUGREPORT = http://bugs.opensuse.org/
+PACKAGE_NAME = yast2-gtk
+PACKAGE_STRING = yast2-gtk 2.15.9
+PACKAGE_TARNAME = yast2-gtk
+PACKAGE_VERSION = 2.15.9
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG_PATH =
+PYUI_LIBS = -lpy2UI
+RANLIB = ranlib
+RPMNAME = yast2-gtk
+SED = /usr/bin/sed
+SET_MAKE =
+SHELL = /bin/sh
+STRIP = strip
+STYLESHEET_CSS = /usr/share/YaST2/data/docbook/css/yast2docs.css
+STYLESHEET_HTML = /usr/share/YaST2/data/docbook/stylesheets/customize-html.xsl
+STYLESHEET_PDF = /usr/share/YaST2/data/docbook/stylesheets/customize-fo.xsl
+STYLESHEET_YCPDOC = /usr/share/YaST2/data/docbook/stylesheets/ycpdoc.xsl
+STYLESHEET_YDOC = /usr/share/YaST2/data/docbook/stylesheets/ydoc.xsl
+VERSION = 2.15.9
+XGETTEXT = /usr/bin/xgettext
+Y2DEVTOOLS_PREFIX = /usr
+YDOXYGEN = /usr/lib/YaST2/bin/ydoxygen
+ZYPP_CFLAGS =
+ZYPP_LIBS = -lzypp
+abs_builddir = /home/rick2/Documents/yast/gtk/unstable/src
+abs_srcdir = /home/rick2/Documents/yast/gtk/unstable/src
+abs_top_builddir = /home/rick2/Documents/yast/gtk/unstable
+abs_top_srcdir = /home/rick2/Documents/yast/gtk/unstable
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 =
+agentdir = ${prefix}/lib/YaST2/servers_non_y2
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = tar --format=ustar -chf - "$$tardir"
+am__untar = tar -xf -
+bindir = ${exec_prefix}/bin
+build = i686-suse-linux-gnu
+build_alias =
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = suse
+builddir = .
+clientdir = ${prefix}/share/YaST2/clients
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+desktopdir = ${prefix}/share/applications/YaST2
+docdir = ${prefix}/share/doc/packages/yast2-gtk
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+execcompdir = ${prefix}/lib/YaST2
+fillupdir = /var/adm/fillup-templates
+host = i686-suse-linux-gnu
+host_alias =
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = suse
+htmldir = ${docdir}
+imagedir = ${prefix}/share/YaST2/images
+includedir = ${prefix}/include/YaST2
+infodir = ${datarootdir}/info
+install_sh = $(SHELL) /home/rick2/Documents/yast/gtk/unstable/install-sh
+libdir = /usr/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${prefix}/share/YaST2/locale
+localstatedir = ${prefix}/var
+mandir = ${prefix}/share/man
+mkdir_p = /bin/mkdir -p
+moduledir = ${prefix}/share/YaST2/modules
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+pkgconfigdatadir = ${datadir}/pkgconfig
+pkgconfigdir = ${libdir}/pkgconfig
+plugindir = ${libdir}/YaST2/plugin
+potdir = ${docdir}/pot
+prefix = /usr
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+schemadir = ${prefix}/share/YaST2/schema
+scrconfdir = ${prefix}/share/YaST2/scrconf
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target = i686-suse-linux-gnu
+target_alias =
+target_cpu = i686
+target_os = linux-gnu
+target_vendor = suse
+themedir = ${prefix}/share/YaST2/theme
+top_builddir = ..
+top_srcdir = ..
+yast2dir = ${prefix}/share/YaST2
+ybindir = ${prefix}/lib/YaST2/bin
+ydatadir = ${prefix}/share/YaST2/data
+yncludedir = ${prefix}/share/YaST2/include
+ystartupdir = ${prefix}/lib/YaST2
+AM_CFLAGS = $(GTK_CFLAGS) \
+ -DTHEMEDIR=\"${themedir}/current\"
+
+AM_CXXFLAGS = $(GTK_CFLAGS) \
+ -DY2LOG=\"ui-gtk\" \
+ -DTHEMEDIR=\"${themedir}/current\"
+
+noinst_HEADERS = $(wildcard *.h)
+
+# plugin, libtool forces 'lib' prefix
+plugin_LTLIBRARIES = libpy2gtk.la
+libpy2gtk_la_LDFLAGS = -version-info 2:0
+libpy2gtk_la_LIBADD = -L$(plugindir) $(PYUI_LIBS) -L$(libdir) -lycp -ly2 \
+ $(GTK_LIBS) $(ZYPP_LIBS) $(GTKHTML_LIBS)
+
+libpy2gtk_la_SOURCES = \
+ Y2CCGtk.cc \
+ YGUtils.cc \
+ YGUI.cc \
+ YGDialog.cc \
+ YGLayout.cc \
+ YGWidget.cc \
+ YGLabel.cc \
+ YGPushButton.cc \
+ YGProgressBar.cc \
+ YGTextEntry.cc \
+ YGMultiLineEdit.cc \
+ YGIntField.cc \
+ YGRadioButton.cc \
+ YGImage.cc \
+ YGFrame.cc \
+ YGComboBox.cc \
+ YGTable.cc \
+ YGTree.cc \
+ YGMenuButton.cc \
+ YGBarGraph.cc \
+ YGDumbTab.cc \
+ YGWizard.cc \
+ YGTime.cc \
+ YGPackageSelector.cc \
+ ygtkratiobox.c \
+ ygtkbargraph.c \
+ ygtksteps.c \
+ ygtkfieldentry.c \
+ ygtkmenubutton.c \
+ ygtkwizard.c \
+ ygtkfindentry.c \
+ ygdkmngloader.c \
+ ygtkhtmlwrap.c \
+ ygtkrichtext.c \
+ yzyppwrapper.cc \
+ ygtkzyppwrapper.cc
+
+# should only append ygtkrichtext.c if USE_GTKHTML is set
+dummy_SOURCES = dummy.cc
+dummy_LDADD = libpy2gtk.la
+TESTS = $(check_PROGRAMS)
+test_SOURCES = test.cc
+test_LDADD = $(top_builddir)/src/$(plugin_LTLIBRARIES)
+INCLUDES = -I$(srcdir)/include -I$(includedir) -I$(includedir)/yui $(ZYPP_CFLAGS)
+EXTRA_DIST =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libpy2gtk.la: $(libpy2gtk_la_OBJECTS) $(libpy2gtk_la_DEPENDENCIES)
+ $(libpy2gtk_la_LINK) -rpath $(plugindir) $(libpy2gtk_la_OBJECTS) $(libpy2gtk_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+dummy$(EXEEXT): $(dummy_OBJECTS) $(dummy_DEPENDENCIES)
+ @rm -f dummy$(EXEEXT)
+ $(CXXLINK) $(dummy_OBJECTS) $(dummy_LDADD) $(LIBS)
+test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES)
+ @rm -f test$(EXEEXT)
+ $(CXXLINK) $(test_OBJECTS) $(test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/Y2CCGtk.Plo
+include ./$(DEPDIR)/YGBarGraph.Plo
+include ./$(DEPDIR)/YGComboBox.Plo
+include ./$(DEPDIR)/YGDialog.Plo
+include ./$(DEPDIR)/YGDumbTab.Plo
+include ./$(DEPDIR)/YGFrame.Plo
+include ./$(DEPDIR)/YGImage.Plo
+include ./$(DEPDIR)/YGIntField.Plo
+include ./$(DEPDIR)/YGLabel.Plo
+include ./$(DEPDIR)/YGLayout.Plo
+include ./$(DEPDIR)/YGMenuButton.Plo
+include ./$(DEPDIR)/YGMultiLineEdit.Plo
+include ./$(DEPDIR)/YGPackageSelector.Plo
+include ./$(DEPDIR)/YGProgressBar.Plo
+include ./$(DEPDIR)/YGPushButton.Plo
+include ./$(DEPDIR)/YGRadioButton.Plo
+include ./$(DEPDIR)/YGTable.Plo
+include ./$(DEPDIR)/YGTextEntry.Plo
+include ./$(DEPDIR)/YGTime.Plo
+include ./$(DEPDIR)/YGTree.Plo
+include ./$(DEPDIR)/YGUI.Plo
+include ./$(DEPDIR)/YGUtils.Plo
+include ./$(DEPDIR)/YGWidget.Plo
+include ./$(DEPDIR)/YGWizard.Plo
+include ./$(DEPDIR)/dummy.Po
+include ./$(DEPDIR)/test.Po
+include ./$(DEPDIR)/ygdkmngloader.Plo
+include ./$(DEPDIR)/ygtkbargraph.Plo
+include ./$(DEPDIR)/ygtkfieldentry.Plo
+include ./$(DEPDIR)/ygtkfindentry.Plo
+include ./$(DEPDIR)/ygtkhtmlwrap.Plo
+include ./$(DEPDIR)/ygtkmenubutton.Plo
+include ./$(DEPDIR)/ygtkratiobox.Plo
+include ./$(DEPDIR)/ygtkrichtext.Plo
+include ./$(DEPDIR)/ygtksteps.Plo
+include ./$(DEPDIR)/ygtkwizard.Plo
+include ./$(DEPDIR)/ygtkzyppwrapper.Plo
+include ./$(DEPDIR)/yzyppwrapper.Plo
+
+.c.o:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+# source='$<' object='$@' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(LTCOMPILE) -c -o $@ $<
+
+.cc.o:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+# source='$<' object='$@' libtool=yes \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstPROGRAMS clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Added: trunk/gtk/unstable/src/Makefile.am
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/Makefile.am?rev…
==============================================================================
--- trunk/gtk/unstable/src/Makefile.am (added)
+++ trunk/gtk/unstable/src/Makefile.am Thu Nov 29 18:22:01 2007
@@ -0,0 +1,69 @@
+AM_CFLAGS = $(GTK_CFLAGS) \
+ -DTHEMEDIR=\"${themedir}/current\"
+AM_CXXFLAGS = $(GTK_CFLAGS) \
+ -DY2LOG=\"ui-gtk\" \
+ -DTHEMEDIR=\"${themedir}/current\"
+
+noinst_HEADERS = $(wildcard *.h)
+
+# test linkage for missing symbols etc.
+noinst_PROGRAMS = dummy
+
+# plugin, libtool forces 'lib' prefix
+plugin_LTLIBRARIES = libpy2gtk.la
+
+libpy2gtk_la_LDFLAGS = -version-info 2:0
+libpy2gtk_la_LIBADD = -L$(plugindir) $(PYUI_LIBS) -L$(libdir) -lycp -ly2 \
+ $(GTK_LIBS) $(ZYPP_LIBS) $(GTKHTML_LIBS)
+libpy2gtk_la_SOURCES = \
+ Y2CCGtk.cc \
+ YGUtils.cc \
+ YGUI.cc \
+ YGDialog.cc \
+ YGLayout.cc \
+ YGWidget.cc \
+ YGLabel.cc \
+ YGPushButton.cc \
+ YGProgressBar.cc \
+ YGTextEntry.cc \
+ YGMultiLineEdit.cc \
+ YGIntField.cc \
+ YGRadioButton.cc \
+ YGImage.cc \
+ YGFrame.cc \
+ YGComboBox.cc \
+ YGTable.cc \
+ YGTree.cc \
+ YGMenuButton.cc \
+ YGBarGraph.cc \
+ YGDumbTab.cc \
+ YGWizard.cc \
+ YGTime.cc \
+ YGPackageSelector.cc \
+ ygtkratiobox.c \
+ ygtkbargraph.c \
+ ygtksteps.c \
+ ygtkfieldentry.c \
+ ygtkmenubutton.c \
+ ygtkwizard.c \
+ ygtkfindentry.c \
+ ygdkmngloader.c \
+ ygtkhtmlwrap.c \
+ ygtkrichtext.c \
+ yzyppwrapper.cc \
+ ygtkzyppwrapper.cc
+# should only append ygtkrichtext.c if USE_GTKHTML is set
+
+dummy_SOURCES = dummy.cc
+dummy_LDADD = libpy2gtk.la
+
+check_PROGRAMS = test
+TESTS = $(check_PROGRAMS)
+
+test_SOURCES = test.cc
+test_LDADD = $(top_builddir)/src/$(plugin_LTLIBRARIES)
+
+INCLUDES = -I$(srcdir)/include -I$(includedir) -I$(includedir)/yui $(ZYPP_CFLAGS)
+
+EXTRA_DIST =
+
Added: trunk/gtk/unstable/src/Makefile.in
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/Makefile.in?rev…
==============================================================================
--- trunk/gtk/unstable/src/Makefile.in (added)
+++ trunk/gtk/unstable/src/Makefile.in Thu Nov 29 18:22:01 2007
@@ -0,0 +1,754 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = dummy$(EXEEXT)
+check_PROGRAMS = test$(EXEEXT)
+subdir = src
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(plugindir)"
+pluginLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(plugin_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libpy2gtk_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libpy2gtk_la_OBJECTS = Y2CCGtk.lo YGUtils.lo YGUI.lo YGDialog.lo \
+ YGLayout.lo YGWidget.lo YGLabel.lo YGPushButton.lo \
+ YGProgressBar.lo YGTextEntry.lo YGMultiLineEdit.lo \
+ YGIntField.lo YGRadioButton.lo YGImage.lo YGFrame.lo \
+ YGComboBox.lo YGTable.lo YGTree.lo YGMenuButton.lo \
+ YGBarGraph.lo YGDumbTab.lo YGWizard.lo YGTime.lo \
+ YGPackageSelector.lo ygtkratiobox.lo ygtkbargraph.lo \
+ ygtksteps.lo ygtkfieldentry.lo ygtkmenubutton.lo ygtkwizard.lo \
+ ygtkfindentry.lo ygdkmngloader.lo ygtkhtmlwrap.lo \
+ ygtkrichtext.lo yzyppwrapper.lo ygtkzyppwrapper.lo
+libpy2gtk_la_OBJECTS = $(am_libpy2gtk_la_OBJECTS)
+libpy2gtk_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libpy2gtk_la_LDFLAGS) $(LDFLAGS) -o $@
+PROGRAMS = $(noinst_PROGRAMS)
+am_dummy_OBJECTS = dummy.$(OBJEXT)
+dummy_OBJECTS = $(am_dummy_OBJECTS)
+dummy_DEPENDENCIES = libpy2gtk.la
+am_test_OBJECTS = test.$(OBJEXT)
+test_OBJECTS = $(am_test_OBJECTS)
+test_DEPENDENCIES = $(top_builddir)/src/$(plugin_LTLIBRARIES)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libpy2gtk_la_SOURCES) $(dummy_SOURCES) $(test_SOURCES)
+DIST_SOURCES = $(libpy2gtk_la_SOURCES) $(dummy_SOURCES) \
+ $(test_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AGENT_LIBADD = @AGENT_LIBADD@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINTAINER = @MAINTAINER@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PYUI_LIBS = @PYUI_LIBS@
+RANLIB = @RANLIB@
+RPMNAME = @RPMNAME@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+STYLESHEET_CSS = @STYLESHEET_CSS@
+STYLESHEET_HTML = @STYLESHEET_HTML@
+STYLESHEET_PDF = @STYLESHEET_PDF@
+STYLESHEET_YCPDOC = @STYLESHEET_YCPDOC@
+STYLESHEET_YDOC = @STYLESHEET_YDOC@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+Y2DEVTOOLS_PREFIX = @Y2DEVTOOLS_PREFIX@
+YDOXYGEN = @YDOXYGEN@
+ZYPP_CFLAGS = @ZYPP_CFLAGS@
+ZYPP_LIBS = @ZYPP_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+agentdir = @agentdir@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+clientdir = @clientdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+desktopdir = @desktopdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+execcompdir = @execcompdir@
+fillupdir = @fillupdir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imagedir = @imagedir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdatadir = @pkgconfigdatadir@
+pkgconfigdir = @pkgconfigdir@
+plugindir = @plugindir@
+potdir = @potdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+schemadir = @schemadir@
+scrconfdir = @scrconfdir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+themedir = @themedir@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+yast2dir = @yast2dir@
+ybindir = @ybindir@
+ydatadir = @ydatadir@
+yncludedir = @yncludedir@
+ystartupdir = @ystartupdir@
+AM_CFLAGS = $(GTK_CFLAGS) \
+ -DTHEMEDIR=\"${themedir}/current\"
+
+AM_CXXFLAGS = $(GTK_CFLAGS) \
+ -DY2LOG=\"ui-gtk\" \
+ -DTHEMEDIR=\"${themedir}/current\"
+
+noinst_HEADERS = $(wildcard *.h)
+
+# plugin, libtool forces 'lib' prefix
+plugin_LTLIBRARIES = libpy2gtk.la
+libpy2gtk_la_LDFLAGS = -version-info 2:0
+libpy2gtk_la_LIBADD = -L$(plugindir) $(PYUI_LIBS) -L$(libdir) -lycp -ly2 \
+ $(GTK_LIBS) $(ZYPP_LIBS) $(GTKHTML_LIBS)
+
+libpy2gtk_la_SOURCES = \
+ Y2CCGtk.cc \
+ YGUtils.cc \
+ YGUI.cc \
+ YGDialog.cc \
+ YGLayout.cc \
+ YGWidget.cc \
+ YGLabel.cc \
+ YGPushButton.cc \
+ YGProgressBar.cc \
+ YGTextEntry.cc \
+ YGMultiLineEdit.cc \
+ YGIntField.cc \
+ YGRadioButton.cc \
+ YGImage.cc \
+ YGFrame.cc \
+ YGComboBox.cc \
+ YGTable.cc \
+ YGTree.cc \
+ YGMenuButton.cc \
+ YGBarGraph.cc \
+ YGDumbTab.cc \
+ YGWizard.cc \
+ YGTime.cc \
+ YGPackageSelector.cc \
+ ygtkratiobox.c \
+ ygtkbargraph.c \
+ ygtksteps.c \
+ ygtkfieldentry.c \
+ ygtkmenubutton.c \
+ ygtkwizard.c \
+ ygtkfindentry.c \
+ ygdkmngloader.c \
+ ygtkhtmlwrap.c \
+ ygtkrichtext.c \
+ yzyppwrapper.cc \
+ ygtkzyppwrapper.cc
+
+# should only append ygtkrichtext.c if USE_GTKHTML is set
+dummy_SOURCES = dummy.cc
+dummy_LDADD = libpy2gtk.la
+TESTS = $(check_PROGRAMS)
+test_SOURCES = test.cc
+test_LDADD = $(top_builddir)/src/$(plugin_LTLIBRARIES)
+INCLUDES = -I$(srcdir)/include -I$(includedir) -I$(includedir)/yui $(ZYPP_CFLAGS)
+EXTRA_DIST =
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(pluginLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(plugindir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$p"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libpy2gtk.la: $(libpy2gtk_la_OBJECTS) $(libpy2gtk_la_DEPENDENCIES)
+ $(libpy2gtk_la_LINK) -rpath $(plugindir) $(libpy2gtk_la_OBJECTS) $(libpy2gtk_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+dummy$(EXEEXT): $(dummy_OBJECTS) $(dummy_DEPENDENCIES)
+ @rm -f dummy$(EXEEXT)
+ $(CXXLINK) $(dummy_OBJECTS) $(dummy_LDADD) $(LIBS)
+test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES)
+ @rm -f test$(EXEEXT)
+ $(CXXLINK) $(test_OBJECTS) $(test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Y2CCGtk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGBarGraph.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGComboBox.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGDialog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGDumbTab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGFrame.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGImage.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGIntField.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGLabel.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGLayout.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGMenuButton.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGMultiLineEdit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGPackageSelector.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGProgressBar.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGPushButton.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGRadioButton.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGTable.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGTextEntry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGTime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGTree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGUI.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGUtils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGWidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/YGWizard.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygdkmngloader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkbargraph.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkfieldentry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkfindentry.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkhtmlwrap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkmenubutton.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkratiobox.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkrichtext.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtksteps.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkwizard.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ygtkzyppwrapper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yzyppwrapper.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstPROGRAMS clean-pluginLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pluginLTLIBRARIES \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-pluginLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Added: trunk/gtk/unstable/src/Y2CCGtk.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/Y2CCGtk.cc?rev=…
==============================================================================
--- trunk/gtk/unstable/src/Y2CCGtk.cc (added)
+++ trunk/gtk/unstable/src/Y2CCGtk.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,68 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <YGUI.h>
+#include <YUIComponent.h>
+#include <ycp/y2log.h>
+
+#if YAST2_VERSION >= 2015006
+// New UI plugin work
+# include <Y2CCUI.h>
+# define NEW_UI_PLUGIN
+# define Y2CCUI_INIT
+#else
+# define Y2CCUI Y2ComponentCreator
+# define Y2CCUI_INIT Y2ComponentBroker::BUILTIN
+#endif
+
+class YGUIComponent : public YUIComponent
+{
+public:
+
+ YGUIComponent() : YUIComponent() {}
+
+ virtual string name() const { return "gtk"; }
+
+ virtual YUI *createUI (int argc, char **argv,
+ bool with_threads, const char * macro_file)
+ {
+#ifdef IMPL_DEBUG
+ fprintf (stderr, "Create a gtk+ UI: %d '%s' !\n", with_threads, macro_file);
+#endif
+ return new YGUI (argc, argv, with_threads, macro_file);
+ }
+};
+
+class Y2CCGtk : public Y2CCUI
+{
+public:
+ Y2CCGtk () : Y2CCUI (Y2CCUI_INIT) { };
+
+ bool isServerCreator () const { return true; };
+
+ Y2Component *create (const char * name) const
+ {
+ y2milestone( "Creating %s component", name );
+ if (!strcmp (name, "gtk") ) {
+#ifdef NEW_UI_PLUGIN
+ Y2Component* ret = YUIComponent::uiComponent ();
+ if (!ret || ret->name () != name) {
+ y2debug ("UI component is %s, creating %s", ret? ret->name().c_str() : "NULL", name);
+ ret = new YGUIComponent();
+ }
+ return ret;
+#else
+ return new YGUIComponent();
+#endif
+ }
+ else
+ return 0;
+ }
+};
+
+// Singleton plugin registration instance.
+Y2CCGtk g_y2ccgtk;
+
+
Added: trunk/gtk/unstable/src/YGBarGraph.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGBarGraph.cc?r…
==============================================================================
--- trunk/gtk/unstable/src/YGBarGraph.cc (added)
+++ trunk/gtk/unstable/src/YGBarGraph.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,193 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+#include "ygtkbargraph.h"
+
+#include "YBarGraph.h"
+
+class YGBarGraph : public YBarGraph, public YGWidget
+{
+public:
+ YGBarGraph (const YWidgetOpt &opt, YGWidget *parent)
+ : YBarGraph (opt)
+ , YGWidget (this, parent, true, YGTK_TYPE_BAR_GRAPH, NULL)
+ { }
+
+ // YBarGraph
+ virtual void doUpdate()
+ {
+ ygtk_bar_graph_create_entries (YGTK_BAR_GRAPH (getWidget()), segments());
+ for (int i = 0; i < segments(); i++)
+ ygtk_bar_graph_setup_entry (YGTK_BAR_GRAPH (getWidget()), i,
+ label(i).c_str(), value(i));
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createBarGraph (YWidget *parent, YWidgetOpt &opt)
+{
+ return new YGBarGraph (opt, YGWidget::get (parent));
+}
+
+#include "YPartitionSplitter.h"
+
+class YGPartitionSplitter : public YPartitionSplitter, public YGWidget
+{
+public:
+ YGtkBarGraph *m_barGraph;
+ bool m_showDelta;
+ GtkWidget *m_scale, *m_free_spin, *m_new_spin;
+ string m_freeLabel, m_newPartLabel;
+
+ YGPartitionSplitter (const YWidgetOpt &opt, YGWidget *parent,
+ int _usedSize, int _totalFreeSize, int _newPartSize,
+ int _minNewPartSize, int _minFreeSize,
+ const YCPString &usedLabel, const YCPString &freeLabel,
+ const YCPString &newPartLabel, const YCPString &freeFieldLabel,
+ const YCPString &newPartFieldLabel)
+ : YPartitionSplitter (opt, _usedSize, _totalFreeSize, _newPartSize,
+ _minNewPartSize, _minFreeSize, usedLabel,
+ freeLabel, newPartLabel, freeFieldLabel,
+ newPartFieldLabel)
+ , YGWidget (this, parent, true, 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->value_cstr(),
+ usedSize());
+ m_freeLabel = freeLabel->value();
+ m_newPartLabel = newPartLabel->value();
+ // the others are setup-ed on SetValue()
+
+ /* Labels over the slider */
+ GtkWidget *labels_box, *free_label, *new_part_label;
+ labels_box = gtk_hbox_new (FALSE, 0);
+ free_label = gtk_label_new (freeFieldLabel->value_cstr());
+ new_part_label = gtk_label_new (newPartFieldLabel->value_cstr());
+ gtk_box_pack_start (GTK_BOX (labels_box), free_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (labels_box), new_part_label, FALSE, FALSE, 0);
+
+ /* Slider and the spinners */
+ m_showDelta = opt.countShowDelta.value();
+
+ GtkWidget *slider_box = gtk_hbox_new (FALSE, 0);
+ m_scale = gtk_hscale_new_with_range (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);
+
+ 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);
+
+ g_signal_connect (G_OBJECT (m_scale), "value-changed",
+ G_CALLBACK (scale_changed_cb), this);
+ g_signal_connect (G_OBJECT (m_free_spin), "value-changed",
+ G_CALLBACK (free_spin_changed_cb), this);
+ g_signal_connect (G_OBJECT (m_new_spin), "value-changed",
+ G_CALLBACK (new_spin_changed_cb), this);
+
+ /* Main layout */
+ gtk_box_pack_start (GTK_BOX (getWidget()), graph, TRUE, TRUE, 0);
+ 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 void setValue (int newValue)
+ {
+ IMPL
+ YPartitionSplitter::setValue (newValue);
+
+ ygtk_bar_graph_setup_entry (m_barGraph, 1, m_freeLabel.c_str(),
+ remainingFreeSize());
+ ygtk_bar_graph_setup_entry (m_barGraph, 2, m_newPartLabel.c_str(),
+ newPartSize());
+
+ // block connections
+ g_signal_handlers_block_by_func (m_scale,
+ (gpointer) scale_changed_cb, this);
+ g_signal_handlers_block_by_func (m_free_spin,
+ (gpointer) free_spin_changed_cb, this);
+ g_signal_handlers_block_by_func (m_new_spin,
+ (gpointer) new_spin_changed_cb, this);
+
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_free_spin),
+ remainingFreeSize());
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_new_spin),
+ newPartSize());
+ gtk_range_set_value (GTK_RANGE (m_scale), remainingFreeSize());
+
+ // unblock connections
+ g_signal_handlers_unblock_by_func (m_scale,
+ (gpointer) scale_changed_cb, this);
+ g_signal_handlers_unblock_by_func (m_free_spin,
+ (gpointer) free_spin_changed_cb, this);
+ g_signal_handlers_unblock_by_func (m_new_spin,
+ (gpointer) new_spin_changed_cb, this);
+ }
+
+ static void scale_changed_cb (GtkRange *range, YGPartitionSplitter *pThis)
+ {
+ IMPL
+ int newFreeSize = (int) gtk_range_get_value (range);
+ int newPartSize = pThis->totalFreeSize() - newFreeSize;
+ if (pThis->m_showDelta)
+ newPartSize += pThis->usedSize();
+
+ pThis->setValue (newPartSize);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void free_spin_changed_cb (GtkSpinButton *spin, YGPartitionSplitter *pThis)
+ {
+ IMPL
+ int newFreeSize = gtk_spin_button_get_value_as_int (spin);
+ int newPartSize = pThis->totalFreeSize() - newFreeSize;
+ if (pThis->m_showDelta)
+ newPartSize += pThis->usedSize();
+
+ pThis->setValue (newPartSize);
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ static void new_spin_changed_cb (GtkSpinButton *spin, YGPartitionSplitter *pThis)
+ {
+ IMPL
+ if (pThis->m_showDelta)
+ pThis->setValue (pThis->remainingFreeSize() - pThis->totalFreeSize());
+ else
+ pThis->setValue (gtk_spin_button_get_value_as_int (spin));
+ pThis->emitEvent (YEvent::ValueChanged);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createPartitionSplitter (YWidget *parent, YWidgetOpt &opt,
+ int usedSize, int totalFreeSize, int newPartSize,
+ int minNewPartSize, int minFreeSize,
+ const YCPString &usedLabel,const YCPString &freeLabel,
+ const YCPString &newPartLabel,
+ const YCPString &freeFieldLabel,
+ const YCPString &newPartFieldLabel)
+{
+ return new YGPartitionSplitter (opt, YGWidget::get (parent), usedSize,
+ totalFreeSize, newPartSize, minNewPartSize, minFreeSize, usedLabel,
+ freeLabel, newPartLabel, freeFieldLabel, newPartFieldLabel);
+}
Added: trunk/gtk/unstable/src/YGComboBox.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGComboBox.cc?r…
==============================================================================
--- trunk/gtk/unstable/src/YGComboBox.cc (added)
+++ trunk/gtk/unstable/src/YGComboBox.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,156 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YComboBox.h"
+#include "YGWidget.h"
+
+class YGComboBox : public YComboBox, public YGLabeledWidget
+{
+bool m_showingIcons;
+
+ public:
+ YGComboBox (const YWidgetOpt &opt, YGWidget *parent, YCPString label)
+ : YComboBox (opt, label)
+ , YGLabeledWidget (this, parent, label, YD_HORIZ, true,
+ opt.isEditable.value() ? GTK_TYPE_COMBO_BOX_ENTRY : GTK_TYPE_COMBO_BOX, NULL)
+ {
+ // pixbufs will be enabled if icons are provided
+ m_showingIcons = false;
+
+ GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, GDK_TYPE_PIXBUF);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (getWidget()), GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ if(opt.isEditable.value())
+ gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (getWidget()), 0);
+ else {
+ GtkCellRenderer* cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (getWidget()), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (getWidget()), cell,
+ "text", 0, NULL);
+ }
+
+ g_signal_connect (G_OBJECT (getWidget()), "changed",
+ G_CALLBACK (selected_changed_cb), this);
+ }
+
+ GtkComboBox *getComboBox() const
+ {
+ return GTK_COMBO_BOX ((const_cast<YGComboBox *>(this)->getWidget()));
+ }
+
+ GtkEntry *getEntry()
+ {
+ if (!GTK_IS_COMBO_BOX_ENTRY (getWidget())) {
+ y2error ("YGComboBox: trying to edit read-only combo box");
+ return NULL;
+ }
+
+ GtkWidget *entry = gtk_bin_get_child (GTK_BIN (getWidget()));
+ if (!GTK_IS_ENTRY (entry)) {
+ g_error ("YGComboBox: GtkComboBoxEntry doesn't have a GtkEntry as child");
+ return NULL;
+ }
+
+ return GTK_ENTRY (entry);
+ }
+
+ virtual void itemAdded (const YCPString &string, int index, bool selected)
+ {
+ GtkListStore *store = GTK_LIST_STORE (gtk_combo_box_get_model (getComboBox()));
+ GtkTreeIter iter;
+ gtk_list_store_insert (store, &iter, index);
+ gtk_list_store_set (store, &iter, 0, string->value_cstr(), -1);
+
+ if(hasIcons() && !m_showingIcons) {
+ 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", 1, NULL);
+ m_showingIcons = true;
+ }
+
+ if (hasIcons() && !itemIcon (index)->value().empty()) {
+ std::string path = itemIcon (index)->value();
+ if (path[0] != '/')
+ path = ICON_DIR + path;
+
+ GdkPixbuf *pixbuf;
+ GError *error = 0;
+ pixbuf = gdk_pixbuf_new_from_file (path.c_str(), &error);
+ if (!pixbuf)
+ y2warning ("YGComboBox: Could not load icon: %s.\n"
+ "Because %s", path.c_str(), error->message);
+ gtk_list_store_set (store, &iter, 1, pixbuf, -1);
+ }
+
+ if (selected || index == 0)
+ setCurrentItem (index);
+ }
+
+ virtual void setValue (const YCPString &value)
+ {
+ IMPL
+ gtk_entry_set_text (getEntry(), value->value_cstr());
+ }
+
+ virtual YCPString getValue() const
+ {
+ return YCPString (gtk_combo_box_get_active_text (getComboBox()));
+ }
+
+ virtual int getCurrentItem() const
+ {
+ return gtk_combo_box_get_active (getComboBox());
+ }
+
+ virtual void setCurrentItem (int index)
+ {
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) selected_changed_cb, this);
+ gtk_combo_box_set_active (GTK_COMBO_BOX(getWidget()), index);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) selected_changed_cb, this);
+ }
+
+ virtual void setInputMaxLength (const YCPInteger &numberOfChars)
+ {
+ gtk_entry_set_width_chars (getEntry(), numberOfChars->asInteger()->value());
+ }
+
+ // Events notifications
+ static void selected_changed_cb (GtkComboBox *widget, YGComboBox *pThis)
+ {
+ /* selected_changed_cb() is called when a new item was selected or the user has
+ typed some text on a writable ComboBox. text_changed is true for the later and
+ false for the former. */
+ bool text_changed = GTK_IS_COMBO_BOX_ENTRY (widget)
+ && pThis->getCurrentItem() == -1;
+
+ if (text_changed) {
+ g_signal_handlers_block_by_func (pThis->getWidget(), (gpointer)
+ selected_changed_cb, pThis);
+ YGUtils::filterText (GTK_EDITABLE (pThis->getEntry()), 0, -1,
+ pThis->getValidChars()->value_cstr());
+ g_signal_handlers_unblock_by_func (pThis->getWidget(), (gpointer)
+ selected_changed_cb, pThis);
+
+ pThis->emitEvent (YEvent::ValueChanged, true, true);
+ }
+ else
+ pThis->emitEvent (YEvent::SelectionChanged, true, true);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN(YComboBox)
+};
+
+YWidget *
+YGUI::createComboBox (YWidget *parent, YWidgetOpt & opt,
+ const YCPString & label)
+{
+ return new YGComboBox (opt, YGWidget::get (parent), label);
+}
Added: trunk/gtk/unstable/src/YGDialog.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGDialog.cc?rev…
==============================================================================
--- trunk/gtk/unstable/src/YGDialog.cc (added)
+++ trunk/gtk/unstable/src/YGDialog.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,379 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGDialog.h"
+#include <gdk/gdkkeysyms.h>
+#include <math.h> // easter
+
+/* In the main dialog case (when opt.hasDefaultSize is set), 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.
+*/
+
+class YGWindow;
+static YGWindow *main_window = NULL;
+
+YGWindow::~YGWindow()
+{
+ IMPL
+ setChild (NULL);
+ gtk_widget_destroy (m_widget);
+ g_object_unref (G_OBJECT (m_widget));
+}
+
+void YGWindow::setChild (YWidget *new_child)
+{
+ IMPL
+ 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;
+}
+
+void YGWindow::ref (YGWindow *window)
+{
+ window->m_refcount++;
+}
+void YGWindow::unref (YGWindow *window)
+{
+ if (--window->m_refcount == 0) {
+ bool is_main_window = (window == main_window);
+ delete window;
+ if (is_main_window)
+ main_window = NULL;
+ }
+}
+
+static gboolean draw_border_cb (GtkWidget *widget, GdkEventExpose *event,
+ YGWindow *pThis)
+{
+ IMPL
+ // to avoid background from overlapping, we emit the expose to the containee
+ // ourselves
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ gtk_bin_get_child (GTK_BIN (widget)),
+ event);
+
+ GtkAllocation *alloc = &widget->allocation;
+ gtk_draw_shadow (gtk_widget_get_style (widget), widget->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT,
+ alloc->x, alloc->y, alloc->width, alloc->height);
+ return TRUE;
+}
+
+static gboolean expode_window_timeout_cb (gpointer data)
+{
+ GtkWindow *window = YGUI::ui()->currentWindow();
+ if (!window)
+ return FALSE;
+ 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;
+}
+
+gboolean YGWindow::close_window_cb (GtkWidget *widget, GdkEvent *event,
+ YGWindow *pThis)
+{
+ IMPL
+ // never let GTK+ destroy the window! just inform YCP, and let it
+ // do its thing.
+ pThis->closeWindow();
+ return TRUE;
+}
+
+void YGWindow::closeWindow()
+{
+ if (!m_canClose || m_canClose (m_canCloseData))
+ YGUI::ui()->sendEvent (new YCancelEvent());
+}
+
+static gboolean key_pressed_cb (GtkWidget *widget, GdkEventKey *event,
+ YGWindow *pThis)
+{
+ IMPL
+ // if not main dialog, close it on escape
+ if (event->keyval == GDK_Escape &&
+ /* not main window */ main_window != pThis)
+ {
+ pThis->closeWindow();
+ 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)) {
+ y2milestone ("Caught YaST2 magic key combination");
+ 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:
+ y2milestone ("Starting xterm");
+ system ("/usr/bin/xterm &");
+ return TRUE;
+ case GDK_T:
+ dumpYastTree (pThis->getChild());
+ 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, NULL);
+ else {
+ g_source_remove (explode_timeout);
+ explode_timeout = 0;
+ }
+ return TRUE;
+ default:
+ break;
+ }
+ }
+ return FALSE;
+}
+
+YGWindow::YGWindow (bool main_window)
+{
+ m_widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_object_ref (G_OBJECT (m_widget));
+ gtk_object_sink (GTK_OBJECT (m_widget));
+
+ m_refcount = 0;
+ if (main_window)
+ ::main_window = this;
+ m_child = NULL;
+ m_canClose = NULL;
+
+ {
+ GtkWindow *parent = YGUI::ui()->currentWindow();
+ 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);
+ //gtk_window_set_focus_on_map (window, FALSE);
+ }
+ else {
+ gtk_window_set_title (window, "YaST");
+ if (YGUI::ui()->unsetBorder())
+ gtk_window_set_decorated (window, FALSE);
+ }
+
+ if (main_window) {
+ int w = YGUI::ui()->getDefaultSize (YD_HORIZ),
+ h = YGUI::ui()->getDefaultSize (YD_VERT);
+ gtk_window_set_default_size (window, w, h);
+ }
+
+ gtk_window_set_role (window, "yast-gtk");
+ if (!YGUI::ui()->hasWM())
+ g_signal_connect (G_OBJECT (m_widget), "expose-event",
+ G_CALLBACK (draw_border_cb), 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);
+}
+
+void YGWindow::setCloseCallback (YGWindowCloseFn canClose, void *canCloseData)
+{
+ m_canClose = canClose;
+ m_canCloseData = canCloseData;
+}
+
+void YGWindow::unsetCloseCallback()
+{
+ m_canClose = NULL;
+}
+
+YGDialog::YGDialog (YWidgetOpt &opt)
+ : YDialog (opt),
+ YGWidget (this, NULL, FALSE, GTK_TYPE_HBOX, NULL)
+{
+ setBorder (0);
+ m_padding = 0;
+ m_containee = gtk_event_box_new();
+ if (hasDefaultSize() && main_window)
+ m_window = main_window;
+ else
+ m_window = new YGWindow (hasDefaultSize());
+ YGWindow::ref (m_window);
+
+ if (hasWarnColor() || hasInfoColor()) {
+ // emulate a warning / info dialog
+ GtkWidget *icon = gtk_image_new_from_stock
+ (hasWarnColor() ? 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);
+
+ GtkRequisition req;
+ gtk_widget_size_request (icon, &req);
+ m_padding = req.width + 24;
+ }
+ 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::showWindow()
+{
+ IMPL
+ m_window->setChild (this);
+ gtk_widget_show (m_window->getWidget());
+ YGUI::ui()->busyCursor();
+}
+
+void YGDialog::hideWindow()
+{
+ IMPL
+ m_window->setChild (NULL);
+ gtk_widget_hide (m_window->getWidget());
+}
+
+YDialog *
+YGUI::createDialog (YWidgetOpt &opt)
+{
+ IMPL
+ return new YGDialog (opt);
+}
+
+static list <YGDialog *> dialogs_stack;
+
+void
+YGUI::showDialog (YDialog *_dialog)
+{
+ IMPL
+ YGDialog *dialog = static_cast <YGDialog *> (_dialog);
+ if (dialog->hasDefaultSize())
+ dialogs_stack.push_back (dialog);
+ dialog->showWindow();
+}
+
+void
+YGUI::closeDialog (YDialog *_dialog)
+{
+ IMPL
+ YGDialog *dialog = static_cast <YGDialog *> (_dialog);
+ if (dialog->hasDefaultSize()) {
+ dialogs_stack.pop_back();
+ if (!dialogs_stack.empty()) {
+ YGDialog *old_dialog = dialogs_stack.back();
+ old_dialog->showWindow();
+ }
+ else
+ dialog->hideWindow();
+ }
+ else
+ dialog->hideWindow();
+}
+
+GtkWindow *
+YGUI::currentWindow()
+{
+ YDialog *ydialog = YGUI::ui()->currentDialog();
+ if (ydialog)
+ return static_cast<YGDialog *>(ydialog)->getWindow();
+ else
+ return NULL;
+}
+
+YGDialog *
+YGUI::currentYGDialog()
+{
+ YDialog *ydialog = YGUI::ui()->currentDialog();
+ if (ydialog)
+ return static_cast<YGDialog *>(ydialog);
+ else
+ return NULL;
+}
+
+void YGDialog::busyCursor()
+{
+ // NOTE: GdkDisplay won't change for new dialogs, so we don't
+ // have to synchronize between them or something.
+ static GdkCursor *cursor = NULL;
+ if (!cursor) {
+ GdkDisplay *display = gtk_widget_get_display (m_window->getWidget());
+ cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+ }
+ gdk_window_set_cursor (m_window->getWidget()->window, cursor);
+}
+
+void YGDialog::normalCursor()
+{
+ gdk_window_set_cursor (m_window->getWidget()->window, NULL);
+}
+
Added: trunk/gtk/unstable/src/YGDialog.h
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGDialog.h?rev=…
==============================================================================
--- trunk/gtk/unstable/src/YGDialog.h (added)
+++ trunk/gtk/unstable/src/YGDialog.h Thu Nov 29 18:22:01 2007
@@ -0,0 +1,70 @@
+#ifndef YGDIALOG_H
+#define YGDIALOG_H
+
+#include "YGWidget.h"
+#include "YDialog.h"
+
+typedef bool (*YGWindowCloseFn) (void *closure);
+
+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;
+ YGWindowCloseFn m_canClose;
+ void *m_canCloseData;
+
+private:
+ static gboolean close_window_cb (GtkWidget *widget, GdkEvent *event,
+ YGWindow *pThis);
+public:
+ YGWindow (bool main_window);
+ ~YGWindow();
+ void setChild (YWidget *new_child);
+ static void ref (YGWindow *window);
+ static void unref (YGWindow *window);
+
+ void normalCursor();
+ void busyCursor();
+
+ void setCloseCallback (YGWindowCloseFn canClose, void *canCloseData);
+ void unsetCloseCallback();
+ void closeWindow();
+
+ // Y(G)Widget-like methods
+ GtkWidget *getWidget() { return m_widget; }
+ YWidget *getChild() { return m_child; }
+};
+
+class YGDialog : public YDialog, public YGWidget
+{
+ int m_padding;
+ GtkWidget *m_containee;
+
+ YGWindow *m_window;
+
+public:
+ YGDialog (YWidgetOpt &opt);
+ virtual ~YGDialog();
+ void showWindow();
+ void hideWindow();
+ GtkWindow *getWindow() { return GTK_WINDOW (m_window->getWidget()); }
+
+ void setCloseCallback (YGWindowCloseFn closeCallback, void *closeData)
+ { m_window->setCloseCallback (closeCallback, closeData); }
+ void unsetCloseCallback()
+ { m_window->unsetCloseCallback(); }
+
+ void normalCursor();
+ void busyCursor();
+
+ YGWIDGET_IMPL_COMMON
+
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (m_containee)
+};
+
+#endif // YGDIALOG_H
+
Added: trunk/gtk/unstable/src/YGDumbTab.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGDumbTab.cc?re…
==============================================================================
--- trunk/gtk/unstable/src/YGDumbTab.cc (added)
+++ trunk/gtk/unstable/src/YGDumbTab.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,118 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.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;
+ vector <GtkWidget *> m_tab_widgets;
+
+public:
+ YGDumbTab (const YWidgetOpt &opt, YGWidget *parent)
+ : YDumbTab (opt),
+ YGWidget (this, parent, true, GTK_TYPE_NOTEBOOK, NULL)
+ {
+ IMPL
+ m_containee = gtk_event_box_new();
+ gtk_widget_show (m_containee);
+ g_object_ref (G_OBJECT (m_containee));
+ gtk_object_sink (GTK_OBJECT (m_containee));
+
+ m_last_tab = 0;
+ // GTK+ keeps the notebook size set to the biggset page. We can't
+ // do this since this is dynamic, but at least don't let the notebook
+ // reduce its size.
+ ygtk_adj_size_set_only_expand (YGTK_ADJ_SIZE (m_adj_size), TRUE);
+
+ g_signal_connect (G_OBJECT (getWidget()), "switch-page",
+ G_CALLBACK (changed_tab_cb), this);
+ }
+
+ ~YGDumbTab()
+ {
+ IMPL
+ gtk_widget_destroy (m_containee);
+ g_object_unref (G_OBJECT (m_containee));
+ }
+
+ virtual void addTab (const YCPString &label_text)
+ {
+ IMPL
+ // the tab label
+ string str = YGUtils::mapKBAccel (label_text->value_cstr());
+ GtkWidget *label = gtk_label_new (str.c_str());
+ gtk_widget_show (label);
+
+ GtkNotebook *notebook = GTK_NOTEBOOK (getWidget());
+ g_signal_handlers_block_by_func (notebook, (gpointer) changed_tab_cb, this);
+
+ GtkWidget *empty = gtk_event_box_new();
+ gtk_widget_show (empty);
+
+ gtk_notebook_append_page (notebook, empty, label);
+ m_tab_widgets.push_back (empty);
+
+ if (!m_last_tab)
+ change_tab (0);
+
+ g_signal_handlers_unblock_by_func (notebook, (gpointer) changed_tab_cb, this);
+ }
+
+ // 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 change_tab (int tab_nb)
+ {
+ if (m_last_tab)
+ gtk_container_remove (GTK_CONTAINER (m_last_tab), m_containee);
+
+ GtkWidget *tab = m_tab_widgets [tab_nb];
+ gtk_container_add (GTK_CONTAINER (tab), m_containee);
+ m_last_tab = tab;
+ }
+
+ virtual int getSelectedTabIndex()
+ {
+ IMPL
+ return gtk_notebook_get_current_page (GTK_NOTEBOOK (getWidget()));
+ }
+
+ virtual void setSelectedTab (int index)
+ {
+ IMPL
+ change_tab (index);
+
+ g_signal_handlers_block_by_func (getWidget(), (gpointer) changed_tab_cb, this);
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (getWidget()), index);
+ g_signal_handlers_unblock_by_func (getWidget(), (gpointer) changed_tab_cb, this);
+ }
+
+ static void changed_tab_cb (GtkNotebook *notebook, GtkNotebookPage *page,
+ gint tab_nb, YGDumbTab *pThis)
+ {
+ YCPValue id = pThis->_tabs[tab_nb].id();
+ YGUI::ui()->sendEvent (new YMenuEvent (id));
+
+ pThis->change_tab (tab_nb);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (m_containee)
+};
+
+YWidget *
+YGUI::createDumbTab (YWidget *parent, YWidgetOpt &opt)
+{
+ IMPL
+ return new YGDumbTab (opt, YGWidget::get (parent));
+}
Added: trunk/gtk/unstable/src/YGFrame.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGFrame.cc?rev=…
==============================================================================
--- trunk/gtk/unstable/src/YGFrame.cc (added)
+++ trunk/gtk/unstable/src/YGFrame.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,171 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-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 15
+
+class YGBaseFrame : public YGWidget
+{
+protected:
+// a GtkAlignment to set some indentation on the child
+GtkWidget *m_containee;
+
+public:
+ YGBaseFrame (YWidget *y_widget, YGWidget *parent)
+ : YGWidget (y_widget, parent, true, GTK_TYPE_FRAME,
+ "shadow-type", GTK_SHADOW_NONE, NULL)
+ {
+ IMPL
+ m_containee = gtk_alignment_new (0, 0, 1, 1);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (m_containee), 0, 0, 15, 0);
+ gtk_widget_show (m_containee);
+ gtk_container_add (GTK_CONTAINER (getWidget()), m_containee);
+ }
+ virtual ~YGBaseFrame() {}
+};
+
+#include "YFrame.h"
+
+class YGFrame : public YFrame, public YGBaseFrame
+{
+public:
+ YGFrame (const YWidgetOpt &opt, YGWidget *parent, const YCPString &label)
+ : YFrame (opt, label),
+ YGBaseFrame (this, parent)
+ {
+ GtkWidget *label_widget = gtk_label_new ("");
+ YGUtils::setWidgetFont (GTK_WIDGET (label_widget), PANGO_WEIGHT_BOLD,
+ PANGO_SCALE_MEDIUM);
+ gtk_widget_show (label_widget);
+ gtk_frame_set_label_widget (GTK_FRAME (getWidget()), label_widget);
+ setLabel (label);
+ }
+
+ virtual ~YGFrame() {}
+
+ // YFrame
+ virtual void setLabel (const YCPString &_str)
+ {
+ IMPL
+ /* Get rid of mnemonics; make no sense here. */
+ const char *_cstr = _str->value_cstr();
+ size_t _clen = strlen (_cstr);
+
+ string str;
+ str.reserve (_clen);
+ for (size_t i = 0; i < _clen; i++)
+ if (_cstr[i] != '&')
+ str += _cstr[i];
+
+ GtkWidget *label = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ gtk_label_set_text (GTK_LABEL (label), str.c_str());
+
+ YFrame::setLabel (_str);
+ }
+
+ YGWIDGET_IMPL_COMMON
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YContainerWidget *
+YGUI::createFrame (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ IMPL
+ return new YGFrame (opt, YGWidget::get (parent), label);
+}
+
+#if YAST2_YGUI_CHECKBOX_FRAME
+#include "YCheckBoxFrame.h"
+
+class YGCheckBoxFrame : public YCheckBoxFrame, public YGBaseFrame
+{
+public:
+ YGCheckBoxFrame (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &label, bool checked)
+ : YCheckBoxFrame (opt, label),
+ YGBaseFrame (this, parent)
+ {
+ IMPL
+ GtkWidget *button = gtk_check_button_new_with_mnemonic("");
+ YGUtils::setWidgetFont (GTK_WIDGET (button), PANGO_WEIGHT_BOLD,
+ PANGO_SCALE_MEDIUM);
+ gtk_widget_show_all (button);
+ gtk_frame_set_label_widget (GTK_FRAME (getWidget()), button);
+
+ setLabel (label);
+ setValue (checked);
+ g_signal_connect (G_OBJECT (button), "toggled",
+ G_CALLBACK (toggled_cb), this);
+ }
+ virtual ~YGCheckBoxFrame() {}
+
+ // YCheckBoxFrame
+ virtual void setLabel (const YCPString &_str)
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ GtkLabel *label = GTK_LABEL (GTK_BIN (button)->child);
+
+ string str (YGUtils::mapKBAccel (_str->value_cstr()));
+ gtk_label_set_text_with_mnemonic (label, str.c_str());
+ YCheckBoxFrame::setLabel (_str);
+ }
+
+ bool getValue()
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+ }
+
+ void setValue (bool newValue)
+ {
+ GtkWidget *button = gtk_frame_get_label_widget (GTK_FRAME (getWidget()));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), newValue);
+ }
+
+ virtual void setEnabling (bool enabled)
+ {
+ GtkWidget *frame = getWidget();
+ if (enabled)
+ {
+ gtk_widget_set_sensitive (frame, TRUE);
+ handleChildrenEnablement (getValue());
+ }
+ else
+ {
+ setChildrenEnabling( false );
+ gtk_widget_set_sensitive (frame, FALSE);
+ }
+ }
+
+ YGWIDGET_IMPL_CHILD_ADDED (m_containee)
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+
+private:
+ static void toggled_cb (GtkWidget *widget, YGCheckBoxFrame *pThis)
+ {
+ pThis->setEnabling (true);
+ if (pThis->getNotify())
+ YGUI::ui()->sendEvent (new YWidgetEvent (pThis, YEvent::ValueChanged));
+ }
+};
+
+YContainerWidget *
+YGUI::createCheckBoxFrame (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label, bool checked)
+{
+ IMPL
+ return new YGCheckBoxFrame (opt, YGWidget::get (parent), label, checked);
+}
+
+#else
+# warning "Not compiling CheckBoxFrame..."
+#endif /*YAST2_YGUI_CHECKBOX_FRAME*/
Added: trunk/gtk/unstable/src/YGImage.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGImage.cc?rev=…
==============================================================================
--- trunk/gtk/unstable/src/YGImage.cc (added)
+++ trunk/gtk/unstable/src/YGImage.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,287 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include "ygdkmngloader.h"
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YEvent.h"
+#include "YGWidget.h"
+#include "YImage.h"
+
+class YGImage : public YImage, public YGWidget
+{
+ bool m_hasZeroWidth, m_hasZeroHeight, m_isScaled, m_isTiled, m_isAnimation;
+ bool m_imageLoaded;
+
+ struct Animation {
+ GdkPixbufAnimation *pixbuf;
+ GdkPixbufAnimationIter *frame;
+ guint timeout_id;
+ };
+ union {
+ GdkPixbuf *m_pixbuf;
+ Animation *m_animation;
+ };
+ gchar *alt_text;
+
+ void initOptions (const YWidgetOpt &opt)
+ {
+ IMPL
+ m_imageLoaded = false;
+ m_hasZeroWidth = opt.zeroWidth.value();
+ m_hasZeroHeight = opt.zeroHeight.value();
+ m_isAnimation = opt.animated.value();
+ m_isScaled = opt.scaleToFit.value();
+ m_isTiled = opt.tiled.value();
+
+ if (m_hasZeroWidth || m_isScaled || m_isTiled)
+ setStretchable (YD_HORIZ, true);
+ if (m_hasZeroHeight || m_isScaled || m_isTiled)
+ setStretchable (YD_VERT, true);
+
+ if (m_isScaled && m_isTiled) {
+ y2warning ("YImage can't be scaled and tiled at the same time");
+ m_isTiled = false;
+ }
+
+ if (m_isAnimation)
+ m_animation = NULL;
+ else
+ m_pixbuf = NULL;
+
+ g_signal_connect (G_OBJECT (getWidget()), "expose-event",
+ G_CALLBACK (expose_event_cb), this);
+ gtk_widget_queue_draw (getWidget());
+ }
+
+ void loadImage (GdkPixbuf *pixbuf, const char *error_msg)
+ {
+ IMPL
+ if (pixbuf == NULL) {
+ g_warning ("Couldn't load image - %s", error_msg);
+ return;
+ }
+
+ m_imageLoaded = true;
+ m_pixbuf = pixbuf;
+ gtk_widget_set_size_request (getWidget(), m_hasZeroWidth ? -1 : gdk_pixbuf_get_width (pixbuf),
+ m_hasZeroHeight ? -1 : gdk_pixbuf_get_height (pixbuf));
+ }
+
+ void loadAnimation (GdkPixbufAnimation *pixbuf, const char *error_msg)
+ {
+ IMPL
+ if (pixbuf == NULL) {
+ g_warning ("Couldn't load animation - %s", error_msg);
+ return;
+ }
+
+ m_imageLoaded = true;
+ m_animation = new Animation;
+ m_animation->pixbuf = pixbuf;
+
+ m_animation->frame = NULL;
+ advance_frame_cb (this);
+
+ g_signal_connect (G_OBJECT (getWidget()), "expose-event",
+ G_CALLBACK (expose_event_cb), this);
+ gtk_widget_queue_draw (getWidget());
+ }
+
+public:
+ YGImage (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPString &filename_str, const YCPString &text)
+ : YImage (opt),
+ YGWidget (this, parent, true, GTK_TYPE_DRAWING_AREA, NULL)
+ {
+ IMPL
+ alt_text = g_strdup (text->value_cstr());
+ initOptions (opt);
+
+ const char *filename = filename_str->value_cstr();
+ GError *error = 0;
+ if (m_isAnimation) {
+ GdkPixbufAnimation *pixbuf;
+ if (ygdk_mng_pixbuf_is_file_mng (filename))
+ pixbuf = ygdk_mng_pixbuf_new_from_file (filename, &error);
+ else
+ pixbuf = gdk_pixbuf_animation_new_from_file (filename, &error);
+ loadAnimation (pixbuf, error ? error->message : "(undefined)");
+ }
+ else {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
+ loadImage (pixbuf, error ? error->message : "(undefined)");
+ }
+ }
+
+ YGImage (const YWidgetOpt &opt, YGWidget *parent,
+ const YCPByteblock &byteblock, const YCPString &text)
+ : YImage (opt),
+ YGWidget (this, parent, true, GTK_TYPE_DRAWING_AREA, NULL)
+ {
+ IMPL
+ alt_text = g_strdup (text->value_cstr());
+ initOptions (opt);
+
+ GError *error = 0;
+ if (m_isAnimation && ygdk_mng_pixbuf_is_data_mng (byteblock->value(), byteblock->size()))
+ {
+ GdkPixbufAnimation *pixbuf;
+ pixbuf = ygdk_mng_pixbuf_new_from_data (byteblock->value(), byteblock->size(), &error);
+ loadAnimation (pixbuf, error ? error->message : "(undefined)");
+ }
+ else
+ {
+ GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
+ g_signal_connect (G_OBJECT (loader), "area-prepared",
+ G_CALLBACK (image_loaded_cb), this);
+
+ if (!gdk_pixbuf_loader_write (loader,
+ byteblock->value(), byteblock->size(), &error))
+ g_warning ("Could not load image from data blocks: %s", error->message);
+ gdk_pixbuf_loader_close (loader, &error);
+ }
+ }
+
+ virtual ~YGImage()
+ {
+ IMPL
+ if (m_imageLoaded) {
+ if (m_isAnimation) {
+ g_object_unref (G_OBJECT (m_animation->pixbuf));
+ if (m_animation->timeout_id)
+ g_source_remove (m_animation->timeout_id);
+ delete m_animation;
+ }
+ else
+ g_object_unref (G_OBJECT (m_pixbuf));
+ }
+ g_free (alt_text);
+ }
+
+ // callback for image loading
+ static void image_loaded_cb (GdkPixbufLoader *loader, YGImage *pThis)
+ {
+ IMPL
+ if (pThis->m_isAnimation) {
+ if (pThis->m_animation) {
+ // a new frame loaded -- just redraw the widget
+ if (gdk_pixbuf_animation_iter_on_currently_loading_frame
+ (pThis->m_animation->frame))
+ gtk_widget_queue_draw (pThis->getWidget());
+ }
+ else {
+ GdkPixbufAnimation *pixbuf = gdk_pixbuf_loader_get_animation (loader);
+ g_object_ref (G_OBJECT (pixbuf));
+ pThis->loadAnimation (pixbuf, " on block data reading callback");
+ }
+ }
+ else {
+ GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ g_object_ref (G_OBJECT (pixbuf));
+ pThis->loadImage (pixbuf, " on block data reading callback");
+ }
+ }
+
+ // callback for image displaying
+ static gboolean advance_frame_cb (void *pData)
+ {
+ IMPL
+ YGImage *pThis = (YGImage *) pData;
+ Animation *animation = pThis->m_animation;
+
+ if (!animation->frame) // no frame yet loaded
+ animation->frame = gdk_pixbuf_animation_get_iter (animation->pixbuf, NULL);
+ else
+ if (gdk_pixbuf_animation_iter_advance (animation->frame, NULL))
+ gtk_widget_queue_draw (pThis->getWidget());
+
+ // shedule next frame
+ int delay = gdk_pixbuf_animation_iter_get_delay_time (animation->frame);
+ if (delay != -1)
+ animation->timeout_id = g_timeout_add (delay, advance_frame_cb, pThis);
+
+ GdkPixbuf *pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (pThis->m_animation->frame);
+ gtk_widget_set_size_request (pThis->getWidget(), gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+ return FALSE;
+ }
+
+ static gboolean expose_event_cb (GtkWidget *widget, GdkEventExpose *event,
+ YGImage *pThis)
+ {
+ IMPL
+ int x, y, width, height;
+ x = widget->allocation.x + 6;
+ y = widget->allocation.y + 6;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+
+ cairo_t *cr = gdk_cairo_create (widget->window);
+
+ if (!pThis->m_imageLoaded) {
+ // show default text if no image was loaded
+ PangoLayout *layout;
+ layout = gtk_widget_create_pango_layout (widget, pThis->alt_text);
+
+ int text_width, text_height;
+ pango_layout_get_size (layout, &text_width, &text_height);
+ text_width /= PANGO_SCALE;
+ text_height /= PANGO_SCALE;
+
+ x += (width - text_width) / 2;
+ y += (height - text_height) / 2;
+
+ cairo_move_to (cr, x, y);
+ pango_cairo_show_layout (cr, layout);
+
+ g_object_unref (layout);
+ cairo_destroy (cr);
+ return TRUE;
+ }
+
+ GdkPixbuf *pixbuf;
+ if (pThis->m_isAnimation)
+ pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (pThis->m_animation->frame);
+ else
+ pixbuf = pThis->m_pixbuf;
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+
+ if (pThis->m_isTiled)
+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+
+ if (pThis->m_isScaled) {
+ double scale_x = (double) gdk_pixbuf_get_width (pixbuf) / width;
+ double scale_y = (double) gdk_pixbuf_get_height (pixbuf) / height;
+ cairo_matrix_t matrix;
+ cairo_matrix_init_scale (&matrix, scale_x, scale_y);
+ cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
+ }
+
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+ return TRUE;
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createImage (YWidget *parent, YWidgetOpt &opt,
+ YCPByteblock image_data, YCPString default_text)
+{
+ IMPL
+ return new YGImage (opt, YGWidget::get (parent), image_data, default_text);
+}
+
+YWidget *
+YGUI::createImage (YWidget *parent, YWidgetOpt &opt,
+ YCPString file_name, YCPString default_text)
+{
+ IMPL
+ return new YGImage (opt, YGWidget::get (parent), file_name, default_text);
+}
Added: trunk/gtk/unstable/src/YGIntField.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGIntField.cc?r…
==============================================================================
--- trunk/gtk/unstable/src/YGIntField.cc (added)
+++ trunk/gtk/unstable/src/YGIntField.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,152 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+#define SLIDER_NICESIZE_IN_CHARS 15
+
+class YGSpinBox : public YGLabeledWidget
+{
+ GtkWidget *m_spiner, *m_slider;
+
+public:
+ YGSpinBox (YWidget *y_widget, YGWidget *parent,
+ const YWidgetOpt &opt, const YCPString &label,
+ int minValue, int maxValue, int initialValue,
+ bool show_slider)
+ : YGLabeledWidget (y_widget, parent, label, YD_HORIZ, true,
+ GTK_TYPE_HBOX, 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), TRUE);
+ YGLabeledWidget::setBuddy (m_slider);
+ gtk_widget_set_size_request (m_slider,
+ YGUtils::getCharsWidth (m_slider, SLIDER_NICESIZE_IN_CHARS), -1);
+
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_slider, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (getWidget()), m_spiner, FALSE, FALSE, 5);
+ 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);
+ g_signal_connect (G_OBJECT (m_spiner), "value-changed",
+ G_CALLBACK (spiner_changed_cb), this);
+ if (m_slider)
+ g_signal_connect (G_OBJECT (m_slider), "value-changed",
+ G_CALLBACK (slider_changed_cb), this);
+ }
+
+ GtkSpinButton *getSpiner()
+ { return GTK_SPIN_BUTTON (m_spiner); }
+
+ bool useSlider()
+ { return m_slider != NULL; }
+ GtkHScale *getSlider()
+ { return GTK_HSCALE (m_slider); }
+
+ virtual void reportValue (int newValue) {}
+
+ void doSetValue (int newValue)
+ {
+ gtk_spin_button_set_value (getSpiner(), newValue);
+ if (useSlider())
+ gtk_range_set_value (GTK_RANGE (getSlider()), newValue);
+ }
+
+ // Events callbacks
+ static void spiner_changed_cb (GtkSpinButton *widget, YGSpinBox *pThis)
+ {
+ int newValue = gtk_spin_button_get_value_as_int (pThis->getSpiner());
+ pThis->reportValue (newValue);
+ if (pThis->useSlider())
+ gtk_range_set_value (GTK_RANGE (pThis->getSlider()), newValue);
+ 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_SET_VALUE_CHAIN(ParentClass) \
+ virtual void reportValue (int newValue) { \
+ ParentClass::setValue (newValue); \
+ } \
+ virtual void setValue (int newValue) { \
+ doSetValue (newValue); \
+ reportValue (newValue); \
+ }
+
+#include "YIntField.h"
+
+class YGIntField : public YIntField, public YGSpinBox
+{
+public:
+ YGIntField (const YWidgetOpt &opt, YGWidget *parent, const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+ : YIntField (opt, label, minValue, maxValue, initialValue)
+ , YGSpinBox (this, parent, opt, label, minValue, maxValue, initialValue, false)
+ { }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YIntField)
+ YGSPIN_BOX_IMPL_SET_VALUE_CHAIN (YIntField)
+};
+
+YWidget *
+YGUI::createIntField (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+{
+ IMPL
+ return new YGIntField (opt, YGWidget::get (parent), label,
+ minValue, maxValue, initialValue);
+}
+
+#include "YSlider.h"
+
+class YGSlider : public YSlider, public YGSpinBox
+{
+public:
+ YGSlider (const YWidgetOpt &opt, YGWidget *parent, const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+ : YSlider (opt, label, minValue, maxValue, initialValue)
+ , YGSpinBox (this, parent, opt, label, minValue, maxValue, initialValue, true)
+ { }
+
+ YGWIDGET_IMPL_COMMON
+ YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YSlider)
+ YGSPIN_BOX_IMPL_SET_VALUE_CHAIN (YSlider)
+};
+
+YWidget *
+YGUI::createSlider (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label,
+ int minValue, int maxValue, int initialValue)
+{
+ IMPL
+ return new YGSlider (opt, YGWidget::get (parent), label,
+ minValue, maxValue, initialValue);
+}
Added: trunk/gtk/unstable/src/YGLabel.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGLabel.cc?rev=…
==============================================================================
--- trunk/gtk/unstable/src/YGLabel.cc (added)
+++ trunk/gtk/unstable/src/YGLabel.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,97 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+#include "YLabel.h"
+
+class YGLabel : public YLabel, public YGWidget
+{
+public:
+ YGLabel (const YWidgetOpt &opt, YGWidget *parent, YCPString text)
+ : YLabel (opt, text),
+ YGWidget (this, parent, true, GTK_TYPE_LABEL, NULL)
+ {
+ IMPL
+ gtk_misc_set_alignment (GTK_MISC (getWidget()), 0.0, 0.5);
+ if (opt.isOutputField.value())
+ gtk_label_set_selectable (GTK_LABEL (getWidget()), TRUE);
+
+ if (opt.boldFont.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM);
+ if (opt.isHeading.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_ULTRABOLD, PANGO_SCALE_XX_LARGE);
+ setLabel (text);
+ }
+
+ virtual void setLabel (const YCPString &label)
+ {
+ gtk_label_set_label (GTK_LABEL (getWidget()), label->value_cstr());
+ YLabel::setLabel (label);
+
+ // Some YCP progs have no labeled labels cluttering the layout
+ label->value().empty() ? gtk_widget_hide (getWidget())
+ : gtk_widget_show (getWidget());
+ }
+
+ // YWidget
+ virtual bool doSetKeyboardFocus()
+ { return false; }
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createLabel (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &text)
+{
+ return new YGLabel (opt, YGWidget::get (parent), text);
+}
+
+#include "YColoredLabel.h"
+#include "ygtkbargraph.h"
+
+class YGColoredLabel : public YColoredLabel, public YGWidget
+{
+public:
+ YGColoredLabel (const YWidgetOpt &opt, YGWidget *parent, YCPString text,
+ const YColor &fgColor, const YColor &bgColor, int margin)
+ : YColoredLabel (opt, text),
+ YGWidget (this, parent, true, YGTK_TYPE_COLORED_LABEL, NULL)
+ {
+ IMPL
+ gtk_misc_set_alignment (GTK_MISC (getWidget()), 0.0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (getWidget()), margin, margin);
+
+ if (opt.boldFont.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_BOLD, PANGO_SCALE_MEDIUM);
+ if (opt.isHeading.value())
+ YGUtils::setWidgetFont (getWidget(), PANGO_WEIGHT_ULTRABOLD, PANGO_SCALE_XX_LARGE);
+ setLabel (text);
+
+ YGtkColoredLabel *color_label = YGTK_COLORED_LABEL (getWidget());
+ ygtk_colored_label_set_shadow_type (color_label, GTK_SHADOW_OUT);
+ ygtk_colored_label_set_foreground (color_label, fgColor.red, fgColor.green, fgColor.blue);
+ ygtk_colored_label_set_background (color_label, bgColor.red, bgColor.green, bgColor.blue);
+ }
+
+ virtual void setLabel (const YCPString &label)
+ {
+ gtk_label_set_label (GTK_LABEL (getWidget()), label->value_cstr());
+ YColoredLabel::setLabel (label);
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createColoredLabel (YWidget *parent, YWidgetOpt &opt, YCPString label,
+ YColor fgColor, YColor bgColor, int margin)
+{
+ return new YGColoredLabel (opt, YGWidget::get (parent), label,
+ fgColor, bgColor, margin);
+}
Added: trunk/gtk/unstable/src/YGLayout.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGLayout.cc?rev…
==============================================================================
--- trunk/gtk/unstable/src/YGLayout.cc (added)
+++ trunk/gtk/unstable/src/YGLayout.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,371 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGWidget.h"
+#include "YGUtils.h"
+
+#include "YSplit.h"
+#include "ygtkratiobox.h"
+#include "YSpacing.h"
+
+// GtkBox-like container (actually, more like our YGtkRatioBox)
+class YGSplit : public YSplit, public YGWidget
+{
+ // This group is meant to set all YGLabeledWidget with horizontal label
+ // to share the same width (if they belong to the same YSplit), so they
+ // look right
+ GtkSizeGroup *m_labels_group;
+
+public:
+ YGSplit (const YWidgetOpt &opt, YGWidget *parent, YUIDimension dim)
+ : YSplit (opt, dim),
+ YGWidget (this, parent, true,
+ dim == YD_HORIZ ? YGTK_TYPE_RATIO_HBOX
+ : YGTK_TYPE_RATIO_VBOX, NULL)
+ {
+ setBorder (0);
+ m_labels_group = NULL;
+ }
+
+ ~YGSplit()
+ {
+ if (m_labels_group)
+ g_object_unref (G_OBJECT (m_labels_group));
+ }
+
+ virtual void childAdded (YWidget *ychild)
+ {
+ IMPL
+ YGWidget *ygchild = YGWidget::get (ychild);
+
+ gtk_container_add (GTK_CONTAINER (getWidget()), ygchild->getLayout());
+ sync_stretchable (ychild);
+
+ // set labels of YGLabeledWidgets to the same width
+ // we have to do quite some work due to over-clutter on YCP progs
+ while (ychild) {
+ if (ychild->isContainer()) {
+ // try to see if there is a YGLabeledWidget at start
+ // (and ignore YSpacings)
+ YContainerWidget *container = (YContainerWidget *) ychild;
+ if (container->numChildren())
+ for (int i = 0; i < container->numChildren(); i++) {
+ ychild = container->child (i);
+ if (!dynamic_cast <YSpacing *> (ychild))
+ break;
+ }
+ else // no kids
+ break;
+ }
+ else {
+ ygchild = YGWidget::get (ychild);
+ YGLabeledWidget *labeled_child = dynamic_cast <YGLabeledWidget *> (ygchild);
+ if (labeled_child && labeled_child->orientation() == YD_HORIZ) {
+ if (!m_labels_group)
+ m_labels_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (m_labels_group,
+ labeled_child->getLabelWidget());
+ }
+ break;
+ }
+ }
+ }
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+
+ virtual void sync_stretchable (YWidget *ychild)
+ {
+ IMPL
+ YGtkRatioBox *box = YGTK_RATIO_BOX (getWidget());
+ YGWidget *child = YGWidget::get (ychild);
+
+ YUIDimension dim = dimension();
+ bool horiz_fill = child->isStretchable (YD_HORIZ)
+ || ychild->hasWeight (YD_HORIZ);
+ bool vert_fill = child->isStretchable (YD_VERT)
+ || ychild->hasWeight (YD_VERT);
+
+ ygtk_ratio_box_set_child_packing (box, child->getLayout(), ychild->weight (dim),
+ horiz_fill, vert_fill, 0);
+ ygtk_ratio_box_set_child_expand (box, child->getLayout(),
+ child->isStretchable (dim),
+ ychild->isLayoutStretch (dim));
+ YGWidget::sync_stretchable();
+ }
+
+ virtual void moveChild (YWidget *, long, long) {}; // ignore
+};
+
+YContainerWidget *
+YGUI::createSplit (YWidget *parent, YWidgetOpt &opt, YUIDimension dimension)
+{
+ IMPL
+ return new YGSplit (opt, YGWidget::get (parent), dimension);
+}
+
+#include "YAlignment.h"
+
+class YGAlignment : public YAlignment, public YGWidget
+{
+ GdkPixbuf *m_background_pixbuf;
+
+public:
+ YGAlignment (const YWidgetOpt &opt, YGWidget *parent,
+ YAlignmentType halign, YAlignmentType valign)
+ : YAlignment (opt, halign, valign),
+ YGWidget (this, parent, true, GTK_TYPE_ALIGNMENT, NULL)
+ {
+ setBorder (0);
+ m_background_pixbuf = 0;
+ }
+
+ virtual ~YGAlignment()
+ {
+ if (m_background_pixbuf)
+ g_object_unref (G_OBJECT (m_background_pixbuf));
+ }
+
+ virtual void childAdded (YWidget *ychild)
+ {
+ YGWidget *child = YGWidget::get (ychild);
+ gtk_container_add (GTK_CONTAINER (getWidget()), child->getLayout());
+
+ /* The padding is used for stuff like making YCP progs nicer for
+ yast-qt wizard, so it hurts us -- it's disabled. */
+ //child->setPadding (topMargin(), bottomMargin(),
+ // leftMargin(), rightMargin());
+ setMinSize (minWidth(), minHeight());
+
+ sync_stretchable (ychild); // alignment will be set here
+ }
+ YGWIDGET_IMPL_CHILD_REMOVED (m_widget)
+
+ virtual void sync_stretchable (YWidget *child)
+ {
+ IMPL
+ setAlignment (align [YD_HORIZ], align [YD_VERT]);
+ YGWidget::sync_stretchable (m_y_widget);
+ }
+
+ void setAlignment (YAlignmentType halign, YAlignmentType valign)
+ {
+ // special case (which YAlignment.cc also uses); let stretchable
+ // children stretch if opt.stretch is set (exploitable by the wizard)
+ GValue hstretch, vstretch;
+ hstretch = YGUtils::floatToGValue (0);
+ if (_stretch [YD_HORIZ] && YGWidget::get (child (0))->isStretchable (YD_HORIZ))
+ hstretch = YGUtils::floatToGValue (1);
+ vstretch = YGUtils::floatToGValue (0);
+ if (_stretch [YD_VERT] && YGWidget::get (child (0))->isStretchable (YD_VERT))
+ vstretch = YGUtils::floatToGValue (1);
+
+ if (halign != YAlignUnchanged) {
+ GValue xalign = YGUtils::floatToGValue (yToGtkAlign (halign));
+ g_object_set_property (G_OBJECT (getWidget()), "xalign", &xalign);
+ g_object_set_property (G_OBJECT (getWidget()), "xscale", &hstretch);
+ }
+ if (valign != YAlignUnchanged) {
+ GValue yalign = YGUtils::floatToGValue (yToGtkAlign (valign));
+ g_object_set_property (G_OBJECT (getWidget()), "yalign", &yalign);
+ g_object_set_property (G_OBJECT (getWidget()), "yscale", &vstretch);
+ }
+ }
+
+ void setPadding (int top, int bottom, int left, int right)
+ {
+ gtk_alignment_set_padding (GTK_ALIGNMENT (getWidget()),
+ top, bottom, left, right);
+ }
+
+ virtual void setBackgroundPixmap (string filename)
+ {
+ // YAlignment will prepend a path to the image
+ YAlignment::setBackgroundPixmap (filename);
+ 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;
+ }
+
+ virtual void moveChild (YWidget *, long, long) {}; // ignore
+
+ virtual string getDebugLabel() const
+ {
+ struct inner {
+ static const char *alignLabel (YAlignmentType align)
+ {
+ switch (align) {
+ case YAlignUnchanged:
+ return "unchanged";
+ case YAlignBegin:
+ return "begin";
+ case YAlignEnd:
+ return "end";
+ case YAlignCenter:
+ return "center";
+ }
+ return ""; /*not run*/
+ }
+ };
+
+ string str;
+ str += inner::alignLabel (align [YD_HORIZ]);
+ str += " x ";
+ str += inner::alignLabel (align [YD_VERT]);
+ return str;
+ }
+
+private:
+ // helper -- converts YWidget YAlignmentType to Gtk's align float
+ static float yToGtkAlign (YAlignmentType align)
+ {
+ switch (align) {
+ case YAlignBegin: return 0.0;
+ default:
+ case YAlignCenter: return 0.5;
+ case YAlignEnd: return 1.0;
+ }
+ }
+};
+
+YContainerWidget *
+YGUI::createAlignment (YWidget *parent, YWidgetOpt &opt,
+ YAlignmentType halign, YAlignmentType valign)
+{
+ IMPL
+ return new YGAlignment (opt, YGWidget::get (parent), halign, valign);
+}
+
+#include "YEmpty.h"
+
+// Just an empty space.
+class YGEmpty : public YEmpty, public YGWidget
+{
+public:
+ YGEmpty (const YWidgetOpt &opt, YGWidget *parent)
+ : YEmpty (opt),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+};
+
+YWidget *
+YGUI::createEmpty (YWidget *parent, YWidgetOpt &opt)
+{
+ IMPL
+ return new YGEmpty (opt, YGWidget::get (parent));
+}
+
+#include "YSpacing.h"
+
+// Empty space, with a fixed size.
+class YGSpacing : public YSpacing, public YGWidget
+{
+public:
+ YGSpacing (const YWidgetOpt &opt, YGWidget *parent,
+ float size, bool horizontal, bool vertical)
+ : YSpacing (opt, size, horizontal, vertical),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ gtk_widget_set_size_request (getWidget(), width(), height());
+ }
+};
+
+YWidget *
+YGUI::createSpacing (YWidget *parent, YWidgetOpt & opt, float size,
+ bool horiz, bool vert)
+{
+ IMPL
+ return new YGSpacing (opt, YGWidget::get (parent), size, horiz, vert);
+}
+
+#include "YReplacePoint.h"
+
+// an empty space that will get replaced
+class YGReplacePoint : public YReplacePoint, public YGWidget
+{
+public:
+ YGReplacePoint (const YWidgetOpt &opt, YGWidget *parent)
+ : YReplacePoint (opt),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CHILD_ADDED (getWidget())
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YContainerWidget *
+YGUI::createReplacePoint( YWidget *parent, YWidgetOpt & opt )
+{
+ IMPL
+ return new YGReplacePoint (opt, YGWidget::get (parent));
+}
+
+#include "YSquash.h"
+
+// 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 (const YWidgetOpt &opt, YGWidget *parent,
+ bool hsquash, bool vsquash)
+ : YSquash (opt, hsquash, vsquash),
+ YGWidget (this, parent, true, GTK_TYPE_EVENT_BOX, NULL)
+ {
+ setBorder (0);
+ }
+
+ YGWIDGET_IMPL_CHILD_ADDED (getWidget())
+ YGWIDGET_IMPL_CHILD_REMOVED (getWidget())
+};
+
+YContainerWidget *
+YGUI::createSquash (YWidget *parent, YWidgetOpt &opt,
+ bool hsquash, bool vsquash)
+{
+ IMPL
+ return new YGSquash (opt, YGWidget::get (parent), hsquash, vsquash);
+}
Added: trunk/gtk/unstable/src/YGMenuButton.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGMenuButton.cc…
==============================================================================
--- trunk/gtk/unstable/src/YGMenuButton.cc (added)
+++ trunk/gtk/unstable/src/YGMenuButton.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,79 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include "YGUtils.h"
+#include "YGWidget.h"
+#include "YMenuButton.h"
+#include "ygtkmenubutton.h"
+
+class YGMenuButton : public YMenuButton, public YGWidget
+{
+public:
+ YGMenuButton (const YWidgetOpt &opt,
+ YGWidget *parent,
+ YCPString label)
+ : YMenuButton (opt, label),
+ YGWidget (this, parent, true, YGTK_TYPE_MENU_BUTTON, NULL)
+ {
+ IMPL
+ setLabel (label);
+ }
+
+ virtual ~YGMenuButton() {}
+
+ // YMenuButton
+ virtual void setLabel (const YCPString &label)
+ {
+ IMPL
+ string str = YGUtils::mapKBAccel (label->value_cstr());
+ ygtk_menu_button_set_label (YGTK_MENU_BUTTON (getWidget()), str.c_str());
+ YMenuButton::setLabel (label);
+ }
+
+ // YMenuButton
+ virtual void createMenu()
+ {
+ GtkWidget *menu = doCreateMenu (getToplevelMenu()->itemList());
+ gtk_widget_show_all (menu);
+ ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (getWidget()), menu);
+ }
+
+ static GtkWidget* doCreateMenu (YMenuItemList &items)
+ {
+ GtkWidget *menu = gtk_menu_new();
+ for (YMenuItemListIterator it = items.begin(); it != items.end(); it++) {
+ GtkWidget *entry;
+ string str = YGUtils::mapKBAccel ((*it)->getLabel()->value_cstr());
+ entry = gtk_menu_item_new_with_mnemonic (str.c_str());
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), entry);
+
+ if ((*it)->hasChildren())
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (entry),
+ doCreateMenu ((*it)->itemList()));
+ else
+ g_signal_connect (G_OBJECT (entry), "activate",
+ G_CALLBACK (selected_item_cb), *it);
+ }
+
+ return menu;
+ }
+
+ static void selected_item_cb (GtkMenuItem *menuitem, YMenuItem *yitem)
+ {
+ YGUI::ui()->sendEvent (new YMenuEvent (yitem->getId()));
+ }
+
+ YGWIDGET_IMPL_COMMON
+};
+
+YWidget *
+YGUI::createMenuButton (YWidget *parent, YWidgetOpt &opt,
+ const YCPString &label)
+{
+ return new YGMenuButton (opt, YGWidget::get (parent), label);
+}
Added: trunk/gtk/unstable/src/YGMultiLineEdit.cc
URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/unstable/src/YGMultiLineEdit…
==============================================================================
--- trunk/gtk/unstable/src/YGMultiLineEdit.cc (added)
+++ trunk/gtk/unstable/src/YGMultiLineEdit.cc Thu Nov 29 18:22:01 2007
@@ -0,0 +1,390 @@
+/********************************************************************
+ * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
+ ********************************************************************/
+
+#include <config.h>
+#include <ycp/y2log.h>
+#include <YGUI.h>
+#include <string>
+#include "YGUtils.h"
+#include "YGWidget.h"
+
+class YGTextView : public YGScrolledWidget
+{
+int maxChars;
+
+public:
+ YGTextView (YWidget *y_widget, YGWidget *parent, const YWidgetOpt &opt,
+ const YCPString &label, const YCPString &text, bool editable)
+ : YGScrolledWidget (y_widget, parent, label, YD_VERT, true,
+ GTK_TYPE_TEXT_VIEW, "wrap-mode", GTK_WRAP_WORD, NULL)
+ {
+ IMPL
+ if (!opt.isShrinkable.value())
+ setMinSizeInChars (20, 10);
+ setPolicy (GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ maxChars = -1;
+ setText (text);
+
+ if (!editable)
+ {
+ gtk_text_view_set_editable (GTK_TEXT_VIEW (getWidget()), FALSE);
+ gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (getWidget()), FALSE);
+ }
+
+ g_signal_connect (G_OBJECT (getBuffer()), "changed",
+ G_CALLBACK (text_changed_cb), this);
+ }
+
+ GtkTextBuffer* getBuffer()
+ { return gtk_text_view_get_buffer (GTK_TEXT_VIEW (getWidget())); }
+
+ int getCharsNb()